When developing Android applications, you must use Log to monitor and debug program execution. In the previous article on Android Log system driver Logger source code analysis, we analyzed the source code of the driver Logger. in the previous article, we discussed the use of Log in Android system development, we also briefly introduce how to use Log in applications. In this article, we will introduce in detail the source code of the Log system at the Android Application Framework layer and system running inventory layer, this allows us to better understand the implementation of the Android log system.
In Android applications, we generally call the Java interface (android. util. log) to use the Log system. This Java interface uses the JNI method and the system Runtime Library to finally call the kernel driver Logger to write the Log to the kernel space. According to this call process, we will introduce the source code of the log system at the framework layer of the Android Application step by step. After learning this process, we can have a good understanding of the architecture of the Android system, that is, how the Application interface is called to use the kernel space step by step.
1. Implementation of the Java interface of the log system at the application framework layer.
In the article on Log usage in Android system development, we have introduced the source code interface of the Log system at the framework layer of Android applications. Here, we re-post this part of code to describe convenience and integrity of the article, in frameworks/base/core/java/android/util/Log. java interface for implementing the log system in the Java file:
[Color = amily: Consolas, 'courier]
[Java] view plaincopy
........................................ ........
Public final class 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;
........................................ .............
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 ));
}
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 ));
}
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 ));
}
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 ));
}
Public static int w (String tag, Throwable tr ){
Return println_native (LOG_ID_MAIN, WARN, tag, getStackTraceString (tr ));
}
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 ));
}
........................................ ..........................
/** @ Hide */public static native int LOG_ID_MAIN = 0;
/** @ Hide */public static native int LOG_ID_RADIO = 1;
/** @ Hide */public static native int LOG_ID_EVENTS = 2;
/** @ Hide */public static native int LOG_ID_SYSTEM = 3;
/** @ Hide */public static native int println_native (int bufID,
Int priority, String tag, String msg );
}
2 ~ 7 A total of 6 log priority IDs and 4 log buffer IDs. Recall the Android log system driver Logger source code analysis article. In the Logger driver module, three log buffers, log_main, log_events, and log_radio, are defined, three Device Files:/dev/log/main,/dev/log/events, And/dev/log/radio. The first three IDs of the four log buffers correspond to the file descriptors of these three device files. In the following section, we will see how these three file descriptors are created. In the downloaded Android kernel source code, the 4th log buffer LOG_ID_SYSTEM does not have a corresponding device file. In this case, it corresponds to the same buffer ID as LOG_ID_MAIN, in the following chapter, we can also see how these two IDs correspond to the same device file.
The println_native local method is declared in the most critical part of the Log interface. All Log interfaces call this local method to implement Log logging. Next we will continue to analyze the local method println_native.
2. Implementation of the JNI method of the log system at the application framework layer.
In the frameworks/base/core/jni/android_util_Log.cpp file, implement the JNI method println_native:
[Color = amily: Consolas, 'courier]
[Cpp] view plaincopy
/* // Device/libs/android_runtime/android_util_Log.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License ");
** You may not use this file except T in compliance with the License.
** You may obtain a copy of the License
**
** Http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** Distributed under the License is distributed on an "as is" BASIS,
** Without warranties or conditions of any kind, either express or implied.
** See the License for the specific language governing permissions and
** Limitations under the License.
*/
# Define LOG_NAMESPACE "log. tag ."
# Define LOG_TAG "Log_println"
# Include <assert. h>
# Include <cutils/properties. h>
# Include <utils/Log. h>
# Include <utils/String8.h>
# Include "jni. h"
# Include "utils/misc. h"
# Include "android_runtime/AndroidRuntime. h"
# Define MIN (a, B) (a <B )? A: B)
Namespace android {
Struct levels_t {
Jint verbose;
Jint debug;
Jint info;
Jint warn;
Jint error;
Jint assert;
};
Static levels_t levels;
Static int toLevel (const char * value)
{
Switch (value [0]) {
Case 'V': return levels. verbose;
Case 'D': return levels. debug;
Case 'I': return levels.info;
Case 'W': return levels. warn;
Case 'E': return levels. error;
Case 'A': return levels. assert;
Case's ': return-1; // SUPPRESS
}
Return levels.info;
}
Static jboolean android_util_Log_isLoggable (JNIEnv * env, jobject clazz, jstring tag, jint level)
{
# Ifndef HAVE_ANDROID_ OS
Return false;
# Else/* HAVE_ANDROID_ OS */
Int len;
Char key [PROPERTY_KEY_MAX];
Char buf [PROPERTY_VALUE_MAX];
If (tag = NULL ){
Return false;
}
Jboolean result = false;
Const char * chars = env-> GetStringUTFChars (tag, NULL );
If (strlen (chars) + sizeof (LOG_NAMESPACE)> PROPERTY_KEY_MAX ){
Jclass clazz = env-> FindClass ("java/lang/IllegalArgumentException ");
Char buf2 [200];
Snprintf (buf2, sizeof (buf2), "Log tag \" % s \ "exceeds limit of % d characters \ n ",
Chars, PROPERTY_KEY_MAX-sizeof (LOG_NAMESPACE ));
// Release the chars!
Env-> ReleaseStringUTFChars (tag, chars );
Env-> ThrowNew (clazz, buf2 );
Return false;
} Else {