Android 开发中 C++ 和Java 日志调试

发布于:2024-07-05 ⋅ 阅读:(17) ⋅ 点赞:(0)

在 C++ 中添加堆栈日志

先在 Android.bp 中 添加 ‘libutilscallstack’

 shared_libs:[
    "liblog",
 "	libutilscallstack"
 ]

在想要打印堆栈的代码中添加

#include <utils/CallStack.h>
using android::CallStack;

// 在函数中添加
int VisualizerLib_Create{
 CallStack stack(TAG);
 stack.update(); 
}

最后日志示例:
image.png

通过 堆栈日志,可以分析函数的调用路径。在代码跳转中了解整个调用逻辑。

系统库的源码位置

代码路径: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)060416: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)060416: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:1

 ALOGW%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博客


网站公告

今日签到

点亮在社区的每一天
去签到