1 /* 2 * Copyright (C) 2012 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 package android.os; 18 19 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; 20 21 import android.annotation.NonNull; 22 import android.annotation.SystemApi; 23 import android.compat.annotation.UnsupportedAppUsage; 24 25 import dalvik.annotation.optimization.CriticalNative; 26 import dalvik.annotation.optimization.FastNative; 27 28 /** 29 * Writes trace events to the system trace buffer. These trace events can be 30 * collected and visualized using the Systrace tool. 31 * 32 * <p>This tracing mechanism is independent of the method tracing mechanism 33 * offered by {@link Debug#startMethodTracing}. In particular, it enables 34 * tracing of events that occur across multiple processes. 35 * <p>For information about using the Systrace tool, read <a 36 * href="{@docRoot}tools/debugging/systrace.html">Analyzing Display and Performance 37 * with Systrace</a>. 38 */ 39 public final class Trace { 40 /* 41 * Writes trace events to the kernel trace buffer. These trace events can be 42 * collected using the "atrace" program for offline analysis. 43 */ 44 45 private static final String TAG = "Trace"; 46 47 // These tags must be kept in sync with system/core/include/cutils/trace.h. 48 // They should also be added to frameworks/native/cmds/atrace/atrace.cpp. 49 /** @hide */ 50 public static final long TRACE_TAG_NEVER = 0; 51 /** @hide */ 52 public static final long TRACE_TAG_ALWAYS = 1L << 0; 53 /** @hide */ 54 public static final long TRACE_TAG_GRAPHICS = 1L << 1; 55 /** @hide */ 56 public static final long TRACE_TAG_INPUT = 1L << 2; 57 /** @hide */ 58 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 59 public static final long TRACE_TAG_VIEW = 1L << 3; 60 /** @hide */ 61 public static final long TRACE_TAG_WEBVIEW = 1L << 4; 62 /** @hide */ 63 public static final long TRACE_TAG_WINDOW_MANAGER = 1L << 5; 64 /** @hide */ 65 public static final long TRACE_TAG_ACTIVITY_MANAGER = 1L << 6; 66 /** @hide */ 67 public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7; 68 /** @hide */ 69 public static final long TRACE_TAG_AUDIO = 1L << 8; 70 /** @hide */ 71 public static final long TRACE_TAG_VIDEO = 1L << 9; 72 /** @hide */ 73 public static final long TRACE_TAG_CAMERA = 1L << 10; 74 /** @hide */ 75 public static final long TRACE_TAG_HAL = 1L << 11; 76 /** @hide */ 77 @UnsupportedAppUsage 78 public static final long TRACE_TAG_APP = 1L << 12; 79 /** @hide */ 80 public static final long TRACE_TAG_RESOURCES = 1L << 13; 81 /** @hide */ 82 public static final long TRACE_TAG_DALVIK = 1L << 14; 83 /** @hide */ 84 public static final long TRACE_TAG_RS = 1L << 15; 85 /** @hide */ 86 public static final long TRACE_TAG_BIONIC = 1L << 16; 87 /** @hide */ 88 public static final long TRACE_TAG_POWER = 1L << 17; 89 /** @hide */ 90 public static final long TRACE_TAG_PACKAGE_MANAGER = 1L << 18; 91 /** @hide */ 92 public static final long TRACE_TAG_SYSTEM_SERVER = 1L << 19; 93 /** @hide */ 94 public static final long TRACE_TAG_DATABASE = 1L << 20; 95 /** @hide */ 96 @SystemApi(client = MODULE_LIBRARIES) 97 public static final long TRACE_TAG_NETWORK = 1L << 21; 98 /** @hide */ 99 public static final long TRACE_TAG_ADB = 1L << 22; 100 /** @hide */ 101 public static final long TRACE_TAG_VIBRATOR = 1L << 23; 102 /** @hide */ 103 @SystemApi 104 public static final long TRACE_TAG_AIDL = 1L << 24; 105 /** @hide */ 106 public static final long TRACE_TAG_NNAPI = 1L << 25; 107 /** @hide */ 108 public static final long TRACE_TAG_RRO = 1L << 26; 109 /** @hide */ 110 public static final long TRACE_TAG_THERMAL = 1L << 27; 111 112 private static final long TRACE_TAG_NOT_READY = 1L << 63; 113 /** @hide **/ 114 public static final int MAX_SECTION_NAME_LEN = 127; 115 116 // Must be volatile to avoid word tearing. 117 // This is only kept in case any apps get this by reflection but do not 118 // check the return value for null. 119 @UnsupportedAppUsage 120 private static volatile long sEnabledTags = TRACE_TAG_NOT_READY; 121 122 private static int sZygoteDebugFlags = 0; 123 124 @UnsupportedAppUsage 125 @CriticalNative nativeGetEnabledTags()126 private static native long nativeGetEnabledTags(); nativeSetAppTracingAllowed(boolean allowed)127 private static native void nativeSetAppTracingAllowed(boolean allowed); nativeSetTracingEnabled(boolean allowed)128 private static native void nativeSetTracingEnabled(boolean allowed); 129 130 @FastNative nativeTraceCounter(long tag, String name, long value)131 private static native void nativeTraceCounter(long tag, String name, long value); 132 @FastNative nativeTraceBegin(long tag, String name)133 private static native void nativeTraceBegin(long tag, String name); 134 @FastNative nativeTraceEnd(long tag)135 private static native void nativeTraceEnd(long tag); 136 @FastNative nativeAsyncTraceBegin(long tag, String name, int cookie)137 private static native void nativeAsyncTraceBegin(long tag, String name, int cookie); 138 @FastNative nativeAsyncTraceEnd(long tag, String name, int cookie)139 private static native void nativeAsyncTraceEnd(long tag, String name, int cookie); 140 @FastNative nativeAsyncTraceForTrackBegin(long tag, String trackName, String name, int cookie)141 private static native void nativeAsyncTraceForTrackBegin(long tag, 142 String trackName, String name, int cookie); 143 @FastNative nativeAsyncTraceForTrackEnd(long tag, String trackName, int cookie)144 private static native void nativeAsyncTraceForTrackEnd(long tag, 145 String trackName, int cookie); 146 @FastNative nativeInstant(long tag, String name)147 private static native void nativeInstant(long tag, String name); 148 @FastNative nativeInstantForTrack(long tag, String trackName, String name)149 private static native void nativeInstantForTrack(long tag, String trackName, String name); 150 Trace()151 private Trace() { 152 } 153 154 /** 155 * Returns true if a trace tag is enabled. 156 * 157 * @param traceTag The trace tag to check. 158 * @return True if the trace tag is valid. 159 * 160 * @hide 161 */ 162 @UnsupportedAppUsage 163 @SystemApi(client = MODULE_LIBRARIES) isTagEnabled(long traceTag)164 public static boolean isTagEnabled(long traceTag) { 165 long tags = nativeGetEnabledTags(); 166 return (tags & traceTag) != 0; 167 } 168 169 /** 170 * Writes trace message to indicate the value of a given counter. 171 * 172 * @param traceTag The trace tag. 173 * @param counterName The counter name to appear in the trace. 174 * @param counterValue The counter value. 175 * 176 * @hide 177 */ 178 @UnsupportedAppUsage 179 @SystemApi(client = MODULE_LIBRARIES) traceCounter(long traceTag, @NonNull String counterName, int counterValue)180 public static void traceCounter(long traceTag, @NonNull String counterName, int counterValue) { 181 if (isTagEnabled(traceTag)) { 182 nativeTraceCounter(traceTag, counterName, counterValue); 183 } 184 } 185 186 /** 187 * From Android S, this is no-op. 188 * 189 * Before, set whether application tracing is allowed for this process. This is intended to be 190 * set once at application start-up time based on whether the application is debuggable. 191 * 192 * @hide 193 */ 194 @UnsupportedAppUsage setAppTracingAllowed(boolean allowed)195 public static void setAppTracingAllowed(boolean allowed) { 196 nativeSetAppTracingAllowed(allowed); 197 } 198 199 /** 200 * Set whether tracing is enabled in this process. 201 * @hide 202 */ setTracingEnabled(boolean enabled, int debugFlags)203 public static void setTracingEnabled(boolean enabled, int debugFlags) { 204 nativeSetTracingEnabled(enabled); 205 sZygoteDebugFlags = debugFlags; 206 } 207 208 /** 209 * Writes a trace message to indicate that a given section of code has 210 * begun. Must be followed by a call to {@link #traceEnd} using the same 211 * tag. 212 * 213 * @param traceTag The trace tag. 214 * @param methodName The method name to appear in the trace. 215 * 216 * @hide 217 */ 218 @UnsupportedAppUsage 219 @SystemApi(client = MODULE_LIBRARIES) traceBegin(long traceTag, @NonNull String methodName)220 public static void traceBegin(long traceTag, @NonNull String methodName) { 221 if (isTagEnabled(traceTag)) { 222 nativeTraceBegin(traceTag, methodName); 223 } 224 } 225 226 /** 227 * Writes a trace message to indicate that the current method has ended. 228 * Must be called exactly once for each call to {@link #traceBegin} using the same tag. 229 * 230 * @param traceTag The trace tag. 231 * 232 * @hide 233 */ 234 @UnsupportedAppUsage 235 @SystemApi(client = MODULE_LIBRARIES) traceEnd(long traceTag)236 public static void traceEnd(long traceTag) { 237 if (isTagEnabled(traceTag)) { 238 nativeTraceEnd(traceTag); 239 } 240 } 241 242 /** 243 * Writes a trace message to indicate that a given section of code has 244 * begun. Must be followed by a call to {@link #asyncTraceEnd} using the same 245 * tag, name and cookie. 246 * 247 * If two events with the same methodName overlap in time then they *must* have 248 * different cookie values. If they do not, the trace can become corrupted 249 * in unpredictable ways. 250 * 251 * Unlike {@link #traceBegin(long, String)} and {@link #traceEnd(long)}, 252 * asynchronous events cannot be not nested. Consider using 253 * {@link #asyncTraceForTrackBegin(long, String, String, int)} 254 * if nested asynchronous events are needed. 255 * 256 * @param traceTag The trace tag. 257 * @param methodName The method name to appear in the trace. 258 * @param cookie Unique identifier for distinguishing simultaneous events 259 * 260 * @hide 261 */ 262 @UnsupportedAppUsage 263 @SystemApi(client = MODULE_LIBRARIES) asyncTraceBegin(long traceTag, @NonNull String methodName, int cookie)264 public static void asyncTraceBegin(long traceTag, @NonNull String methodName, int cookie) { 265 if (isTagEnabled(traceTag)) { 266 nativeAsyncTraceBegin(traceTag, methodName, cookie); 267 } 268 } 269 270 /** 271 * Writes a trace message to indicate that the current method has ended. 272 * Must be called exactly once for each call to {@link #asyncTraceBegin(long, String, int)} 273 * using the same tag, name and cookie. 274 * 275 * See the documentation for {@link #asyncTraceBegin(long, String, int)}. 276 * for inteded usage of this method. 277 * 278 * @param traceTag The trace tag. 279 * @param methodName The method name to appear in the trace. 280 * @param cookie Unique identifier for distinguishing simultaneous events 281 * 282 * @hide 283 */ 284 @UnsupportedAppUsage 285 @SystemApi(client = MODULE_LIBRARIES) asyncTraceEnd(long traceTag, @NonNull String methodName, int cookie)286 public static void asyncTraceEnd(long traceTag, @NonNull String methodName, int cookie) { 287 if (isTagEnabled(traceTag)) { 288 nativeAsyncTraceEnd(traceTag, methodName, cookie); 289 } 290 } 291 292 293 /** 294 * Writes a trace message to indicate that a given section of code has 295 * begun. Must be followed by a call to {@link #asyncTraceForTrackEnd} using the same 296 * track name and cookie. 297 * 298 * Events with the same trackName and cookie nest inside each other in the 299 * same way as calls to {@link #traceBegin(long, String)} and 300 * {@link #traceEnd(long)}. 301 * 302 * If two events with the same trackName overlap in time but do not nest 303 * correctly, then they *must* have different cookie values. If they do not, 304 * the trace can become corrupted in unpredictable ways. 305 * 306 * Good Example: 307 * 308 * public void parent() { 309 * asyncTraceForTrackBegin(TRACE_TAG_ALWAYS, "Track", "parent", mId); 310 * child() 311 * asyncTraceForTrackEnd(TRACE_TAG_ALWAYS, "Track", mId); 312 * } 313 * 314 * public void child() { 315 * asyncTraceForTrackBegin(TRACE_TAG_ALWAYS, "Track", "child", mId); 316 * // Some code here. 317 * asyncTraceForTrackEnd(TRACE_TAG_ALWAYS, "Track", mId); 318 * } 319 * 320 * This would be visualized as so: 321 * [ Parent ] 322 * [ Child ] 323 * 324 * Bad Example: 325 * 326 * public static void processData(String dataToProcess) { 327 * asyncTraceForTrackBegin(TRACE_TAG_ALWAYS, "processDataInParallel", "processData", 0); 328 * // Some code here. 329 * asyncTraceForTrackEnd(TRACE_TAG_ALWAYS, "processDataInParallel", 0); 330 * } 331 * 332 * public static void processDataInParallel({@code List<String>} data) { 333 * ExecutorService executor = Executors.newCachedThreadPool(); 334 * for (String s : data) { 335 * pool.execute(() -> processData(s)); 336 * } 337 * } 338 * 339 * This is invalid because it's possible for processData to be run many times 340 * in parallel (i.e. processData events overlap) but the same cookie is 341 * provided each time. 342 * 343 * To fix this, specify a different id in each invocation of processData: 344 * 345 * public static void processData(String dataToProcess, int id) { 346 * asyncTraceForTrackBegin(TRACE_TAG_ALWAYS, "processDataInParallel", "processData", id); 347 * // Some code here. 348 * asyncTraceForTrackEnd(TRACE_TAG_ALWAYS, "processDataInParallel", id); 349 * } 350 * 351 * public static void processDataInParallel({@code List<String>} data) { 352 * ExecutorService executor = Executors.newCachedThreadPool(); 353 * for (int i = 0; i < data.size(); ++i) { 354 * pool.execute(() -> processData(data.get(i), i)); 355 * } 356 * } 357 * 358 * @param traceTag The trace tag. 359 * @param trackName The track where the event should appear in the trace. 360 * @param methodName The method name to appear in the trace. 361 * @param cookie Unique identifier used for nesting events on a single 362 * track. Events which overlap without nesting on the same 363 * track must have different values for cookie. 364 * 365 * @hide 366 */ asyncTraceForTrackBegin(long traceTag, @NonNull String trackName, @NonNull String methodName, int cookie)367 public static void asyncTraceForTrackBegin(long traceTag, 368 @NonNull String trackName, @NonNull String methodName, int cookie) { 369 if (isTagEnabled(traceTag)) { 370 nativeAsyncTraceForTrackBegin(traceTag, trackName, methodName, cookie); 371 } 372 } 373 374 /** 375 * Writes a trace message to indicate that the current method has ended. 376 * Must be called exactly once for each call to 377 * {@link #asyncTraceForTrackBegin(long, String, String, int)} 378 * using the same tag, track name, and cookie. 379 * 380 * See the documentation for {@link #asyncTraceForTrackBegin(long, String, String, int)}. 381 * for inteded usage of this method. 382 * 383 * @param traceTag The trace tag. 384 * @param trackName The track where the event should appear in the trace. 385 * @param cookie Unique identifier used for nesting events on a single 386 * track. Events which overlap without nesting on the same 387 * track must have different values for cookie. 388 * 389 * @hide 390 */ asyncTraceForTrackEnd(long traceTag, @NonNull String trackName, int cookie)391 public static void asyncTraceForTrackEnd(long traceTag, 392 @NonNull String trackName, int cookie) { 393 if (isTagEnabled(traceTag)) { 394 nativeAsyncTraceForTrackEnd(traceTag, trackName, cookie); 395 } 396 } 397 398 /** 399 * Writes a trace message to indicate that a given section of code was invoked. 400 * 401 * @param traceTag The trace tag. 402 * @param methodName The method name to appear in the trace. 403 * @hide 404 */ instant(long traceTag, String methodName)405 public static void instant(long traceTag, String methodName) { 406 if (isTagEnabled(traceTag)) { 407 nativeInstant(traceTag, methodName); 408 } 409 } 410 411 /** 412 * Writes a trace message to indicate that a given section of code was invoked. 413 * 414 * @param traceTag The trace tag. 415 * @param trackName The track where the event should appear in the trace. 416 * @param methodName The method name to appear in the trace. 417 * @hide 418 */ instantForTrack(long traceTag, String trackName, String methodName)419 public static void instantForTrack(long traceTag, String trackName, String methodName) { 420 if (isTagEnabled(traceTag)) { 421 nativeInstantForTrack(traceTag, trackName, methodName); 422 } 423 } 424 425 /** 426 * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate 427 * string creation for trace sections that require formatting. It is not necessary 428 * to guard all Trace method calls as they internally already check this. However it is 429 * recommended to use this to prevent creating any temporary objects that would then be 430 * passed to those methods to reduce runtime cost when tracing isn't enabled. 431 * 432 * @return true if tracing is currently enabled, false otherwise 433 */ isEnabled()434 public static boolean isEnabled() { 435 return isTagEnabled(TRACE_TAG_APP); 436 } 437 438 /** 439 * Writes a trace message to indicate that a given section of code has begun. This call must 440 * be followed by a corresponding call to {@link #endSection()} on the same thread. 441 * 442 * <p class="note"> At this time the vertical bar character '|', newline character '\n', and 443 * null character '\0' are used internally by the tracing mechanism. If sectionName contains 444 * these characters they will be replaced with a space character in the trace. 445 * 446 * @param sectionName The name of the code section to appear in the trace. This may be at 447 * most 127 Unicode code units long. 448 */ beginSection(@onNull String sectionName)449 public static void beginSection(@NonNull String sectionName) { 450 if (isTagEnabled(TRACE_TAG_APP)) { 451 if (sectionName.length() > MAX_SECTION_NAME_LEN) { 452 throw new IllegalArgumentException("sectionName is too long"); 453 } 454 nativeTraceBegin(TRACE_TAG_APP, sectionName); 455 } 456 } 457 458 /** 459 * Writes a trace message to indicate that a given section of code has ended. This call must 460 * be preceeded by a corresponding call to {@link #beginSection(String)}. Calling this method 461 * will mark the end of the most recently begun section of code, so care must be taken to 462 * ensure that beginSection / endSection pairs are properly nested and called from the same 463 * thread. 464 */ endSection()465 public static void endSection() { 466 if (isTagEnabled(TRACE_TAG_APP)) { 467 nativeTraceEnd(TRACE_TAG_APP); 468 } 469 } 470 471 /** 472 * Writes a trace message to indicate that a given section of code has 473 * begun. Must be followed by a call to {@link #endAsyncSection(String, int)} with the same 474 * methodName and cookie. Unlike {@link #beginSection(String)} and {@link #endSection()}, 475 * asynchronous events do not need to be nested. The name and cookie used to 476 * begin an event must be used to end it. 477 * 478 * @param methodName The method name to appear in the trace. 479 * @param cookie Unique identifier for distinguishing simultaneous events 480 */ beginAsyncSection(@onNull String methodName, int cookie)481 public static void beginAsyncSection(@NonNull String methodName, int cookie) { 482 asyncTraceBegin(TRACE_TAG_APP, methodName, cookie); 483 } 484 485 /** 486 * Writes a trace message to indicate that the current method has ended. 487 * Must be called exactly once for each call to {@link #beginAsyncSection(String, int)} 488 * using the same name and cookie. 489 * 490 * @param methodName The method name to appear in the trace. 491 * @param cookie Unique identifier for distinguishing simultaneous events 492 */ endAsyncSection(@onNull String methodName, int cookie)493 public static void endAsyncSection(@NonNull String methodName, int cookie) { 494 asyncTraceEnd(TRACE_TAG_APP, methodName, cookie); 495 } 496 497 /** 498 * Writes trace message to indicate the value of a given counter. 499 * 500 * @param counterName The counter name to appear in the trace. 501 * @param counterValue The counter value. 502 */ setCounter(@onNull String counterName, long counterValue)503 public static void setCounter(@NonNull String counterName, long counterValue) { 504 if (isTagEnabled(TRACE_TAG_APP)) { 505 nativeTraceCounter(TRACE_TAG_APP, counterName, counterValue); 506 } 507 } 508 } 509