1 /*
2 * Copyright 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // Should match the definitions in: frameworks/native/cmds/atrace/atrace.cpp
18 #define FRAMEWORK_CATEGORIES(C) \
19 C(always, "always", "Always category") \
20 C(graphics, "gfx", "Graphics category") \
21 C(input, "input", "Input category") \
22 C(view, "view", "View category") \
23 C(webview, "webview", "WebView category") \
24 C(windowmanager, "wm", "WindowManager category") \
25 C(activitymanager, "am", "ActivityManager category") \
26 C(syncmanager, "sm", "SyncManager category") \
27 C(audio, "audio", "Audio category") \
28 C(video, "video", "Video category") \
29 C(camera, "camera", "Camera category") \
30 C(hal, "hal", "HAL category") \
31 C(app, "app", "App category") \
32 C(resources, "res", "Resources category") \
33 C(dalvik, "dalvik", "Dalvik category") \
34 C(rs, "rs", "RS category") \
35 C(bionic, "bionic", "Bionic category") \
36 C(power, "power", "Power category") \
37 C(packagemanager, "pm", "PackageManager category") \
38 C(systemserver, "ss", "System Server category") \
39 C(database, "database", "Database category") \
40 C(network, "network", "Network category") \
41 C(adb, "adb", "ADB category") \
42 C(vibrator, "vibrator", "Vibrator category") \
43 C(aidl, "aidl", "AIDL category") \
44 C(nnapi, "nnapi", "NNAPI category") \
45 C(rro, "rro", "RRO category") \
46 C(thermal, "thermal", "Thermal category")
47
48 #include <atomic>
49 #include <mutex>
50
51 #include <android-base/properties.h>
52 #include <cutils/trace.h>
53 #include <inttypes.h>
54
55 #include "perfetto/public/compiler.h"
56 #include "perfetto/public/producer.h"
57 #include "perfetto/public/te_category_macros.h"
58 #include "perfetto/public/te_macros.h"
59 #include "perfetto/public/track_event.h"
60 #include "trace_categories.h"
61 #include "tracing_perfetto_internal.h"
62
63 #ifdef __BIONIC__
64 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
65 #include <sys/_system_properties.h>
66 #endif
67
68 namespace tracing_perfetto {
69
70 namespace internal {
71
72 namespace {
73 PERFETTO_TE_CATEGORIES_DECLARE(FRAMEWORK_CATEGORIES);
74
75 PERFETTO_TE_CATEGORIES_DEFINE(FRAMEWORK_CATEGORIES);
76
77 static constexpr char kPreferFlagProperty[] = "debug.atrace.prefer_sdk";
78 static std::atomic<const prop_info*> prefer_property_info = nullptr;
79 static std::atomic_uint32_t last_prefer_seq_num = 0;
80 static std::atomic_uint64_t prefer_flags = 0;
81
system_property_find(const char * name)82 static const prop_info* system_property_find(const char* name [[maybe_unused]]) {
83 #ifdef __BIONIC__
84 return __system_property_find(name);
85 #endif
86
87 return nullptr;
88 }
89
system_property_serial(const prop_info * pi)90 static uint32_t system_property_serial(const prop_info* pi [[maybe_unused]]) {
91 #ifdef __BIONIC__
92 return __system_property_serial(pi);
93 #endif
94
95 return last_prefer_seq_num;
96 }
97
toCategory(uint64_t inCategory)98 struct PerfettoTeCategory* toCategory(uint64_t inCategory) {
99 switch (inCategory) {
100 case TRACE_CATEGORY_ALWAYS:
101 return &always;
102 case TRACE_CATEGORY_GRAPHICS:
103 return &graphics;
104 case TRACE_CATEGORY_INPUT:
105 return &input;
106 case TRACE_CATEGORY_VIEW:
107 return &view;
108 case TRACE_CATEGORY_WEBVIEW:
109 return &webview;
110 case TRACE_CATEGORY_WINDOW_MANAGER:
111 return &windowmanager;
112 case TRACE_CATEGORY_ACTIVITY_MANAGER:
113 return &activitymanager;
114 case TRACE_CATEGORY_SYNC_MANAGER:
115 return &syncmanager;
116 case TRACE_CATEGORY_AUDIO:
117 return &audio;
118 case TRACE_CATEGORY_VIDEO:
119 return &video;
120 case TRACE_CATEGORY_CAMERA:
121 return &camera;
122 case TRACE_CATEGORY_HAL:
123 return &hal;
124 case TRACE_CATEGORY_APP:
125 return &app;
126 case TRACE_CATEGORY_RESOURCES:
127 return &resources;
128 case TRACE_CATEGORY_DALVIK:
129 return &dalvik;
130 case TRACE_CATEGORY_RS:
131 return &rs;
132 case TRACE_CATEGORY_BIONIC:
133 return &bionic;
134 case TRACE_CATEGORY_POWER:
135 return &power;
136 case TRACE_CATEGORY_PACKAGE_MANAGER:
137 return &packagemanager;
138 case TRACE_CATEGORY_SYSTEM_SERVER:
139 return &systemserver;
140 case TRACE_CATEGORY_DATABASE:
141 return &database;
142 case TRACE_CATEGORY_NETWORK:
143 return &network;
144 case TRACE_CATEGORY_ADB:
145 return &adb;
146 case TRACE_CATEGORY_VIBRATOR:
147 return &vibrator;
148 case TRACE_CATEGORY_AIDL:
149 return &aidl;
150 case TRACE_CATEGORY_NNAPI:
151 return &nnapi;
152 case TRACE_CATEGORY_RRO:
153 return &rro;
154 case TRACE_CATEGORY_THERMAL:
155 return &thermal;
156 default:
157 return nullptr;
158 }
159 }
160
161 } // namespace
162
isPerfettoCategoryEnabled(PerfettoTeCategory * category)163 bool isPerfettoCategoryEnabled(PerfettoTeCategory* category) {
164 return category != nullptr;
165 }
166
167 /**
168 * Updates the cached |prefer_flags|.
169 *
170 * We cache the prefer_flags because reading it on every trace event is expensive.
171 * The cache is invalidated when a sys_prop sequence number changes.
172 */
updatePreferFlags()173 void updatePreferFlags() {
174 if (!prefer_property_info.load(std::memory_order_acquire)) {
175 auto* new_prefer_property_info = system_property_find(kPreferFlagProperty);
176 prefer_flags.store(android::base::GetIntProperty(kPreferFlagProperty, 0),
177 std::memory_order_relaxed);
178
179 if (!new_prefer_property_info) {
180 // This should never happen. If it does, we fail gracefully and end up reading the property
181 // traced event.
182 return;
183 }
184
185 last_prefer_seq_num = system_property_serial(new_prefer_property_info);
186 prefer_property_info.store(new_prefer_property_info, std::memory_order_release);
187 }
188
189 uint32_t prefer_seq_num = system_property_serial(prefer_property_info);
190 if (prefer_seq_num != last_prefer_seq_num.load(std::memory_order_acquire)) {
191 prefer_flags.store(android::base::GetIntProperty(kPreferFlagProperty, 0),
192 std::memory_order_relaxed);
193 last_prefer_seq_num.store(prefer_seq_num, std::memory_order_release);
194 }
195 }
196
shouldPreferAtrace(PerfettoTeCategory * perfettoCategory,uint64_t atraceCategory)197 bool shouldPreferAtrace(PerfettoTeCategory *perfettoCategory, uint64_t atraceCategory) {
198 // There are 3 cases:
199 // 1. Atrace is not enabled.
200 if (!atrace_is_tag_enabled(atraceCategory)) {
201 return false;
202 }
203
204 // 2. Atrace is enabled but perfetto is not enabled.
205 if (!isPerfettoCategoryEnabled(perfettoCategory)) {
206 return true;
207 }
208
209 // Update prefer_flags before checking it below
210 updatePreferFlags();
211
212 // 3. Atrace and perfetto are enabled.
213 // Even though this category is enabled for track events, the config mandates that we downgrade
214 // it to atrace if the same atrace category is currently enabled. This prevents missing the
215 // event from a concurrent session that needs the same category in atrace.
216 return (atraceCategory & prefer_flags.load(std::memory_order_relaxed)) == 0;
217 }
218
toPerfettoCategory(uint64_t category)219 struct PerfettoTeCategory* toPerfettoCategory(uint64_t category) {
220 struct PerfettoTeCategory* perfettoCategory = toCategory(category);
221 if (perfettoCategory == nullptr) {
222 return nullptr;
223 }
224
225 bool enabled = PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
226 (*perfettoCategory).enabled, PERFETTO_MEMORY_ORDER_RELAXED));
227 return enabled ? perfettoCategory : nullptr;
228 }
229
registerWithPerfetto(bool test)230 void registerWithPerfetto(bool test) {
231 static std::once_flag registration;
232 std::call_once(registration, [test]() {
233 struct PerfettoProducerInitArgs args = PERFETTO_PRODUCER_INIT_ARGS_INIT();
234 args.backends = test ? PERFETTO_BACKEND_IN_PROCESS : PERFETTO_BACKEND_SYSTEM;
235 args.shmem_size_hint_kb = 1024;
236 PerfettoProducerInit(args);
237 PerfettoTeInit();
238 PERFETTO_TE_REGISTER_CATEGORIES(FRAMEWORK_CATEGORIES);
239 });
240 }
241
perfettoTraceBegin(const struct PerfettoTeCategory & category,const char * name)242 void perfettoTraceBegin(const struct PerfettoTeCategory& category, const char* name) {
243 PERFETTO_TE(category, PERFETTO_TE_SLICE_BEGIN(name));
244 }
245
perfettoTraceEnd(const struct PerfettoTeCategory & category)246 void perfettoTraceEnd(const struct PerfettoTeCategory& category) {
247 PERFETTO_TE(category, PERFETTO_TE_SLICE_END());
248 }
249
perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory & category,const char * name,const char * trackName,uint64_t cookie)250 void perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory& category, const char* name,
251 const char* trackName, uint64_t cookie) {
252 PERFETTO_TE(
253 category, PERFETTO_TE_SLICE_BEGIN(name),
254 PERFETTO_TE_PROTO_TRACK(
255 PerfettoTeNamedTrackUuid(trackName, cookie,
256 PerfettoTeProcessTrackUuid()),
257 PERFETTO_TE_PROTO_FIELD_CSTR(
258 perfetto_protos_TrackDescriptor_atrace_name_field_number,
259 trackName),
260 PERFETTO_TE_PROTO_FIELD_VARINT(
261 perfetto_protos_TrackDescriptor_parent_uuid_field_number,
262 PerfettoTeProcessTrackUuid())));
263 }
264
perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory & category,const char * trackName,uint64_t cookie)265 void perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory& category,
266 const char* trackName, uint64_t cookie) {
267 PERFETTO_TE(
268 category, PERFETTO_TE_SLICE_END(),
269 PERFETTO_TE_PROTO_TRACK(
270 PerfettoTeNamedTrackUuid(trackName, cookie,
271 PerfettoTeProcessTrackUuid()),
272 PERFETTO_TE_PROTO_FIELD_CSTR(
273 perfetto_protos_TrackDescriptor_atrace_name_field_number,
274 trackName),
275 PERFETTO_TE_PROTO_FIELD_VARINT(
276 perfetto_protos_TrackDescriptor_parent_uuid_field_number,
277 PerfettoTeProcessTrackUuid())));
278 }
279
perfettoTraceAsyncBegin(const struct PerfettoTeCategory & category,const char * name,uint64_t cookie)280 void perfettoTraceAsyncBegin(const struct PerfettoTeCategory& category, const char* name,
281 uint64_t cookie) {
282 perfettoTraceAsyncBeginForTrack(category, name, name, cookie);
283 }
284
perfettoTraceAsyncEnd(const struct PerfettoTeCategory & category,const char * name,uint64_t cookie)285 void perfettoTraceAsyncEnd(const struct PerfettoTeCategory& category, const char* name,
286 uint64_t cookie) {
287 perfettoTraceAsyncEndForTrack(category, name, cookie);
288 }
289
perfettoTraceInstant(const struct PerfettoTeCategory & category,const char * name)290 void perfettoTraceInstant(const struct PerfettoTeCategory& category, const char* name) {
291 PERFETTO_TE(category, PERFETTO_TE_INSTANT(name));
292 }
293
perfettoTraceInstantForTrack(const struct PerfettoTeCategory & category,const char * trackName,const char * name)294 void perfettoTraceInstantForTrack(const struct PerfettoTeCategory& category,
295 const char* trackName, const char* name) {
296 PERFETTO_TE(
297 category, PERFETTO_TE_INSTANT(name),
298 PERFETTO_TE_PROTO_TRACK(
299 PerfettoTeNamedTrackUuid(trackName, 1,
300 PerfettoTeProcessTrackUuid()),
301 PERFETTO_TE_PROTO_FIELD_CSTR(
302 perfetto_protos_TrackDescriptor_atrace_name_field_number,
303 trackName),
304 PERFETTO_TE_PROTO_FIELD_VARINT(
305 perfetto_protos_TrackDescriptor_parent_uuid_field_number,
306 PerfettoTeProcessTrackUuid())));
307 }
308
perfettoTraceCounter(const struct PerfettoTeCategory & category,const char * name,int64_t value)309 void perfettoTraceCounter(const struct PerfettoTeCategory& category,
310 const char* name, int64_t value) {
311 PERFETTO_TE(
312 category, PERFETTO_TE_COUNTER(),
313 PERFETTO_TE_PROTO_TRACK(
314 PerfettoTeCounterTrackUuid(name,
315 PerfettoTeProcessTrackUuid()),
316 PERFETTO_TE_PROTO_FIELD_CSTR(
317 perfetto_protos_TrackDescriptor_atrace_name_field_number,
318 name),
319 PERFETTO_TE_PROTO_FIELD_VARINT(
320 perfetto_protos_TrackDescriptor_parent_uuid_field_number,
321 PerfettoTeProcessTrackUuid()),
322 PERFETTO_TE_PROTO_FIELD_BYTES(
323 perfetto_protos_TrackDescriptor_counter_field_number,
324 PERFETTO_NULL, 0)),
325 PERFETTO_TE_INT_COUNTER(value));
326 }
327 } // namespace internal
328
329 } // namespace tracing_perfetto
330