基于Android N的Log机制浅析 上篇

本文探讨Android N的Log实现机制,主要关注从Java接口调用到与logd进程通信的过程。Log的输出通过logd模块完成,logd通过socket接收来自应用进程的Log请求。Log有不同的优先级,通过JNI调用进入liblog,最终通过socket传递给logd进行处理。
摘要由CSDN通过智能技术生成

写在前面

由于工作原因最近研究了一下Android的Log实现机制,在这里做一个记录,如果有理解不到位的地方也请各位大哥大姐们指点指点。以下涉及的代码均基于Android N。下面开始咯。


Android N中Log机制的总线:
Log的输出是由不同的进程发起的,但真正实现Log的输入与输出的是一个叫logd的模块,他是一个单独的native进程,当一个应用进程需要打印一条Log时,其实是通过socket与logd模块通信最终由logd来完成Log的处理工作的。

本系列文章计划按调用栈的顺序分上下两篇,上篇记录从java中调用常用的log打印接口后一直到连接到logd模块的过程。下篇详细记录logd中处理log信息的过程。

Log Priority

首先,在Android中输出的Log是有优先级的,如下所示列出了Android中Log的所有优先级:

    /**
     * Priority constant for the println method; use Log.v.
     */
    public static final int VERBOSE = 2;

    /**
     * Priority constant for the println method; use Log.d.
     */
    public static final int DEBUG = 3;

    /**
     * Priority constant for the println method; use Log.i.
     */
    public static final int INFO = 4;

    /**
     * Priority constant for the println method; use Log.w.
     */
    public static final int WARN = 5;

    /**
     * Priority constant for the println method; use Log.e.
     */
    public static final int ERROR = 6;

    /**
     * Priority constant for the println method.
     */
    public static final int ASSERT = 7;

Verbose优先级最低,跟着到Debug优先级依次提高,在这里看到的优先级最高的是Assert。后面会说到基于Log的优先级,提供了一套支持设置Log过滤的方法。

从调用开始

我们在平时开发过程中需要在程序中加入一些Log,这个自然大家都知道,Android中为我们提供了以下一些常用的接口实现Log的输出:

    /**
     * Send a {@link #VERBOSE} log message.
     * @param tag Used to identify the source of a log message.  It usually identifies
     *        the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static int v(String tag, String msg) {
        return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
    }

    /**
     * Send a {@link #DEBUG} log message.
     * @param tag Used to identify the source of a log message.  It usually identifies
     *        the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static int d(String tag, String msg) {
        return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
    }

    /**
     * Send an {@link #INFO} log message.
     * @param tag Used to identify the source of a log message.  It usually identifies
     *        the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static int i(String tag, String msg) {
        return println_native(LOG_ID_MAIN, INFO, tag, msg);
    }

    /**
     * Send a {@link #WARN} log message.
     * @param tag Used to identify the source of a log message.  It usually identifies
     *        the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static int w(String tag, String msg) {
        return println_native(LOG_ID_MAIN, WARN, tag, msg);
    }

    /**
     * Send an {@link #ERROR} log message.
     * @param tag Used to identify the source of a log message.  It usually identifies
     *        the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static int e(String tag, String msg) {
        return println_native(LOG_ID_MAIN, ERROR, tag, msg);
    }

    /** @hide */ public static native int println_native(int bufID,
            int priority, String tag, String msg);

这几个接口分别实现不同优先级的log的输出,可以看到他们内部都是通过一个native方法println_native实现的。这里需要注意的是println_native函数的第一个参数,它是一个整形,表示当前Log是往哪一个buffer里面去写,后面讲到logd时会看到这里的这个参数控制了我们输出的Log该往logd中的那一块buffer里面填充。println_native的实现在android_util_Log.cpp文件中:

/*
 * In class android.util.Log:
 *  public static native int println_native(int buffer, int priority, String tag, String msg)
 */
static jint android_util_Log_println_native(JNIEnv* env, jobject clazz,
        jint bufID, jint priority, jstring tagObj, jstring msgObj)
{
    const char* tag = NULL;
    const char* msg = NULL;

    if (msgObj == NULL) {
        jniThrowNullPointerException(env, "println needs a message");
        return -1;
    }

    if (bufID < 0 || bufID >= LOG_ID_MAX) {
        jniThrowNullPointerException(env, "bad bufID");
        return -1;
    }

    if (tagObj != NULL)
        tag = env->GetStringUTFChars(tagObj, NULL);
    msg = env->GetStringUTFChars(msgObj, NULL);

    int res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);

    if (tag != NULL)
        env->ReleaseStringUTFChars(tagObj, tag);
    env->ReleaseStringUTFChars(msgObj, msg);

    return res;
}

/*
 * JNI registration.
 */
static 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值