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 public static final long TRACE_TAG_AIDL = 1L << 24; 104 /** @hide */ 105 public static final long TRACE_TAG_NNAPI = 1L << 25; 106 /** @hide */ 107 public static final long TRACE_TAG_RRO = 1L << 26; 108 /** @hide */ 109 public static final long TRACE_TAG_THERMAL = 1L << 27; 110 111 private static final long TRACE_TAG_NOT_READY = 1L << 63; 112 /** @hide **/ 113 public static final int MAX_SECTION_NAME_LEN = 127; 114 115 // Must be volatile to avoid word tearing. 116 // This is only kept in case any apps get this by reflection but do not 117 // check the return value for null. 118 @UnsupportedAppUsage 119 private static volatile long sEnabledTags = TRACE_TAG_NOT_READY; 120 121 private static int sZygoteDebugFlags = 0; 122 123 @UnsupportedAppUsage 124 @CriticalNative nativeGetEnabledTags()125 private static native long nativeGetEnabledTags(); nativeSetAppTracingAllowed(boolean allowed)126 private static native void nativeSetAppTracingAllowed(boolean allowed); nativeSetTracingEnabled(boolean allowed)127 private static native void nativeSetTracingEnabled(boolean allowed); 128 129 @FastNative nativeTraceCounter(long tag, String name, long value)130 private static native void nativeTraceCounter(long tag, String name, long value); 131 @FastNative nativeTraceBegin(long tag, String name)132 private static native void nativeTraceBegin(long tag, String name); 133 @FastNative nativeTraceEnd(long tag)134 private static native void nativeTraceEnd(long tag); 135 @FastNative nativeAsyncTraceBegin(long tag, String name, int cookie)136 private static native void nativeAsyncTraceBegin(long tag, String name, int cookie); 137 @FastNative nativeAsyncTraceEnd(long tag, String name, int cookie)138 private static native void nativeAsyncTraceEnd(long tag, String name, int cookie); 139 @FastNative nativeAsyncTraceForTrackBegin(long tag, String trackName, String name, int cookie)140 private static native void nativeAsyncTraceForTrackBegin(long tag, 141 String trackName, String name, int cookie); 142 @FastNative nativeAsyncTraceForTrackEnd(long tag, String trackName, String name, int cookie)143 private static native void nativeAsyncTraceForTrackEnd(long tag, 144 String trackName, String name, int cookie); 145 @FastNative nativeInstant(long tag, String name)146 private static native void nativeInstant(long tag, String name); 147 @FastNative nativeInstantForTrack(long tag, String trackName, String name)148 private static native void nativeInstantForTrack(long tag, String trackName, String name); 149 Trace()150 private Trace() { 151 } 152 153 /** 154 * Returns true if a trace tag is enabled. 155 * 156 * @param traceTag The trace tag to check. 157 * @return True if the trace tag is valid. 158 * 159 * @hide 160 */ 161 @UnsupportedAppUsage 162 @SystemApi(client = MODULE_LIBRARIES) isTagEnabled(long traceTag)163 public static boolean isTagEnabled(long traceTag) { 164 long tags = nativeGetEnabledTags(); 165 return (tags & traceTag) != 0; 166 } 167 168 /** 169 * Writes trace message to indicate the value of a given counter. 170 * 171 * @param traceTag The trace tag. 172 * @param counterName The counter name to appear in the trace. 173 * @param counterValue The counter value. 174 * 175 * @hide 176 */ 177 @UnsupportedAppUsage 178 @SystemApi(client = MODULE_LIBRARIES) traceCounter(long traceTag, @NonNull String counterName, int counterValue)179 public static void traceCounter(long traceTag, @NonNull String counterName, int counterValue) { 180 if (isTagEnabled(traceTag)) { 181 nativeTraceCounter(traceTag, counterName, counterValue); 182 } 183 } 184 185 /** 186 * From Android S, this is no-op. 187 * 188 * Before, set whether application tracing is allowed for this process. This is intended to be 189 * set once at application start-up time based on whether the application is debuggable. 190 * 191 * @hide 192 */ 193 @UnsupportedAppUsage setAppTracingAllowed(boolean allowed)194 public static void setAppTracingAllowed(boolean allowed) { 195 nativeSetAppTracingAllowed(allowed); 196 } 197 198 /** 199 * Set whether tracing is enabled in this process. 200 * @hide 201 */ setTracingEnabled(boolean enabled, int debugFlags)202 public static void setTracingEnabled(boolean enabled, int debugFlags) { 203 nativeSetTracingEnabled(enabled); 204 sZygoteDebugFlags = debugFlags; 205 } 206 207 /** 208 * Writes a trace message to indicate that a given section of code has 209 * begun. Must be followed by a call to {@link #traceEnd} using the same 210 * tag. 211 * 212 * @param traceTag The trace tag. 213 * @param methodName The method name to appear in the trace. 214 * 215 * @hide 216 */ 217 @UnsupportedAppUsage 218 @SystemApi(client = MODULE_LIBRARIES) traceBegin(long traceTag, @NonNull String methodName)219 public static void traceBegin(long traceTag, @NonNull String methodName) { 220 if (isTagEnabled(traceTag)) { 221 nativeTraceBegin(traceTag, methodName); 222 } 223 } 224 225 /** 226 * Writes a trace message to indicate that the current method has ended. 227 * Must be called exactly once for each call to {@link #traceBegin} using the same tag. 228 * 229 * @param traceTag The trace tag. 230 * 231 * @hide 232 */ 233 @UnsupportedAppUsage 234 @SystemApi(client = MODULE_LIBRARIES) traceEnd(long traceTag)235 public static void traceEnd(long traceTag) { 236 if (isTagEnabled(traceTag)) { 237 nativeTraceEnd(traceTag); 238 } 239 } 240 241 /** 242 * Writes a trace message to indicate that a given section of code has 243 * begun. Must be followed by a call to {@link #asyncTraceEnd} using the same 244 * tag. Unlike {@link #traceBegin(long, String)} and {@link #traceEnd(long)}, 245 * asynchronous events do not need to be nested. The name and cookie used to 246 * begin an event must be used to end it. 247 * 248 * @param traceTag The trace tag. 249 * @param methodName The method name to appear in the trace. 250 * @param cookie Unique identifier for distinguishing simultaneous events 251 * 252 * @hide 253 */ 254 @UnsupportedAppUsage 255 @SystemApi(client = MODULE_LIBRARIES) asyncTraceBegin(long traceTag, @NonNull String methodName, int cookie)256 public static void asyncTraceBegin(long traceTag, @NonNull String methodName, int cookie) { 257 if (isTagEnabled(traceTag)) { 258 nativeAsyncTraceBegin(traceTag, methodName, cookie); 259 } 260 } 261 262 /** 263 * Writes a trace message to indicate that the current method has ended. 264 * Must be called exactly once for each call to {@link #asyncTraceBegin(long, String, int)} 265 * using the same tag, name and cookie. 266 * 267 * @param traceTag The trace tag. 268 * @param methodName The method name to appear in the trace. 269 * @param cookie Unique identifier for distinguishing simultaneous events 270 * 271 * @hide 272 */ 273 @UnsupportedAppUsage 274 @SystemApi(client = MODULE_LIBRARIES) asyncTraceEnd(long traceTag, @NonNull String methodName, int cookie)275 public static void asyncTraceEnd(long traceTag, @NonNull String methodName, int cookie) { 276 if (isTagEnabled(traceTag)) { 277 nativeAsyncTraceEnd(traceTag, methodName, cookie); 278 } 279 } 280 281 282 /** 283 * Writes a trace message to indicate that a given section of code has 284 * begun. Must be followed by a call to {@link #asyncTraceForTrackEnd} using the same 285 * tag. This function operates exactly like {@link #asyncTraceBegin(long, String, int)}, 286 * except with the inclusion of a track name argument for where this method should appear. 287 * 288 * @param traceTag The trace tag. 289 * @param trackName The track where the event should appear in the trace. 290 * @param methodName The method name to appear in the trace. 291 * @param cookie Unique identifier for distinguishing simultaneous events 292 * 293 * @hide 294 */ asyncTraceForTrackBegin(long traceTag, @NonNull String trackName, @NonNull String methodName, int cookie)295 public static void asyncTraceForTrackBegin(long traceTag, 296 @NonNull String trackName, @NonNull String methodName, int cookie) { 297 if (isTagEnabled(traceTag)) { 298 nativeAsyncTraceForTrackBegin(traceTag, trackName, methodName, cookie); 299 } 300 } 301 302 /** 303 * Writes a trace message to indicate that the current method has ended. 304 * Must be called exactly once for each call to 305 * {@link #asyncTraceForTrackBegin(long, String, String, int)} 306 * using the same tag, track name, name and cookie. 307 * 308 * @param traceTag The trace tag. 309 * @param trackName The track where the event should appear in the trace. 310 * @param methodName The method name to appear in the trace. 311 * @param cookie Unique identifier for distinguishing simultaneous events 312 * 313 * @hide 314 */ asyncTraceForTrackEnd(long traceTag, @NonNull String trackName, @NonNull String methodName, int cookie)315 public static void asyncTraceForTrackEnd(long traceTag, 316 @NonNull String trackName, @NonNull String methodName, int cookie) { 317 if (isTagEnabled(traceTag)) { 318 nativeAsyncTraceForTrackEnd(traceTag, trackName, methodName, cookie); 319 } 320 } 321 322 /** 323 * Writes a trace message to indicate that a given section of code was invoked. 324 * 325 * @param traceTag The trace tag. 326 * @param methodName The method name to appear in the trace. 327 * @hide 328 */ instant(long traceTag, String methodName)329 public static void instant(long traceTag, String methodName) { 330 if (methodName == null) { 331 throw new IllegalArgumentException("methodName cannot be null"); 332 } 333 if (isTagEnabled(traceTag)) { 334 nativeInstant(traceTag, methodName); 335 } 336 } 337 338 /** 339 * Writes a trace message to indicate that a given section of code was invoked. 340 * 341 * @param traceTag The trace tag. 342 * @param trackName The track where the event should appear in the trace. 343 * @param methodName The method name to appear in the trace. 344 * @hide 345 */ instantForTrack(long traceTag, String trackName, String methodName)346 public static void instantForTrack(long traceTag, String trackName, String methodName) { 347 if (trackName == null) { 348 throw new IllegalArgumentException("trackName cannot be null"); 349 } 350 if (methodName == null) { 351 throw new IllegalArgumentException("methodName cannot be null"); 352 } 353 if (isTagEnabled(traceTag)) { 354 nativeInstantForTrack(traceTag, trackName, methodName); 355 } 356 } 357 358 /** 359 * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate 360 * string creation for trace sections that require formatting. It is not necessary 361 * to guard all Trace method calls as they internally already check this. However it is 362 * recommended to use this to prevent creating any temporary objects that would then be 363 * passed to those methods to reduce runtime cost when tracing isn't enabled. 364 * 365 * @return true if tracing is currently enabled, false otherwise 366 */ isEnabled()367 public static boolean isEnabled() { 368 return isTagEnabled(TRACE_TAG_APP); 369 } 370 371 /** 372 * Writes a trace message to indicate that a given section of code has begun. This call must 373 * be followed by a corresponding call to {@link #endSection()} on the same thread. 374 * 375 * <p class="note"> At this time the vertical bar character '|', newline character '\n', and 376 * null character '\0' are used internally by the tracing mechanism. If sectionName contains 377 * these characters they will be replaced with a space character in the trace. 378 * 379 * @param sectionName The name of the code section to appear in the trace. This may be at 380 * most 127 Unicode code units long. 381 */ beginSection(@onNull String sectionName)382 public static void beginSection(@NonNull String sectionName) { 383 if (isTagEnabled(TRACE_TAG_APP)) { 384 if (sectionName.length() > MAX_SECTION_NAME_LEN) { 385 throw new IllegalArgumentException("sectionName is too long"); 386 } 387 nativeTraceBegin(TRACE_TAG_APP, sectionName); 388 } 389 } 390 391 /** 392 * Writes a trace message to indicate that a given section of code has ended. This call must 393 * be preceeded by a corresponding call to {@link #beginSection(String)}. Calling this method 394 * will mark the end of the most recently begun section of code, so care must be taken to 395 * ensure that beginSection / endSection pairs are properly nested and called from the same 396 * thread. 397 */ endSection()398 public static void endSection() { 399 if (isTagEnabled(TRACE_TAG_APP)) { 400 nativeTraceEnd(TRACE_TAG_APP); 401 } 402 } 403 404 /** 405 * Writes a trace message to indicate that a given section of code has 406 * begun. Must be followed by a call to {@link #endAsyncSection(String, int)} with the same 407 * methodName and cookie. Unlike {@link #beginSection(String)} and {@link #endSection()}, 408 * asynchronous events do not need to be nested. The name and cookie used to 409 * begin an event must be used to end it. 410 * 411 * @param methodName The method name to appear in the trace. 412 * @param cookie Unique identifier for distinguishing simultaneous events 413 */ beginAsyncSection(@onNull String methodName, int cookie)414 public static void beginAsyncSection(@NonNull String methodName, int cookie) { 415 asyncTraceBegin(TRACE_TAG_APP, methodName, cookie); 416 } 417 418 /** 419 * Writes a trace message to indicate that the current method has ended. 420 * Must be called exactly once for each call to {@link #beginAsyncSection(String, int)} 421 * using the same name and cookie. 422 * 423 * @param methodName The method name to appear in the trace. 424 * @param cookie Unique identifier for distinguishing simultaneous events 425 */ endAsyncSection(@onNull String methodName, int cookie)426 public static void endAsyncSection(@NonNull String methodName, int cookie) { 427 asyncTraceEnd(TRACE_TAG_APP, methodName, cookie); 428 } 429 430 /** 431 * Writes trace message to indicate the value of a given counter. 432 * 433 * @param counterName The counter name to appear in the trace. 434 * @param counterValue The counter value. 435 */ setCounter(@onNull String counterName, long counterValue)436 public static void setCounter(@NonNull String counterName, long counterValue) { 437 if (isTagEnabled(TRACE_TAG_APP)) { 438 nativeTraceCounter(TRACE_TAG_APP, counterName, counterValue); 439 } 440 } 441 } 442