Android 日志系统

logcat 工作原理

Posted by LXG on December 3, 2019

Android logd日志原理-Gityuan

Android Log系统介绍-简书

框架

log_system

源码

基于Android源码7.1,解读logd的日志记录过程


frameworks/base/core/java/android/util/
    - Log.java
    - Slog.java
    - EventLog.java

frameworks/base/core/jni/android_util_Log.cpp

/system/core/logcat/logcat.cpp
/system/core/liblog/logd_write.c
/system/core/liblog/uio.c

/system/core/logd/
    - main.cpp
    - LogBuffer.cpp
    - LogStatistics.cpp

/system/core/libsysutils/src/SocketListener.cpp

Java

android/util/Log.java


public final class Log {

    public static native int println_native(int bufID,
            int priority, String tag, String msg);

    public static int d(String tag, String msg) {
        return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
    }

}

Jni

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 const JNINativeMethod gMethods[] = {
    /* name, signature, funcPtr */
    { "isLoggable",      "(Ljava/lang/String;I)Z", (void*) android_util_Log_isLoggable },
    { "println_native",  "(IILjava/lang/String;Ljava/lang/String;)I", (void*) android_util_Log_println_native },
    { "logger_entry_max_payload_native",  "()I", (void*) android_util_Log_logger_entry_max_payload_native },
};

liblog

system/core/liblog/

logger_write.c

logger_write.c


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;


LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
                                              const char *tag, const char *msg)
{
    ---------------------------------------------------------------------------------

    return write_to_log(bufID, vec, 3);
}


static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
{
    __android_log_lock();

    if (write_to_log == __write_to_log_init) {
        int ret;

        ret = __write_to_log_initialize();
        if (ret < 0) {
            __android_log_unlock();
            if (!list_empty(&__android_log_persist_write)) {
                __write_to_log_daemon(log_id, vec, nr);
            }
            return ret;
        }

        write_to_log = __write_to_log_daemon;
    }

    __android_log_unlock();

    return write_to_log(log_id, vec, nr);
}

/* log_init_lock assumed */
static int __write_to_log_initialize()
{

}


static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
{

}


config_write.c


LIBLOG_HIDDEN void __android_log_config_write() {
#if (FAKE_LOG_DEVICE == 0)
    extern struct android_log_transport_write logdLoggerWrite;
    extern struct android_log_transport_write pmsgLoggerWrite;

    __android_log_add_transport(&__android_log_transport_write, &logdLoggerWrite);
    __android_log_add_transport(&__android_log_persist_write, &pmsgLoggerWrite);
#else
    extern struct android_log_transport_write fakeLoggerWrite;

    __android_log_add_transport(&__android_log_transport_write, &fakeLoggerWrite);
#endif
}


log_write.c


static int logdAvailable(log_id_t LogId);
static int logdOpen();
static void logdClose();
static int logdWrite(log_id_t logId, struct timespec *ts,
                     struct iovec *vec, size_t nr);

LIBLOG_HIDDEN struct android_log_transport_write logdLoggerWrite = {
    .node = { &logdLoggerWrite.node, &logdLoggerWrite.node },
    .context.sock = -1,
    .name = "logd",
    .available = logdAvailable,
    .open = logdOpen,
    .close = logdClose,
    .write = logdWrite,
};

logd

system/core/logd

logd.rc


service logd /system/bin/logd
    socket logd stream 0666 logd logd
    socket logdr seqpacket 0666 logd logd
    socket logdw dgram 0222 logd logd
    group root system readproc
    writepid /dev/cpuset/system-background/tasks

service logd-reinit /system/bin/logd --reinit
    oneshot
    disabled
    writepid /dev/cpuset/system-background/tasks

logcat

system/core/logcat

总结

log_system_2