综述:日志系统的实现流程
1、应用层应用程序:调用应用程序框架层的java接口,实际是java类的静态函数,android.util.Log(如Log.i());----------应用程序
2、应用框架层java接口:Log的静态方法如(v()、i()、e()),调用本层对应的JNI方法:如:println_native ------------java类Log jar包:system/framework/framework.jar
3、应用框架层JNI方法:调用运行库层的C接口:如__android_log_buf_write -C库:libandroid_runtime.so
4、运行库层C接口:通过设备文件类访问内核空间的Logger驱动程序:如write\read C库:liblog.so
5、驱动程序层:实现日志的操作 -C库:打包进内核
一、应用层android程序写日志
1、导入应用框架层接口类:import android.util.Log
2、调用类的静态函数Log.i(Info_Tag,"This a info log");
二、应用框架层android.util.Log
1、源文件、输出文件及编译方法
源文件:frameworks/base/core/java/android/util/Log.java
输出jar包:system/framework/framework.jar
编译方法:mmm framework/base
2、Log.java日志接口类文件概要说明
public final class Log { //final class: 当一个类声明为final,决定该类不能被继承,应用框架层接口类一般这样定义 //final data : 用于基本数据类型定义时,其值不可变,相当于定义常量 //public static 函数:静态函数,属于类,通过类来调用,接口函数一般这样定义 //定义了2~7一共6个日志优先级别ID,不同的级别调用不同的函数 public static final int VERBOSE = 2; public static final int DEBUG = 3; public static final int INFO = 4; public static final int WARN = 5; public static final int ERROR = 6; public static final int ASSERT = 7; //V优先级的接口函数 public static int v(String tag, String msg) { return println_native(LOG_ID_MAIN, VERBOSE, tag, msg); } public static int v(String tag, String msg, Throwable tr) { return println_native(LOG_ID_MAIN, VERBOSE, tag, msg + '\n' + getStackTraceString(tr)); } //d优先级的接口函数 public static int d(String tag, String msg) { return println_native(LOG_ID_MAIN, DEBUG, tag, msg); } public static int d(String tag, String msg, Throwable tr) { return println_native(LOG_ID_MAIN, DEBUG, tag, msg + '\n' + getStackTraceString(tr)); } //i优先级的接口函数 public static int i(String tag, String msg) { return println_native(LOG_ID_MAIN, INFO, tag, msg); } public static int i(String tag, String msg, Throwable tr) { return println_native(LOG_ID_MAIN, INFO, tag, msg + '\n' + getStackTraceString(tr)); } //w优先级的接口函数 public static int w(String tag, String msg) { return println_native(LOG_ID_MAIN, WARN, tag, msg); } public static int w(String tag, String msg, Throwable tr) { return println_native(LOG_ID_MAIN, WARN, tag, msg + '\n' + getStackTraceString(tr)); } //e优先级的接口函数 public static int e(String tag, String msg) { return println_native(LOG_ID_MAIN, ERROR, tag, msg); } public static int e(String tag, String msg, Throwable tr) { return println_native(LOG_ID_MAIN, ERROR, tag, msg + '\n' + getStackTraceString(tr)); } //日志类型ID,有四个日志类型,对应3个日志缓冲区设备文件,此处接口函数全用main日志缓冲区 /** @hide */ public static final int LOG_ID_MAIN = 0;//对应设备文件 dev/log/main /** @hide */ public static final int LOG_ID_RADIO = 1;//对应设备文件 dev/log/radio /** @hide */ public static final int LOG_ID_EVENTS = 2;//对应设备文件 dev/log/enents /** @hide */ public static final int LOG_ID_SYSTEM = 3;//对应设备文件 dev/log/main //声明了println_native本地方法,接口函数通过该方法写入日志 /** @hide */ public static native int println_native(int bufID,int priority, String tag, String msg); }
三、应用框架层JNI方法
1、源文件、输出文件及编译方法
源文件:frameworks/base/core/jni/android_util_Log.cpp
输出C库:system/lib/libandroid_runtime.so
编译方法:mmm frameworks/base/core/jni
2、jni方法分析
实现方法:
//android_util_Log对应android.util.Log类,有jni声明
static jint android_util_Log_println_native(...)
{...
__android_log_buf_write(...);//调用运行库的方法
....
}
定义方法表:
static JNINativeMethod gMethods[] = { .... { "println_native", "(IILjava/lang/String;Ljava/lang/String;)I", (void*) android_util_Log_println_native }, };
注册方法表:
int register_android_util_Log(JNIEnv* env) { .... return AndroidRuntime::registerNativeMethods(env, "android/util/Log", gMethods, NELEM(gMethods)); }
说明:在gMethods变量中,定义了println_native本地方法对应的函数调用是android_util_Log_println_native。在android_util_Log_println_native函数中,调用运行时库函数__android_log_buf_write来实现Log的写入操作
四、运行库层liblog.so
1、源文件、输出库及编译方法
源文件目录:system/core/liblog/,其中的logd_write.c这个文件实现_android_log_buf_write方法
输出库文件:system/lib/liblog.so
编译方法:mmm system/core/liblog
2、说明:运行库层函数通过标准的文件操作函数open read write和设备文件描述符fd通过操作系统调用日志驱动程序,从而实现日志的写入
五、Logger驱动程序
略