在 C++ 中添加堆栈日志
先在 Android.bp 中 添加 ‘libutilscallstack’
shared_libs:["liblog"," libutilscallstack"]
在想要打印堆栈的代码中添加
#include <utils/CallStack.h>
using android::CallStack;// 在函数中添加
int VisualizerLib_Create{CallStack stack(TAG);stack.update();
}
最后日志示例:
通过 堆栈日志,可以分析函数的调用路径。在代码跳转中了解整个调用逻辑。
系统库的源码位置
代码路径:android\system\core\libutils\include\utils\CallStack.h
// Collect/print the call stack (function, file, line) traces for a single thread.
class CallStack {
public:// Create an empty call stack. No-op.CallStack();// Create a callstack with the current thread's stack trace.// Immediately dump it to logcat using the given logtag.CallStack(const char* logtag, int32_t ignoreDepth = 1);~CallStack();// Reset the stack frames (same as creating an empty call stack).void clear() { mFrameLines.clear(); }// Immediately collect the stack traces for the specified thread.// The default is to dump the stack of the current call.void update(int32_t ignoreDepth = 1, pid_t tid = BACKTRACE_CURRENT_THREAD);// Dump a stack trace to the log using the supplied logtag.void log(const char* logtag,android_LogPriority priority = ANDROID_LOG_DEBUG,const char* prefix = nullptr) const;// Dump a stack trace to the specified file descriptor.void dump(int fd, int indent = 0, const char* prefix = nullptr) const;// Return a string (possibly very long) containing the complete stack trace.String8 toString(const char* prefix = nullptr) const;// Dump a serialized representation of the stack trace to the specified printer.void print(Printer& printer) const;// Get the count of stack frames that are in this call stack.size_t size() const { return mFrameLines.size(); }
在 C++ 中打开日志开关
#define LOG_NDEBUG 0
这里针对的是 所有 ALOGV 的日志开关,调试时需要打开上面的 define
如果只是针对联调日志,只想添加部分日志, 则加上 ALOGD 或 ALOGW 的日志
在 java 中添加日志
import android.util.Log;//
Exception e = new Exception("This is a log");
e.printStackTrace();//
Thread.currentThread().getStackTrace();//
Log.e(TAG , Log.getStackTraceString(new Throwable()));
打印日志示例:
06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): java.lang.Throwable
06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at com.android.server.telecom.CallAudioRouteStateMachine.setSpeakerphoneOn(CallAudioRouteStateMachine.java:1655)
06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at com.android.server.telecom.CallAudioRouteStateMachine.reinitialize(CallAudioRouteStateMachine.java:1898)
06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at com.android.server.telecom.CallAudioRouteStateMachine.access 2200 ( C a l l A u d i o R o u t e S t a t e M a c h i n e . j a v a : 73 ) 06 − 0416 : 19 : 29.648 D / C a l l A u d i o R o u t e S t a t e M a c h i n e ( 1070 ) : a t c o m . a n d r o i d . s e r v e r . t e l e c o m . C a l l A u d i o R o u t e S t a t e M a c h i n e 2200(CallAudioRouteStateMachine.java:73) 06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at com.android.server.telecom.CallAudioRouteStateMachine 2200(CallAudioRouteStateMachine.java:73)06−0416:19:29.648D/CallAudioRouteStateMachine(1070):atcom.android.server.telecom.CallAudioRouteStateMachineActiveSpeakerRoute.processMessage(CallAudioRouteStateMachine.java:1223)
06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at com.android.internal.util.StateMachine S m H a n d l e r . p r o c e s s M s g ( S t a t e M a c h i n e . j a v a : 993 ) 06 − 0416 : 19 : 29.648 D / C a l l A u d i o R o u t e S t a t e M a c h i n e ( 1070 ) : a t c o m . a n d r o i d . i n t e r n a l . u t i l . S t a t e M a c h i n e SmHandler.processMsg(StateMachine.java:993) 06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at com.android.internal.util.StateMachine SmHandler.processMsg(StateMachine.java:993)06−0416:19:29.648D/CallAudioRouteStateMachine(1070):atcom.android.internal.util.StateMachineSmHandler.handleMessage(StateMachine.java:810)
06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at android.os.Handler.dispatchMessage(Handler.java:106)
06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at android.os.Looper.loopOnce(Looper.java:201)
06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at android.os.Looper.loop(Looper.java:288)
06-04 16:19:29.648 D/CallAudioRouteStateMachine( 1070): at android.os.HandlerThread.run(HandlerThread.java:67)
附件: C++的宏定义打印格式
# 打印 bool 类型
bool doProcess = !mEffectCallback->isOffloadOrMmap() && !mEffectCallback->isOffloadOrDirect();ALOGD("doProcess: %s", doProcess ? "true" : "false"); //true:0 False:1ALOGW%s mEffects[%zu] name %s", __func__, i, mEffects[i]->desc().name);
//W/AudioFlinger::EffectChain( 862): process_l mEffects[0] name Visualizer// 测试某个函数的方法打印
ALOGD("----------%s---------",__func__);%d输出int型。
%zu输出size_t型。size_t在库中定义为unsigned int。
一个是整型,一个是无符号整型(无法打印负数)。
补充:如果%zu不能使用,可以用%u取代。%zu,%u不能输出负数。%@ 对象
%d, %i 整数
%u 无符整形
%f 浮点/双字
%x, %X 16进制整数
%x --- 一般的16进制的打印
%2x --- 要求打印2个16进制位,不够2个位的时候使用空格填充
%02x --- 要打印2个16进制位,不够2个位的时候使用0填充
%o 八进制整数
%zu size_t
%p 指针
%e 浮点/双字 (科学计算)
%g 浮点/双字
%s C 字符串
%.*s Pascal字符串
%c 字符
%C unichar
%lld 64位长整数(long long)
%llu 无符64位长整数
%Lf 64位双字
其他 格式的,请参考:
C语言中printf打印形式(%02X, %2X, %-2X, %.nf, %m.nf, %e, %m.ne, %2d, %-2d, %02d, %.2d)_printf %.2x-CSDN博客