Home | History | Annotate | Download | only in utils
      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 #ifndef ANDROID_TRACE_H
     18 #define ANDROID_TRACE_H
     19 
     20 #include <fcntl.h>
     21 #include <stdint.h>
     22 #include <stdio.h>
     23 #include <string.h>
     24 #include <sys/stat.h>
     25 #include <sys/types.h>
     26 #include <unistd.h>
     27 
     28 #include <cutils/compiler.h>
     29 #include <utils/threads.h>
     30 
     31 // The ATRACE_TAG macro can be defined before including this header to trace
     32 // using one of the tags defined below.  It must be defined to one of the
     33 // following ATRACE_TAG_* macros.  The trace tag is used to filter tracing in
     34 // userland to avoid some of the runtime cost of tracing when it is not desired.
     35 //
     36 // Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
     37 // being enabled - this should ONLY be done for debug code, as userland tracing
     38 // has a performance cost even when the trace is not being recorded.  Defining
     39 // ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
     40 // in the tracing always being disabled.
     41 //
     42 // These tags must be kept in sync with frameworks/base/core/java/android/os/Trace.java.
     43 #define ATRACE_TAG_NEVER            0       // The "never" tag is never enabled.
     44 #define ATRACE_TAG_ALWAYS           (1<<0)  // The "always" tag is always enabled.
     45 #define ATRACE_TAG_GRAPHICS         (1<<1)
     46 #define ATRACE_TAG_INPUT            (1<<2)
     47 #define ATRACE_TAG_VIEW             (1<<3)
     48 #define ATRACE_TAG_WEBVIEW          (1<<4)
     49 #define ATRACE_TAG_WINDOW_MANAGER   (1<<5)
     50 #define ATRACE_TAG_ACTIVITY_MANAGER (1<<6)
     51 #define ATRACE_TAG_SYNC_MANAGER     (1<<7)
     52 #define ATRACE_TAG_AUDIO            (1<<8)
     53 #define ATRACE_TAG_VIDEO            (1<<9)
     54 #define ATRACE_TAG_LAST             ATRACE_TAG_VIDEO
     55 
     56 #define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
     57 
     58 #ifndef ATRACE_TAG
     59 #define ATRACE_TAG ATRACE_TAG_NEVER
     60 #elif ATRACE_TAG > ATRACE_TAG_LAST
     61 #error ATRACE_TAG must be defined to be one of the tags defined in utils/Trace.h
     62 #endif
     63 
     64 // ATRACE_CALL traces the beginning and end of the current function.  To trace
     65 // the correct start and end times this macro should be the first line of the
     66 // function body.
     67 #define ATRACE_CALL() android::ScopedTrace ___tracer(ATRACE_TAG, __FUNCTION__)
     68 
     69 // ATRACE_INT traces a named integer value.  This can be used to track how the
     70 // value changes over time in a trace.
     71 #define ATRACE_INT(name, value) android::Tracer::traceCounter(ATRACE_TAG, name, value)
     72 
     73 // ATRACE_ENABLED returns true if the trace tag is enabled.  It can be used as a
     74 // guard condition around more expensive trace calculations.
     75 #define ATRACE_ENABLED() android::Tracer::isTagEnabled(ATRACE_TAG)
     76 
     77 namespace android {
     78 
     79 class Tracer {
     80 
     81 public:
     82 
     83     static uint64_t getEnabledTags() {
     84         initIfNeeded();
     85         return sEnabledTags;
     86     }
     87 
     88     static inline bool isTagEnabled(uint64_t tag) {
     89         initIfNeeded();
     90         return sEnabledTags & tag;
     91     }
     92 
     93     static inline void traceCounter(uint64_t tag, const char* name,
     94             int32_t value) {
     95         if (CC_UNLIKELY(isTagEnabled(tag))) {
     96             char buf[1024];
     97             snprintf(buf, 1024, "C|%d|%s|%d", getpid(), name, value);
     98             write(sTraceFD, buf, strlen(buf));
     99         }
    100     }
    101 
    102     static inline void traceBegin(uint64_t tag, const char* name) {
    103         if (CC_UNLIKELY(isTagEnabled(tag))) {
    104             char buf[1024];
    105             size_t len = snprintf(buf, 1024, "B|%d|%s", getpid(), name);
    106             write(sTraceFD, buf, len);
    107         }
    108     }
    109 
    110    static inline void traceEnd(uint64_t tag) {
    111         if (CC_UNLIKELY(isTagEnabled(tag))) {
    112             char buf = 'E';
    113             write(sTraceFD, &buf, 1);
    114         }
    115     }
    116 
    117 private:
    118 
    119     static inline void initIfNeeded() {
    120         if (!android_atomic_acquire_load(&sIsReady)) {
    121             init();
    122         }
    123     }
    124 
    125     static void changeCallback();
    126 
    127     // init opens the trace marker file for writing and reads the
    128     // atrace.tags.enableflags system property.  It does this only the first
    129     // time it is run, using sMutex for synchronization.
    130     static void init();
    131 
    132     // retrieve the current value of the system property.
    133     static void loadSystemProperty();
    134 
    135     // sIsReady is a boolean value indicating whether a call to init() has
    136     // completed in this process.  It is initialized to 0 and set to 1 when the
    137     // first init() call completes.  It is set to 1 even if a failure occurred
    138     // in init (e.g. the trace marker file couldn't be opened).
    139     //
    140     // This should be checked by all tracing functions using an atomic acquire
    141     // load operation before calling init().  This check avoids the need to lock
    142     // a mutex each time a trace function gets called.
    143     static volatile int32_t sIsReady;
    144 
    145     // sTraceFD is the file descriptor used to write to the kernel's trace
    146     // buffer.  It is initialized to -1 and set to an open file descriptor in
    147     // init() while a lock on sMutex is held.
    148     //
    149     // This should only be used by a trace function after init() has
    150     // successfully completed.
    151     static int sTraceFD;
    152 
    153     // sEnabledTags is the set of tag bits for which tracing is currently
    154     // enabled.  It is initialized to 0 and set based on the
    155     // atrace.tags.enableflags system property in init() while a lock on sMutex
    156     // is held.
    157     //
    158     // This should only be used by a trace function after init() has
    159     // successfully completed.
    160     //
    161     // This value is only ever non-zero when tracing is initialized and sTraceFD is not -1.
    162     static uint64_t sEnabledTags;
    163 
    164     // sMutex is used to protect the execution of init().
    165     static Mutex sMutex;
    166 };
    167 
    168 class ScopedTrace {
    169 
    170 public:
    171     inline ScopedTrace(uint64_t tag, const char* name) :
    172             mTag(tag) {
    173         Tracer::traceBegin(mTag, name);
    174     }
    175 
    176     inline ~ScopedTrace() {
    177         Tracer::traceEnd(mTag);
    178     }
    179 
    180 private:
    181 
    182     uint64_t mTag;
    183 };
    184 
    185 }; // namespace android
    186 
    187 #endif // ANDROID_TRACE_H
    188