在android开发的过程中,需要查看log信息来帮助分析。那么知晓log的原理就是比较重要的了。
Framework 中的Log
Framework中的Log比较简单,主要就是封装接口,在接口中调用println_native函数。下面只以其中的一个进行分析。
public static int v(String tag, String msg) {
if (tag == null) {
tag = "NullTag";
}
if (msg == null) {
msg = "NullMsg";
}
return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
}
默认情况下,log id为main,这个ID的作用后面会提到。这个函数会检查tag & msg。之后就是调用println_native。
JNI中的Log
在JNI中的对应文件为:android_util_Log.cpp
static jint android_util_Log_println_native(JNIEnv* env, jobject clazz,
jint bufID, jint priority, jstring tagObj, jstring msgObj)
{
int res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);
}
在这里需要说明一下BufID & priority
typedef enum android_LogPriority {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT, // only for SetMinPriority()
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT, // only for SetMinPriority(); must be last
} android_LogPriority;
typedef enum {
LOG_ID_MAIN = 0,
LOG_ID_RADIO = 1,
LOG_ID_EVENTS = 2,
LOG_ID_SYSTEM = 3,
LOG_ID_MAX
} log_id_t;
上面对应的输入那种等级的打印信息。下面的对应打印哪种log。用过 logcat -b system/main/events/main来进行log输出。
int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
{
struct iovec vec[3];
char tmp_tag[32];
if (!tag)
tag = "";
//特殊处理radio的log
/* XXX: This needs to go! */
if ((bufID != LOG_ID_RADIO) &&
(!strcmp(tag, "HTC_RIL") ||
!strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
!strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
!strcmp(tag, "AT") ||
!strcmp(tag, "GSM") ||
!strcmp(tag, "STK") ||
!strcmp(tag, "CDMA") ||
!strcmp(tag, "PHONE") ||
!strcmp(tag, "SMS"))) {
bufID = LOG_ID_RADIO;
// Inform third party apps/ril/radio.. to use Rlog or RLOG
snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
tag = tmp_tag;
}
vec[0].iov_base = (unsigned char *) &prio;
vec[0].iov_len = 1;
vec[1].iov_base = (void *) tag;
vec[1].iov_len = strlen(tag) + 1;
vec[2].iov_base = (void *) msg;
vec[2].iov_len = strlen(msg) + 1;
return write_to_log(bufID, vec, 3);
}
这部分是使用linux中的iov的数据格式进行传递的。最后调用write_to_log函数,是一个函数指针。下面看一下这个函数的定义
static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __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<