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 #define FRAMEWORK_CATEGORIES(C) \
18 C(always, "always", "Always category") \
19 C(graphics, "graphics", "Graphics category") \
20 C(input, "input", "Input category") \
21 C(view, "view", "View category") \
22 C(webview, "webview", "WebView category") \
23 C(windowmanager, "wm", "WindowManager category") \
24 C(activitymanager, "am", "ActivityManager category") \
25 C(syncmanager, "syncmanager", "SyncManager category") \
26 C(audio, "audio", "Audio category") \
27 C(video, "video", "Video category") \
28 C(camera, "camera", "Camera category") \
29 C(hal, "hal", "HAL category") \
30 C(app, "app", "App category") \
31 C(resources, "res", "Resources category") \
32 C(dalvik, "dalvik", "Dalvik category") \
33 C(rs, "rs", "RS category") \
34 C(bionic, "bionic", "Bionic category") \
35 C(power, "power", "Power category") \
36 C(packagemanager, "packagemanager", "PackageManager category") \
37 C(systemserver, "ss", "System Server category") \
38 C(database, "database", "Database category") \
39 C(network, "network", "Network category") \
40 C(adb, "adb", "ADB category") \
41 C(vibrator, "vibrator", "Vibrator category") \
42 C(aidl, "aidl", "AIDL category") \
43 C(nnapi, "nnapi", "NNAPI category") \
44 C(rro, "rro", "RRO category") \
45 C(thermal, "thermal", "Thermal category")
46
47 #include <atomic>
48 #include <mutex>
49
50 #include <android_os.h>
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 if (!android::os::perfetto_sdk_tracing()) {
232 return;
233 }
234
235 static std::once_flag registration;
236 std::call_once(registration, [test]() {
237 struct PerfettoProducerInitArgs args = PERFETTO_PRODUCER_INIT_ARGS_INIT();
238 args.backends = test ? PERFETTO_BACKEND_IN_PROCESS : PERFETTO_BACKEND_SYSTEM;
239 args.shmem_size_hint_kb = 1024;
240 PerfettoProducerInit(args);
241 PerfettoTeInit();
242 PERFETTO_TE_REGISTER_CATEGORIES(FRAMEWORK_CATEGORIES);
243 });
244 }
245
perfettoTraceBegin(const struct PerfettoTeCategory & category,const char * name)246 void perfettoTraceBegin(const struct PerfettoTeCategory& category, const char* name) {
247 PERFETTO_TE(category, PERFETTO_TE_SLICE_BEGIN(name));
248 }
249
perfettoTraceEnd(const struct PerfettoTeCategory & category)250 void perfettoTraceEnd(const struct PerfettoTeCategory& category) {
251 PERFETTO_TE(category, PERFETTO_TE_SLICE_END());
252 }
253
perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory & category,const char * name,const char * trackName,uint64_t cookie)254 void perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory& category, const char* name,
255 const char* trackName, uint64_t cookie) {
256 PERFETTO_TE(
257 category, PERFETTO_TE_SLICE_BEGIN(name),
258 PERFETTO_TE_PROTO_TRACK(
259 PerfettoTeNamedTrackUuid(trackName, cookie,
260 PerfettoTeProcessTrackUuid()),
261 PERFETTO_TE_PROTO_FIELD_CSTR(
262 perfetto_protos_TrackDescriptor_atrace_name_field_number,
263 trackName),
264 PERFETTO_TE_PROTO_FIELD_VARINT(
265 perfetto_protos_TrackDescriptor_parent_uuid_field_number,
266 PerfettoTeProcessTrackUuid())));
267 }
268
perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory & category,const char * trackName,uint64_t cookie)269 void perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory& category,
270 const char* trackName, uint64_t cookie) {
271 PERFETTO_TE(
272 category, PERFETTO_TE_SLICE_END(),
273 PERFETTO_TE_PROTO_TRACK(
274 PerfettoTeNamedTrackUuid(trackName, cookie,
275 PerfettoTeProcessTrackUuid()),
276 PERFETTO_TE_PROTO_FIELD_CSTR(
277 perfetto_protos_TrackDescriptor_atrace_name_field_number,
278 trackName),
279 PERFETTO_TE_PROTO_FIELD_VARINT(
280 perfetto_protos_TrackDescriptor_parent_uuid_field_number,
281 PerfettoTeProcessTrackUuid())));
282 }
283
perfettoTraceAsyncBegin(const struct PerfettoTeCategory & category,const char * name,uint64_t cookie)284 void perfettoTraceAsyncBegin(const struct PerfettoTeCategory& category, const char* name,
285 uint64_t cookie) {
286 perfettoTraceAsyncBeginForTrack(category, name, name, cookie);
287 }
288
perfettoTraceAsyncEnd(const struct PerfettoTeCategory & category,const char * name,uint64_t cookie)289 void perfettoTraceAsyncEnd(const struct PerfettoTeCategory& category, const char* name,
290 uint64_t cookie) {
291 perfettoTraceAsyncEndForTrack(category, name, cookie);
292 }
293
perfettoTraceInstant(const struct PerfettoTeCategory & category,const char * name)294 void perfettoTraceInstant(const struct PerfettoTeCategory& category, const char* name) {
295 PERFETTO_TE(category, PERFETTO_TE_INSTANT(name));
296 }
297
perfettoTraceInstantForTrack(const struct PerfettoTeCategory & category,const char * trackName,const char * name)298 void perfettoTraceInstantForTrack(const struct PerfettoTeCategory& category,
299 const char* trackName, const char* name) {
300 PERFETTO_TE(
301 category, PERFETTO_TE_INSTANT(name),
302 PERFETTO_TE_PROTO_TRACK(
303 PerfettoTeNamedTrackUuid(trackName, 1,
304 PerfettoTeProcessTrackUuid()),
305 PERFETTO_TE_PROTO_FIELD_CSTR(
306 perfetto_protos_TrackDescriptor_atrace_name_field_number,
307 trackName),
308 PERFETTO_TE_PROTO_FIELD_VARINT(
309 perfetto_protos_TrackDescriptor_parent_uuid_field_number,
310 PerfettoTeProcessTrackUuid())));
311 }
312
perfettoTraceCounter(const struct PerfettoTeCategory & category,const char * name,int64_t value)313 void perfettoTraceCounter(const struct PerfettoTeCategory& category,
314 const char* name, int64_t value) {
315 PERFETTO_TE(
316 category, PERFETTO_TE_COUNTER(),
317 PERFETTO_TE_PROTO_TRACK(
318 PerfettoTeCounterTrackUuid(name,
319 PerfettoTeProcessTrackUuid()),
320 PERFETTO_TE_PROTO_FIELD_CSTR(
321 perfetto_protos_TrackDescriptor_atrace_name_field_number,
322 name),
323 PERFETTO_TE_PROTO_FIELD_VARINT(
324 perfetto_protos_TrackDescriptor_parent_uuid_field_number,
325 PerfettoTeProcessTrackUuid()),
326 PERFETTO_TE_PROTO_FIELD_BYTES(
327 perfetto_protos_TrackDescriptor_counter_field_number,
328 PERFETTO_NULL, 0)),
329 PERFETTO_TE_INT_COUNTER(value));
330 }
331 } // namespace internal
332
333 } // namespace tracing_perfetto
334