1616
1717package android .os ;
1818
19+ import android .util .Log ;
20+
1921/**
2022 * Writes trace events to the kernel trace buffer. These trace events can be
2123 * collected using the "atrace" program for offline analysis.
2729 * @hide
2830 */
2931public final class Trace {
32+ private static final String TAG = "Trace" ;
33+
3034 // These tags must be kept in sync with frameworks/native/include/utils/Trace.h.
3135 public static final long TRACE_TAG_NEVER = 0 ;
3236 public static final long TRACE_TAG_ALWAYS = 1L << 0 ;
@@ -49,32 +53,72 @@ public final class Trace {
4953
5054 public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags" ;
5155
52- private static long sEnabledTags = nativeGetEnabledTags ();
56+ // This works as a "not ready" flag because TRACE_TAG_ALWAYS is always set.
57+ private static final long TRACE_FLAGS_NOT_READY = 0 ;
58+
59+ // Must be volatile to avoid word tearing.
60+ private static volatile long sEnabledTags = TRACE_FLAGS_NOT_READY ;
5361
5462 private static native long nativeGetEnabledTags ();
5563 private static native void nativeTraceCounter (long tag , String name , int value );
5664 private static native void nativeTraceBegin (long tag , String name );
5765 private static native void nativeTraceEnd (long tag );
5866
5967 static {
68+ // We configure two separate change callbacks, one in Trace.cpp and one here. The
69+ // native callback reads the tags from the system property, and this callback
70+ // reads the value that the native code retrieved. It's essential that the native
71+ // callback executes first.
72+ //
73+ // The system provides ordering through a priority level. Callbacks made through
74+ // SystemProperties.addChangeCallback currently have a negative priority, while
75+ // our native code is using a priority of zero.
6076 SystemProperties .addChangeCallback (new Runnable () {
6177 @ Override public void run () {
62- sEnabledTags = nativeGetEnabledTags ();
78+ cacheEnabledTags ();
6379 }
6480 });
6581 }
6682
6783 private Trace () {
6884 }
6985
86+ /**
87+ * Caches a copy of the enabled-tag bits. The "master" copy is held by the native code,
88+ * and comes from the PROPERTY_TRACE_TAG_ENABLEFLAGS property.
89+ * <p>
90+ * If the native code hasn't yet read the property, we will cause it to do one-time
91+ * initialization. We don't want to do this during class init, because this class is
92+ * preloaded, so all apps would be stuck with whatever the zygote saw. (The zygote
93+ * doesn't see the system-property update broadcasts.)
94+ * <p>
95+ * We want to defer initialization until the first use by an app, post-zygote.
96+ * <p>
97+ * We're okay if multiple threads call here simultaneously -- the native state is
98+ * synchronized, and sEnabledTags is volatile (prevents word tearing).
99+ */
100+ private static long cacheEnabledTags () {
101+ long tags = nativeGetEnabledTags ();
102+ if (tags == TRACE_FLAGS_NOT_READY ) {
103+ Log .w (TAG , "Unexpected value from nativeGetEnabledTags: " + tags );
104+ // keep going
105+ }
106+ sEnabledTags = tags ;
107+ return tags ;
108+ }
109+
70110 /**
71111 * Returns true if a trace tag is enabled.
72112 *
73113 * @param traceTag The trace tag to check.
74114 * @return True if the trace tag is valid.
75115 */
76116 public static boolean isTagEnabled (long traceTag ) {
77- return (sEnabledTags & traceTag ) != 0 ;
117+ long tags = sEnabledTags ;
118+ if (tags == TRACE_FLAGS_NOT_READY ) {
119+ tags = cacheEnabledTags ();
120+ }
121+ return (tags & traceTag ) != 0 ;
78122 }
79123
80124 /**
@@ -85,7 +129,7 @@ public static boolean isTagEnabled(long traceTag) {
85129 * @param counterValue The counter value.
86130 */
87131 public static void traceCounter (long traceTag , String counterName , int counterValue ) {
88- if (( sEnabledTags & traceTag ) != 0 ) {
132+ if (isTagEnabled ( traceTag )) {
89133 nativeTraceCounter (traceTag , counterName , counterValue );
90134 }
91135 }
@@ -98,7 +142,7 @@ public static void traceCounter(long traceTag, String counterName, int counterVa
98142 * @param methodName The method name to appear in the trace.
99143 */
100144 public static void traceBegin (long traceTag , String methodName ) {
101- if (( sEnabledTags & traceTag ) != 0 ) {
145+ if (isTagEnabled ( traceTag )) {
102146 nativeTraceBegin (traceTag , methodName );
103147 }
104148 }
@@ -110,7 +154,7 @@ public static void traceBegin(long traceTag, String methodName) {
110154 * @param traceTag The trace tag.
111155 */
112156 public static void traceEnd (long traceTag ) {
113- if (( sEnabledTags & traceTag ) != 0 ) {
157+ if (isTagEnabled ( traceTag )) {
114158 nativeTraceEnd (traceTag );
115159 }
116160 }
0 commit comments