am trace-ipc使用小技巧之Binder服务端方法systrace打印剖析

48 阅读3分钟

背景

上一篇文章

Binder通讯如何打印client调用堆栈即systrace查看对应方法 已经介绍了Binder调用相关的堆栈打印还有在systrace下面也有相关的调用发起的binder的方法名字打印。

但是同时也有学员朋友提出相关的疑问

客户端展示详细跨进程方法 com.android.internal.app.IAppOpsServiceStubStubProxy.checkOperation 客户端有方法名字展示 但是服务端没有看到有详细方法展示在这里插入图片描述 正常应该是需要两端都有详细方法展示。

解决方法讲解

frameworks/base/core/java/android/os/Binder.java

private boolean execTransactInternal(int code, Parcel data, Parcel reply, int flags,
            int callingUid) {
        final boolean tagEnabled = Trace.isTagEnabled(Trace.TRACE_TAG_AIDL);
      
        final boolean tracingEnabled = tagEnabled && transactionTraceName != null;
        try {
        	
            if (tracingEnabled) {
            //这里有相关的traceBegin打印
                Trace.traceBegin(Trace.TRACE_TAG_AIDL, transactionTraceName);
            }

            // TODO - this logic should not be in Java - it should be in native
            // code in libbinder so that it works for all binder users. Further,
            // this should not re-use flags.
            if ((flags & FLAG_COLLECT_NOTED_APP_OPS) != 0 && callingUid != -1) {
                AppOpsManager.startNotedAppOpsCollection(callingUid);
                try {
                    res = onTransact(code, data, reply, flags);
                } finally {
                    AppOpsManager.finishNotedAppOpsCollection();
                }
            } else {
                res = onTransact(code, data, reply, flags);
            }
        } catch (RemoteException|RuntimeException e) {
         
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_AIDL);
            }

        return res;
    }

大家都知道服务端执行一般是onTransact开始,这里面也可以看到有了相关的trace打印到systrace,但是实际上我们并没有看到有相关的trace有打印。代码中也可以看出线索,这里的Trace打印输出的tag是Trace.TRACE_TAG_AIDL,要这个可以打印出来那么必须要Trace.TRACE_TAG_AIDL是开放的状态。 那么我们尝试抓取trace时候带上aidl参数试试: 在这里插入图片描述 抓取trace之后的结果如下:

在这里插入图片描述 果然发现这里服务端已经有了相关的跨进程详细方法 整体格式

AIDL::java::IAppOpsService::checkOperation::server

AIDL::java 即代表java类型的跨进程方法 IAppOpsService::checkOperation 代表具体服务端方法 server 代表服务端

这个trace打印同时也支持一些cpp端的打印

例如可以看下面: 在这里插入图片描述在这里插入图片描述上面就是apk应用进程发起跨进程调用ISurfaceComposer::createDisplayEventConnection

AIDL::cpp::ISurfaceComposer::createDisplayEventConnection::cppClient
AIDL::cpp::ISurfaceComposer::createDisplayEventConnection::cppServer

AIDL::cpp代表是cpp代码发起跨进程调用

ISurfaceComposer::createDisplayEventConnection 跨进程的具体方法

cppClient,cppServer代表跨进程客户端,服务端

相关trace输出TAG分析

这里可以看一下相关源码 在这里插入图片描述 在这里插入图片描述大家可以看到这里其实也有相关注释说明这些名字的其实由aidl工具生成的

如果是cpp代码情况:

这里可以寻找到对的aidl生成的相关的文件:

比如寻找ISurfaceComposer.aidl文件生成的cpp

test@test:~/disk2/aosp14/out/soong/.intermediates/frameworks$ find -name ISurfaceComposer.cpp
./native/libs/gui/libgui_aidl_static/android_vendor.34_x86_x86_64_static/gen/aidl/android/gui/ISurfaceComposer.cpp
./native/libs/gui/libgui_aidl_static/android_x86_x86_64_static_afdo-libgui_lto-thin/gen/aidl/android/gui/ISurfaceComposer.cpp
./native/libs/gui/libgui_aidl_static/android_vendor.34_x86_64_static_afdo-libgui_lto-thin/gen/aidl/android/gui/ISurfaceComposer.cpp
./native/libs/gui/libgui_aidl_static/android_vendor.34_x86_x86_64_static_afdo-libgui_lto-thin/gen/aidl/android/gui/ISurfaceComposer.cpp
./native/libs/gui/libgui_aidl_static/android_x86_64_static_afdo-libgui_lto-thin/gen/aidl/android/gui/ISurfaceComposer.cpp
./native/libs/gui/libgui_aidl_static/android_x86_64_static/gen/aidl/android/gui/ISurfaceComposer.cpp
./native/libs/gui/libgui_aidl_static/android_x86_x86_64_static/gen/aidl/android/gui/ISurfaceComposer.cpp
./native/libs/gui/libgui_aidl_static/android_x86_64_static_afdo-surfaceflinger_lto-thin/gen/aidl/android/gui/ISurfaceComposer.cpp
./native/libs/gui/libgui_aidl_static/android_vendor.34_x86_64_static/gen/aidl/android/gui/ISurfaceComposer.cpp
test@test:~/disk2/aosp14/out/soong/.intermediates/frameworks$ vi ./native/libs/gui/libgui_aidl_static/android_x86_64_static/gen/aidl/android/gui/ISurfaceComposer.cpp


在这里插入图片描述 在这里插入图片描述

总结

这里的systrace打印跨进程的方法,不是针对所有接口都有哈,一般针对aidl文件实现的接口才有,因为都是会通过aidl工具进行编译时候植入相关trace,本质上要systrace可以看到更多完整的aidl接口相关调用,需要以下两步:

1、adb shell am trace-ipc start

2、抓取perfetto时候偶带上tag为aidl

本文基础参考:

Binder通讯如何打印client调用堆栈即systrace查看对应方法

更多framework实战干货,请关注下面“千里马学框架”