2.2、类android.util.Log的JNI实现
类android.util.Log有两个Native方法,它们通过JNI用c/c++中实现。
public static native boolean
isLoggable(String tag,
int
level);
public static native int
println_native(
int
bufID,int priority, String tag, String msg);
这两个方法是在
frameworks/base/core/jni/android_util_log.cpp
中实现的。这两个方法分别对应下列两个c/c++函数。
static jboolean
android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring tag,
jint
level)
static jint
android_util_Log_println_native(JNIEnv* env, jobject clazz,jint bufID, jint priority, jstring tagObj, jstring msgObj)
isLoggable()
的实现是比较<level>(来自参数)与当前property里设定的“log.tag.<tag>”(<tag>来自参数)的level值,大于或等于都是可记录的。程序实现片断如下:
// LOG_NAMESPACE : “log.tag.”
// chars: convert from param<tag>
strncpy(key, LOG_NAMESPACE, sizeof(LOG_NAMESPACE)-1);
strcpy(key + sizeof(LOG_NAMESPACE) - 1, chars);
//略
len = property_get(key, buf, "");
i
nt logLevel = toLevel(buf);
//略
return (logLevel >= 0 && level >= logLevel) ? true : false;
在
android_util.Log.cpp
中,
函数
android_util_Log_println_native()
调用了
Android_log_buf_write()
函数,而
Android_log_buf_write()
又直接调用了
system/core/liblog/logd_write.c
中的
__android_log_buf_write()
。在
文件
system/core/liblog/logd_write.c
中,
__android_log_buf_write()
组织了参数,又调用了
write_to_log
这个函数指针。
write_to_log
这个函数指针是实现的关键。
看
write_to_log
的定义:
static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
write_to_log
初始是指向
__write_to_log_init()
这个函数的。所以第一次执行write_to_log的时候是执行了
__write_to_log_init()
。而如果
write_to_log
不是第一次被执行,它已经在
__write_to_log_init()
里被修改指向了
__write_to_log_kernel()
。
先看
__write_to_log_init()
的实现:
static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
{
#ifdef HAVE_PTHREADS
pthread_mutex_lock(&log_init_lock);
#endif
if (write_to_log == __write_to_log_init) {
log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY);
write_to_log = __write_to_log_kernel;
if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 ||
log_fds[LOG_ID_EVENTS] < 0) {
log_close(log_fds[LOG_ID_MAIN]);
log_close(log_fds[LOG_ID_RADIO]);
log_close(log_fds[LOG_ID_EVENTS]);
log_fds[LOG_ID_MAIN] = -1;
log_fds[LOG_ID_RADIO] = -1;
log_fds[LOG_ID_EVENTS] = -1;
write_to_log = __write_to_log_null;
}
if (log_fds[LOG_ID_SYSTEM] < 0) {
log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
}
}
#ifdef HAVE_PTHREADS
pthread_mutex_unlock(&log_init_lock);
#endif
return
write_to_log(log_id, vec, nr);
}
如果是第一次调用(
write_to_log
还指向
__write_to_log_init()
),就打开相应的设备文件,获取描述符,并把
write_to_log
指向
__write_to_log_kernel()
。再在
__write_to_log_kernel()
中具体执行写入文件操作。
再看
__write_to_kernel()
的实现,基本就是写操作:
static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
{
ssize_t ret;
int log_fd;
if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
log_fd = log_fds[(int)log_id];
}
else {
return EBADF;
}
do {
ret = log_writev(log_fd, vec, nr);
}
while (ret < 0 && errno == EINTR);
return ret;
}