一、打印 log
1.1 Framework Java
导入包:
import android.util.Log
定义,以 Log.v 为例:
/**
* 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.
* @return A positive value if the message was loggable (see {@link #isLoggable}).
*/
public static int v(@Nullable String tag, @NonNull String msg) {
return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
}
文件路径:/frameworks/base/core/java/android/util/Log.java。
1.2 Framework Native
导入头文件:
#include <log/log.h>
定义,以 ALOGV 为例:
/*
* Simplified macro to send a verbose log message using the current LOG_TAG.
*/
#ifndef ALOGV
#define __ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#if LOG_NDEBUG
#define ALOGV(...) \
do { \
__FAKE_USE_VA_ARGS(__VA_ARGS__); \
if (false) { \
__ALOGV(__VA_ARGS__); \
} \
} while (false)
#else
#define ALOGV(...) __ALOGV(__VA_ARGS__)
#endif
#endif
文件路径:/system/logging/liblog/*。
1.3 Kernel
通过 printk 函数。
二、打印 trace
2.1 Framework Java
导入包:
import android.os.Trace;
常用的方法有 beginSection 和 endSection 等。源码示例:
// /frameworks/base/core/java/android/view/View.java
public void layout(int l, int t, int r, int b) {
if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
if (isTraversalTracingEnabled()) {
Trace.beginSection(mTracingStrings.onMeasureBeforeLayout);
}
onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
if (isTraversalTracingEnabled()) {
Trace.endSection();
}
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
}
...
}
文件路径:/frameworks/base/core/java/android/os/Trace.java。
2.2 Framework Native
2.2.1 Trace.h
导入头文件:
#include <utils/Trace.h>
常用的有 ATRACE_CALL、ATRACE_NAME 和 ATRACE_INT 等。
文件路径:/system/core/libutils/include/utils/Trace.h 和 /system/core/libcutils/include/cutils/trace.h。
2.2.2 TraceUtils.h
导入头文件:
#include <gui/TraceUtils.h>
gui 下的 trace 工具主要提供了 ATRACE_FORMAT 函数,可以按照 printf 格式打印 trace。
文件路径:/frameworks/native/libs/gui/include/gui/TraceUtils.h。
三、打印堆栈
3.1 Framework Java
通过异常打印堆栈:
new Exception.printsStackTrace();
3.2 Framework Native
导入头文件:
#include <utils/callStack.h>
在 Android.bp 中添加库 libutilscallstack(大部分模块都已经包含):
shared_libs:[
"libutilscallstack",
]
用法:
android::callStack cs("TAG");
3.3 Kernel
3.3.1 dump_stack 函数
导入头文件:
#include <asm/ptrace.h>
用法:
dump_stack();
3.3.2 WARN_ON 函数
导入头文件:
#include<linux/kernel.h>
用法:
WARN_ON(condition);
四、常用系统接口
AOSP system 目录下是 Android 的底层库,多翻看这一部分代码可以发现很多方便的接口,这里当个个人记录。
4.1 获取系统属性
- 在 framework Java 层可以使用
SystemProperties类中的方法。 - 在 framework native 层可以使用
property_get相关函数,或者base::GetProperty相关函数。
4.2 读取文件
使用 ReadFdToString 可以将文件读取到字符串中。
五、解析堆栈
addr2line
使用 addr2line 工具可以解析 C/C++ 堆栈。addr2line 工具可以在 Android NDK 中可以找到,其路径取决于 NDK 版本,也可以使用构建时生成的 addr2line 可执行文件,其路径取决于构建时使用的编译配置。
我一般使用如下格式的命令:
llvm-addr2line -c -i -e $symbol -f $offset
oatdump
用于解析虚拟机生成的二进制文件,包括 odex/odx/ko 等文件。目前用得不多,后续可能会补充。