Home | History | Annotate | Download | only in os
      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 android.util.Log;
     20 
     21 /**
     22  * Writes trace events to the kernel trace buffer.  These trace events can be
     23  * collected using the "atrace" program for offline analysis.
     24  *
     25  * This tracing mechanism is independent of the method tracing mechanism
     26  * offered by {@link Debug#startMethodTracing}.  In particular, it enables
     27  * tracing of events that occur across processes.
     28  *
     29  * @hide
     30  */
     31 public final class Trace {
     32     private static final String TAG = "Trace";
     33 
     34     // These tags must be kept in sync with frameworks/native/include/utils/Trace.h.
     35     public static final long TRACE_TAG_NEVER = 0;
     36     public static final long TRACE_TAG_ALWAYS = 1L << 0;
     37     public static final long TRACE_TAG_GRAPHICS = 1L << 1;
     38     public static final long TRACE_TAG_INPUT = 1L << 2;
     39     public static final long TRACE_TAG_VIEW = 1L << 3;
     40     public static final long TRACE_TAG_WEBVIEW = 1L << 4;
     41     public static final long TRACE_TAG_WINDOW_MANAGER = 1L << 5;
     42     public static final long TRACE_TAG_ACTIVITY_MANAGER = 1L << 6;
     43     public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7;
     44     public static final long TRACE_TAG_AUDIO = 1L << 8;
     45     public static final long TRACE_TAG_VIDEO = 1L << 9;
     46     public static final long TRACE_TAG_CAMERA = 1L << 10;
     47 
     48     public static final int TRACE_FLAGS_START_BIT = 1;
     49     public static final String[] TRACE_TAGS = {
     50         "Graphics", "Input", "View", "WebView", "Window Manager",
     51         "Activity Manager", "Sync Manager", "Audio", "Video", "Camera",
     52     };
     53 
     54     public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags";
     55 
     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;
     61 
     62     private static native long nativeGetEnabledTags();
     63     private static native void nativeTraceCounter(long tag, String name, int value);
     64     private static native void nativeTraceBegin(long tag, String name);
     65     private static native void nativeTraceEnd(long tag);
     66 
     67     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.
     76         SystemProperties.addChangeCallback(new Runnable() {
     77             @Override public void run() {
     78                 cacheEnabledTags();
     79             }
     80         });
     81     }
     82 
     83     private Trace() {
     84     }
     85 
     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 
    110     /**
    111      * Returns true if a trace tag is enabled.
    112      *
    113      * @param traceTag The trace tag to check.
    114      * @return True if the trace tag is valid.
    115      */
    116     public static boolean isTagEnabled(long traceTag) {
    117         long tags = sEnabledTags;
    118         if (tags == TRACE_FLAGS_NOT_READY) {
    119             tags = cacheEnabledTags();
    120         }
    121         return (tags & traceTag) != 0;
    122     }
    123 
    124     /**
    125      * Writes trace message to indicate the value of a given counter.
    126      *
    127      * @param traceTag The trace tag.
    128      * @param counterName The counter name to appear in the trace.
    129      * @param counterValue The counter value.
    130      */
    131     public static void traceCounter(long traceTag, String counterName, int counterValue) {
    132         if (isTagEnabled(traceTag)) {
    133             nativeTraceCounter(traceTag, counterName, counterValue);
    134         }
    135     }
    136 
    137     /**
    138      * Writes a trace message to indicate that a given method has begun.
    139      * Must be followed by a call to {@link #traceEnd} using the same tag.
    140      *
    141      * @param traceTag The trace tag.
    142      * @param methodName The method name to appear in the trace.
    143      */
    144     public static void traceBegin(long traceTag, String methodName) {
    145         if (isTagEnabled(traceTag)) {
    146             nativeTraceBegin(traceTag, methodName);
    147         }
    148     }
    149 
    150     /**
    151      * Writes a trace message to indicate that the current method has ended.
    152      * Must be called exactly once for each call to {@link #traceBegin} using the same tag.
    153      *
    154      * @param traceTag The trace tag.
    155      */
    156     public static void traceEnd(long traceTag) {
    157         if (isTagEnabled(traceTag)) {
    158             nativeTraceEnd(traceTag);
    159         }
    160     }
    161 }
    162