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_CAMERA           (1<<10)
     55 #define ATRACE_TAG_LAST             ATRACE_TAG_CAMERA
     56 
     57 #define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
     58 
     59 #ifndef ATRACE_TAG
     60 #define ATRACE_TAG ATRACE_TAG_NEVER
     61 #elif ATRACE_TAG > ATRACE_TAG_LAST
     62 #error ATRACE_TAG must be defined to be one of the tags defined in utils/Trace.h
     63 #endif
     64 
     65 // ATRACE_CALL traces the beginning and end of the current function.  To trace
     66 // the correct start and end times this macro should be the first line of the
     67 // function body.
     68 #define ATRACE_CALL() android::ScopedTrace ___tracer(ATRACE_TAG, __FUNCTION__)
     69 
     70 // ATRACE_NAME traces the beginning and end of the current function.  To trace
     71 // the correct start and end times this macro should be the first line of the
     72 // function body.
     73 #define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)
     74 
     75 // ATRACE_INT traces a named integer value.  This can be used to track how the
     76 // value changes over time in a trace.
     77 #define ATRACE_INT(name, value) android::Tracer::traceCounter(ATRACE_TAG, name, value)
     78 
     79 // ATRACE_ENABLED returns true if the trace tag is enabled.  It can be used as a
     80 // guard condition around more expensive trace calculations.
     81 #define ATRACE_ENABLED() android::Tracer::isTagEnabled(ATRACE_TAG)
     82 
     83 namespace android {
     84 
     85 class Tracer {
     86 
     87 public:
     88 
     89     static uint64_t getEnabledTags() {
     90         initIfNeeded();
     91         return sEnabledTags;
     92     }
     93 
     94     static inline bool isTagEnabled(uint64_t tag) {
     95         initIfNeeded();
     96         return sEnabledTags & tag;
     97     }
     98 
     99     static inline void traceCounter(uint64_t tag, const char* name,
    100             int32_t value) {
    101         if (CC_UNLIKELY(isTagEnabled(tag))) {
    102             char buf[1024];
    103             snprintf(buf, 1024, "C|%d|%s|%d", getpid(), name, value);
    104             write(sTraceFD, buf, strlen(buf));
    105         }
    106     }
    107 
    108     static inline void traceBegin(uint64_t tag, const char* name) {
    109         if (CC_UNLIKELY(isTagEnabled(tag))) {
    110             char buf[1024];
    111             size_t len = snprintf(buf, 1024, "B|%d|%s", getpid(), name);
    112             write(sTraceFD, buf, len);
    113         }
    114     }
    115 
    116    static inline void traceEnd(uint64_t tag) {
    117         if (CC_UNLIKELY(isTagEnabled(tag))) {
    118             char buf = 'E';
    119             write(sTraceFD, &buf, 1);
    120         }
    121     }
    122 
    123 private:
    124 
    125     static inline void initIfNeeded() {
    126         if (!android_atomic_acquire_load(&sIsReady)) {
    127             init();
    128         }
    129     }
    130 
    131     static void changeCallback();
    132 
    133     // init opens the trace marker file for writing and reads the
    134     // atrace.tags.enableflags system property.  It does this only the first
    135     // time it is run, using sMutex for synchronization.
    136     static void init();
    137 
    138     // retrieve the current value of the system property.
    139     static void loadSystemProperty();
    140 
    141     // sIsReady is a boolean value indicating whether a call to init() has
    142     // completed in this process.  It is initialized to 0 and set to 1 when the
    143     // first init() call completes.  It is set to 1 even if a failure occurred
    144     // in init (e.g. the trace marker file couldn't be opened).
    145     //
    146     // This should be checked by all tracing functions using an atomic acquire
    147     // load operation before calling init().  This check avoids the need to lock
    148     // a mutex each time a trace function gets called.
    149     static volatile int32_t sIsReady;
    150 
    151     // sTraceFD is the file descriptor used to write to the kernel's trace
    152     // buffer.  It is initialized to -1 and set to an open file descriptor in
    153     // init() while a lock on sMutex is held.
    154     //
    155     // This should only be used by a trace function after init() has
    156     // successfully completed.
    157     static int sTraceFD;
    158 
    159     // sEnabledTags is the set of tag bits for which tracing is currently
    160     // enabled.  It is initialized to 0 and set based on the
    161     // atrace.tags.enableflags system property in init() while a lock on sMutex
    162     // is held.
    163     //
    164     // This should only be used by a trace function after init() has
    165     // successfully completed.
    166     //
    167     // This value is only ever non-zero when tracing is initialized and sTraceFD is not -1.
    168     static uint64_t sEnabledTags;
    169 
    170     // sMutex is used to protect the execution of init().
    171     static Mutex sMutex;
    172 };
    173 
    174 class ScopedTrace {
    175 
    176 public:
    177     inline ScopedTrace(uint64_t tag, const char* name) :
    178             mTag(tag) {
    179         Tracer::traceBegin(mTag, name);
    180     }
    181 
    182     inline ~ScopedTrace() {
    183         Tracer::traceEnd(mTag);
    184     }
    185 
    186 private:
    187 
    188     uint64_t mTag;
    189 };
    190 
    191 }; // namespace android
    192 
    193 #endif // ANDROID_TRACE_H
    194