背景:
有学员基于aosp15代码版本开始学习马哥的SurfaceFlinger/Perfetto课程,但是它想要基于aosp15版本代码也进行相关的自定义的ATRACE的打印,来通过打atrace看perfetto方式追踪整个函数的调用栈。

但是他在SurfaceFlinger的Layer.cpp中进行相关的ATRACE_CALL添加,具体添加代码如下:
目的很简单,只是想针对releasePreviousBuffer整个方法进行在perfetto上slice输出。
但是学员反馈居然在aosp15版本添加上面代码后,有编译报错
error: no matching constructor for initialization of ‘::android::ScopedTrace’
详细编译报错如下:
system/core/libutils/include/utils/Trace.h:27:9: error: '_PASTE' macro redefined [-Werror,-Wmacro-redefined]
27 | #define _PASTE(x, y) x ## y
| ^
frameworks/native/services/surfaceflinger/common/include/common/trace.h:63:9: note: previous definition is here
63 | #define _PASTE(x, y) x##y
| ^
In file included from frameworks/native/services/surfaceflinger/Layer.cpp:78:
system/core/libutils/include/utils/Trace.h:28:9: error: 'PASTE' macro redefined [-Werror,-Wmacro-redefined]
28 | #define PASTE(x, y) _PASTE(x,y)
| ^
frameworks/native/services/surfaceflinger/common/include/common/trace.h:64:9: note: previous definition is here
64 | #define PASTE(x, y) _PASTE(x, y)
| ^
In file included from frameworks/native/services/surfaceflinger/Layer.cpp:78:
system/core/libutils/include/utils/Trace.h:36:7: error: redefinition of 'ScopedTrace'
36 | class ScopedTrace {
| ^
frameworks/native/services/surfaceflinger/common/include/common/trace.h:80:7: note: previous definition is here
80 | class ScopedTrace {
| ^
frameworks/native/services/surfaceflinger/Layer.cpp:845:9: error: no matching constructor for initialization of '::android::ScopedTrace'
845 | ATRACE_CALL();
那么到底是怎么回事呢?难道高版本的SurfaceFlinger都不支持ATRACE使用了么?
下面来剖析一下整个编译报错的原因。
编译原因剖析
首先看编译报错日志,可以看到其实有多个error输出的:
----错误1:有一个Trace.h:27行的redefined重复第一报错
system/core/libutils/include/utils/Trace.h:27:9: error: '_PASTE' macro redefined [-Werror,-Wmacro-redefined]
27 | #define _PASTE(x, y) x ## y
----错误2:有一个Trace.h:36行的redefined重复第一报错
system/core/libutils/include/utils/Trace.h:36:7: error: redefinition of 'ScopedTrace'
36 | class ScopedTrace {
---错误3:有一个我们自己加入的代码ATRACE_CALL报错,报错是找不到匹配构造方法
frameworks/native/services/surfaceflinger/Layer.cpp:845:9: error: no matching constructor for initialization of '::android::ScopedTrace'
845 | ATRACE_CALL();
首先大家可能下意识的会忽略掉前两个.h中错误,因为可能觉得这块代码都不是我们自己写的,所以很容易不理会,但是错误3因为属于自己加入代码并且报错就在加的哪一行,一般注意力都在错误3,这样看其实也算正常啦,毕竟大家下意识只关注自己加入代码。
哈哈,那么就按照常规分析错误3来看看:
ATRACE_CALL宏剖析
那么我们来看看ATRACE_CALL这个宏
system/core/libutils/include/utils/Trace.h
#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
这里的ATRACE_NAME代码又如下:
#define _PASTE(x, y) x ## y
#define PASTE(x, y) _PASTE(x,y)
#define ATRACE_NAME(name) ::android::ScopedTrace PASTE(___tracer, __LINE__)(ATRACE_TAG, name)
这里一共分为3个部分,这里挨个进行剖析

部分1:
::android::ScopedTrace,它其实是一个类,属于类型的声明
class ScopedTrace {
public:
inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) {
atrace_begin(mTag, name);
}
inline ~ScopedTrace() {
atrace_end(mTag);
}
private:
uint64_t mTag;
};
可以看出这个类型的变量在构造和析构时候会调用atrace_begin和atrace_end。
部分2:
PASTE(___tracer, LINE)
本质其实就是调用宏,进行拼接成唯一的一个对象变量名字,拼接变量名字主要目的就是为了防止命名冲突。
PASTE(___tracer, LINE)第二个__LINE__代表行号意思
所以最后拼接的变量是:
___tracer845
部分3:
这个没啥可说的,就是ScopedTrace构造方法需要传递的参数
所以最后这个宏结果就是:
::android::ScopedTrace ___tracer845(ATRACE_TAG, name)
再看错误
error: no matching constructor for initialization of '::android::ScopedTrace
明明在system/core/libutils/include/utils/Trace.h中看到了有这个的android::ScopedTrace定义,为啥说没有匹配到呢?
这里明明有啊,所以这里其实就需要结合前面的错误2了:
system/core/libutils/include/utils/Trace.h:36:7: error: redefinition of 'ScopedTrace'
36 | class ScopedTrace {
说Trace.h的ScopedTrace是重复定义,那么到底是哪里先定义了呢?错误日志中也有提示:
frameworks/native/services/surfaceflinger/common/include/common/trace.h:80:7: note: previous definition is here
80 | class ScopedTrace {
简单说frameworks/native/services/surfaceflinger/common/include/common/trace.h也有定义ScopedTrace

哈哈,那这里其实就清楚了,原理SurfaceFlinger对于ATRACE打印这块有自己做了全新的trace.h来定义相关的trace打印输出的宏,所以代码中一旦引入了SurfaceFlinger自己的trace.h就不可以再使用
system/core/libutils/include/utils/Trace.h。
那么到此就可以清楚了为啥调用一个ATRACE_CALL会报错的原因了,那么这个问题如何解决呢?
那当然是看看SurfaceFlinger自己的trace.h是不是有类似宏就可以了。
解决办法:
frameworks/native/services/surfaceflinger/common/include/common/trace.h
文件中可以使用的宏
#define SFTRACE_ENABLED() ::tracing_perfetto::isTagEnabled(ATRACE_TAG)
#define SFTRACE_BEGIN(name) ::tracing_perfetto::traceBegin(ATRACE_TAG, name)
#define SFTRACE_END() ::tracing_perfetto::traceEnd(ATRACE_TAG)
#define SFTRACE_ASYNC_BEGIN(name, cookie) \
::tracing_perfetto::traceAsyncBegin(ATRACE_TAG, name, cookie)
#define SFTRACE_ASYNC_END(name, cookie) ::tracing_perfetto::traceAsyncEnd(ATRACE_TAG, name, cookie)
#define SFTRACE_ASYNC_FOR_TRACK_BEGIN(track_name, name, cookie) \
::tracing_perfetto::traceAsyncBeginForTrack(ATRACE_TAG, name, track_name, cookie)
#define SFTRACE_ASYNC_FOR_TRACK_END(track_name, cookie) \
::tracing_perfetto::traceAsyncEndForTrack(ATRACE_TAG, track_name, cookie)
#define SFTRACE_INSTANT(name) ::tracing_perfetto::traceInstant(ATRACE_TAG, name)
#define SFTRACE_FORMAT_INSTANT(fmt, ...) \
::tracing_perfetto::traceFormatInstant(ATRACE_TAG, fmt, ##__VA_ARGS__)
#define SFTRACE_INSTANT_FOR_TRACK(trackName, name) \
::tracing_perfetto::traceInstantForTrack(ATRACE_TAG, trackName, name)
#define SFTRACE_INT(name, value) ::tracing_perfetto::traceCounter32(ATRACE_TAG, name, value)
#define SFTRACE_INT64(name, value) ::tracing_perfetto::traceCounter(ATRACE_TAG, name, value)
// SFTRACE_NAME traces from its location until the end of its enclosing scope.
#define _PASTE(x, y) x##y
#define PASTE(x, y) _PASTE(x, y)
#define SFTRACE_NAME(name) ::android::ScopedTrace PASTE(___tracer, __LINE__)(name)
// SFTRACE_CALL is an SFTRACE_NAME that uses the current function name.
#define SFTRACE_CALL() SFTRACE_NAME(__FUNCTION__)
#define SFTRACE_FORMAT(fmt, ...) \
::android::ScopedTrace PASTE(___tracer, __LINE__)(fmt, ##__VA_ARGS__)
#define ALOGE_AND_TRACE(fmt, ...) \
do { \
ALOGE(fmt, ##__VA_ARGS__); \
SFTRACE_FORMAT_INSTANT(fmt, ##__VA_ARGS__); \
} while (false)
其实可以看出上面的宏其实和以前基本上一个样,就是以前是ATRACE现在要变成SFTRACE。

修改后再次编译:

一次性成果,所以对于SF中如果在aosp15想要加入相关的ATRACE等尽量建议使用
frameworks/native/services/surfaceflinger/common/include/common/trace.h
下的宏进行,不要再使用和引入utils/Trace.h。
更多framework实战干货,请关注下面“千里马学框架”
1417

被折叠的 条评论
为什么被折叠?



