一,log是按照种类存储在不同的buffer中。
/** @hide */ public static final int LOG_ID_MAIN = 0; 用Log.v, Log.d, .... 输出 /** @hide */ public static final int LOG_ID_RADIO = 1; 用RLog.v, Log.d, .... 输出 /** @hide */ public static final int LOG_ID_EVENTS = 2; 用EventLog.writeEvent方法输出 /** @hide */ public static final int LOG_ID_SYSTEM = 3; 用SLog.v, Log.d, .... 输出 /** @hide */ public static final int LOG_ID_CRASH = 4; RuntimeInit.Clog_e方法和debuggerd应用中会使用
二,同一种log buffer中,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;
其中ASSERT是最高的log优先级,用在Log.wtf函数中。
(In Log.java)static int wtf(int logId, String tag, String msg, Throwable tr, boolean localStack, boolean system) { TerribleFailure what = new TerribleFailure(msg, tr); int bytes = println_native(logId, ASSERT, tag, msg + '\n' + getStackTraceString(localStack ? what : tr)); sWtfHandler.onTerribleFailure(tag, what, system); return bytes; }
(In Log.java)private static TerribleFailureHandler sWtfHandler = new TerribleFailureHandler() { public void onTerribleFailure(String tag, TerribleFailure what, boolean system) { RuntimeInit.wtf(tag, what, system); } };
(In RuntimeInit.java)public static voidwtf(String tag, Throwable t, boolean system) { try { if (ActivityManagerNative.getDefault().handleApplicationWtf( mApplicationObject, tag, system, new ApplicationErrorReport.CrashInfo(t))) { // The Activity Manager has already written us off -- now exit. Process.killProcess(Process.myPid()); System.exit(10); } } catch (Throwable t2) { Slog.e(TAG, "Error reporting WTF", t2); Slog.e(TAG, "Original WTF:", t); } }
三,利用system property动态调节log是否输出。
在调用Log类的输出函数之前,用isLoggable判断一下是否要输出
(In Log.java)public static native boolean isLoggable(String tag, int level);
(In Log.java)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;}
(In Log.java)static jboolean isLoggable(const char* tag, jint level) {
String8 key; key.append(LOG_NAMESPACE); key.append(tag); // 生成属性的名字,如"log.tag.ActivityManager" char buf[PROPERTY_VALUE_MAX]; if (property_get(key.string(), buf, "") <= 0) { // 获取指定的tag对应的log的最低输出level buf[0] = '\0'; } int logLevel = toLevel(buf); return logLevel >= 0 && level >= logLevel; // 如果要输出的level大于显示log的最低level,则返回true}
四,C++层的log。
要使用c++层的log,需要先定义LOG_TAG,如在android_util_Log.cpp文件中。
#define LOG_TAG "Log_println"
#include <utils/Log.h>
(In utils/Log.h)
#include <cutils/log.h>
(In cutils/log.h)
#include <log/log.h>
(In log/log.h)
#ifndef LOG_TAG #define LOG_TAG NULL #endif
#ifndef ALOGV #define __ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) #if LOG_NDEBUG #define ALOGV(...) do { if (0) { __ALOGV(__VA_ARGS__); } } while (0) // 输出log的宏定义,用于输出MAIN log,优先级为verbose,tag取自包含该log.h文件的文件中 #else #define ALOGV(...) __ALOGV(__VA_ARGS__) #endif #endif
#ifndef ALOG #define ALOG(priority, tag, ...) \ LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__) #endif /* * Log macro that allows you to specify a number for the priority. */ #ifndef LOG_PRI #define LOG_PRI(priority, tag, ...) \ android_printLog(priority, tag, __VA_ARGS__) #endif
类似的宏定义如下:
#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)
#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
#ifndef SLOGV #define __SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) #if LOG_NDEBUG #define SLOGV(...) do { if (0) { __SLOGV(__VA_ARGS__); } } while (0) #else #define SLOGV(...) __SLOGV(__VA_ARGS__) #endif #endif
#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
#ifndef RLOGV #define __RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) #if LOG_NDEBUG #define RLOGV(...) do { if (0) { __RLOGV(__VA_ARGS__); } } while (0) #else #define RLOGV(...) __RLOGV(__VA_ARGS__) #endif #endif
#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
五,其他的log使用情况。
public class LogWriter extends Writer { private void flushBuilder() { if (mBuilder.length() > 0) { Log.println_native(mBuffer, mPriority, mTag, mBuilder.toString()); mBuilder.delete(0, mBuilder.length()); } } }
public class LogPrinter implements Printer { public void println(String x) { Log.println_native(mBuffer, mPriority, mTag, x); } }
在binder中的使用:
class LogTextOutput : public BufferedTextOutput { public: LogTextOutput() : BufferedTextOutput(MULTITHREADED) { } virtual ~LogTextOutput() { }; protected: virtual status_t writeLines(const struct iovec& vec, size_t N) { //android_writevLog(&vec, N); <-- this is now a no-op if (N != 1) ALOGI("WARNING: writeLines N=%zu\n", N); ALOGI("%.*s", (int)vec.iov_len, (const char*) vec.iov_base); return NO_ERROR; } };
static LogTextOutput gLogTextOutput; // Android MAIN log, 优先级为Info static FdTextOutput gStdoutTextOutput(STDOUT_FILENO); // 输出到stdout static FdTextOutput gStderrTextOutput(STDERR_FILENO); // 输出到err 三个快捷方式 TextOutput& alog(gLogTextOutput); TextOutput& aout(gStdoutTextOutput); TextOutput& aerr(gStderrTextOutput);
