summaryrefslogtreecommitdiffstats
path: root/include/utils/Trace.h
blob: 41bce009597e31eac3fc91f8b48efcd800391ca3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_TRACE_H
#define ANDROID_TRACE_H

#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <cutils/compiler.h>
#include <utils/threads.h>

// The ATRACE_TAG macro can be defined before including this header to trace
// using one of the tags defined below.  It must be defined to one of the
// following ATRACE_TAG_* macros.  The trace tag is used to filter tracing in
// userland to avoid some of the runtime cost of tracing when it is not desired.
//
// Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
// being enabled - this should ONLY be done for debug code, as userland tracing
// has a performance cost even when the trace is not being recorded.  Defining
// ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
// in the tracing always being disabled.
//
// These tags must be kept in sync with frameworks/base/core/java/android/os/Trace.java.
#define ATRACE_TAG_NEVER            0       // The "never" tag is never enabled.
#define ATRACE_TAG_ALWAYS           (1<<0)  // The "always" tag is always enabled.
#define ATRACE_TAG_GRAPHICS         (1<<1)
#define ATRACE_TAG_INPUT            (1<<2)
#define ATRACE_TAG_VIEW             (1<<3)
#define ATRACE_TAG_WEBVIEW          (1<<4)
#define ATRACE_TAG_WINDOW_MANAGER   (1<<5)
#define ATRACE_TAG_ACTIVITY_MANAGER (1<<6)
#define ATRACE_TAG_SYNC_MANAGER     (1<<7)
#define ATRACE_TAG_AUDIO            (1<<8)
#define ATRACE_TAG_VIDEO            (1<<9)
#define ATRACE_TAG_CAMERA           (1<<10)
#define ATRACE_TAG_LAST             ATRACE_TAG_CAMERA

#define ATRACE_TAG_NOT_READY        (1LL<<63)   // Reserved for use during init

#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)

#ifndef ATRACE_TAG
#define ATRACE_TAG ATRACE_TAG_NEVER
#elif ATRACE_TAG > ATRACE_TAG_LAST
#error ATRACE_TAG must be defined to be one of the tags defined in utils/Trace.h
#endif

// ATRACE_CALL traces the beginning and end of the current function.  To trace
// the correct start and end times this macro should be the first line of the
// function body.
#define ATRACE_CALL() android::ScopedTrace ___tracer(ATRACE_TAG, __FUNCTION__)

// ATRACE_NAME traces the beginning and end of the current function.  To trace
// the correct start and end times this macro should be the first line of the
// function body.
#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)

// ATRACE_INT traces a named integer value.  This can be used to track how the
// value changes over time in a trace.
#define ATRACE_INT(name, value) android::Tracer::traceCounter(ATRACE_TAG, name, value)

// ATRACE_ENABLED returns true if the trace tag is enabled.  It can be used as a
// guard condition around more expensive trace calculations.
#define ATRACE_ENABLED() android::Tracer::isTagEnabled(ATRACE_TAG)

namespace android {

class Tracer {

public:

    static uint64_t getEnabledTags() {
        initIfNeeded();
        return sEnabledTags;
    }

    static inline bool isTagEnabled(uint64_t tag) {
        initIfNeeded();
        return sEnabledTags & tag;
    }

    static inline void traceCounter(uint64_t tag, const char* name,
            int32_t value) {
        if (CC_UNLIKELY(isTagEnabled(tag))) {
            char buf[1024];
            snprintf(buf, 1024, "C|%d|%s|%d", getpid(), name, value);
            write(sTraceFD, buf, strlen(buf));
        }
    }

    static inline void traceBegin(uint64_t tag, const char* name) {
        if (CC_UNLIKELY(isTagEnabled(tag))) {
            char buf[1024];
            size_t len = snprintf(buf, 1024, "B|%d|%s", getpid(), name);
            write(sTraceFD, buf, len);
        }
    }

   static inline void traceEnd(uint64_t tag) {
        if (CC_UNLIKELY(isTagEnabled(tag))) {
            char buf = 'E';
            write(sTraceFD, &buf, 1);
        }
    }

private:

    static inline void initIfNeeded() {
        if (!android_atomic_acquire_load(&sIsReady)) {
            init();
        }
    }

    static void changeCallback();

    // init opens the trace marker file for writing and reads the
    // atrace.tags.enableflags system property.  It does this only the first
    // time it is run, using sMutex for synchronization.
    static void init();

    // retrieve the current value of the system property.
    static void loadSystemProperty();

    // sIsReady is a boolean value indicating whether a call to init() has
    // completed in this process.  It is initialized to 0 and set to 1 when the
    // first init() call completes.  It is set to 1 even if a failure occurred
    // in init (e.g. the trace marker file couldn't be opened).
    //
    // This should be checked by all tracing functions using an atomic acquire
    // load operation before calling init().  This check avoids the need to lock
    // a mutex each time a trace function gets called.
    static volatile int32_t sIsReady;

    // sTraceFD is the file descriptor used to write to the kernel's trace
    // buffer.  It is initialized to -1 and set to an open file descriptor in
    // init() while a lock on sMutex is held.
    //
    // This should only be used by a trace function after init() has
    // successfully completed.
    static int sTraceFD;

    // sEnabledTags is the set of tag bits for which tracing is currently
    // enabled.  It is initialized to 0 and set based on the
    // atrace.tags.enableflags system property in init() while a lock on sMutex
    // is held.
    //
    // This should only be used by a trace function after init() has
    // successfully completed.
    //
    // This value is only ever non-zero when tracing is initialized and sTraceFD is not -1.
    static uint64_t sEnabledTags;

    // sMutex is used to protect the execution of init().
    static Mutex sMutex;
};

class ScopedTrace {

public:
    inline ScopedTrace(uint64_t tag, const char* name) :
            mTag(tag) {
        Tracer::traceBegin(mTag, name);
    }

    inline ~ScopedTrace() {
        Tracer::traceEnd(mTag);
    }

private:

    uint64_t mTag;
};

}; // namespace android

#endif // ANDROID_TRACE_H