Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 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 | |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 19 | import android.util.Log; |
| 20 | |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 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 { |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 32 | private static final String TAG = "Trace"; |
| 33 | |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 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; |
Chris Craik | 192a65e | 2012-04-16 16:08:40 -0700 | [diff] [blame] | 40 | public static final long TRACE_TAG_WEBVIEW = 1L << 4; |
Dianne Hackborn | 1ded0b1 | 2012-04-26 14:14:50 -0700 | [diff] [blame] | 41 | public static final long TRACE_TAG_WINDOW_MANAGER = 1L << 5; |
| 42 | public static final long TRACE_TAG_ACTIVITY_MANAGER = 1L << 6; |
Andy Stadler | 09b45a3 | 2012-05-03 15:00:49 -0700 | [diff] [blame] | 43 | public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7; |
Glenn Kasten | ed853fc | 2012-05-07 11:05:55 -0700 | [diff] [blame] | 44 | public static final long TRACE_TAG_AUDIO = 1L << 8; |
Jamie Gennis | 24dae6c | 2012-05-11 04:43:35 -0700 | [diff] [blame] | 45 | public static final long TRACE_TAG_VIDEO = 1L << 9; |
Eino-Ville Talvala | 9c0d9cf | 2012-05-31 15:49:31 -0700 | [diff] [blame] | 46 | public static final long TRACE_TAG_CAMERA = 1L << 10; |
Andy McFadden | 325be8a | 2012-10-29 16:42:41 -0700 | [diff] [blame] | 47 | private static final long TRACE_TAG_NOT_READY = 1L << 63; |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 48 | |
Dianne Hackborn | 83e6eb1 | 2012-05-08 14:53:24 -0700 | [diff] [blame] | 49 | public static final int TRACE_FLAGS_START_BIT = 1; |
| 50 | public static final String[] TRACE_TAGS = { |
| 51 | "Graphics", "Input", "View", "WebView", "Window Manager", |
Eino-Ville Talvala | 9c0d9cf | 2012-05-31 15:49:31 -0700 | [diff] [blame] | 52 | "Activity Manager", "Sync Manager", "Audio", "Video", "Camera", |
Dianne Hackborn | 83e6eb1 | 2012-05-08 14:53:24 -0700 | [diff] [blame] | 53 | }; |
| 54 | |
| 55 | public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags"; |
| 56 | |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 57 | // Must be volatile to avoid word tearing. |
Andy McFadden | 325be8a | 2012-10-29 16:42:41 -0700 | [diff] [blame] | 58 | private static volatile long sEnabledTags = TRACE_TAG_NOT_READY; |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 59 | |
| 60 | private static native long nativeGetEnabledTags(); |
| 61 | private static native void nativeTraceCounter(long tag, String name, int value); |
| 62 | private static native void nativeTraceBegin(long tag, String name); |
| 63 | private static native void nativeTraceEnd(long tag); |
| 64 | |
Dianne Hackborn | a53de06 | 2012-05-08 18:53:51 -0700 | [diff] [blame] | 65 | static { |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 66 | // We configure two separate change callbacks, one in Trace.cpp and one here. The |
| 67 | // native callback reads the tags from the system property, and this callback |
| 68 | // reads the value that the native code retrieved. It's essential that the native |
| 69 | // callback executes first. |
| 70 | // |
| 71 | // The system provides ordering through a priority level. Callbacks made through |
| 72 | // SystemProperties.addChangeCallback currently have a negative priority, while |
| 73 | // our native code is using a priority of zero. |
Dianne Hackborn | a53de06 | 2012-05-08 18:53:51 -0700 | [diff] [blame] | 74 | SystemProperties.addChangeCallback(new Runnable() { |
| 75 | @Override public void run() { |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 76 | cacheEnabledTags(); |
Dianne Hackborn | a53de06 | 2012-05-08 18:53:51 -0700 | [diff] [blame] | 77 | } |
| 78 | }); |
| 79 | } |
| 80 | |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 81 | private Trace() { |
| 82 | } |
| 83 | |
| 84 | /** |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 85 | * Caches a copy of the enabled-tag bits. The "master" copy is held by the native code, |
| 86 | * and comes from the PROPERTY_TRACE_TAG_ENABLEFLAGS property. |
| 87 | * <p> |
| 88 | * If the native code hasn't yet read the property, we will cause it to do one-time |
| 89 | * initialization. We don't want to do this during class init, because this class is |
| 90 | * preloaded, so all apps would be stuck with whatever the zygote saw. (The zygote |
| 91 | * doesn't see the system-property update broadcasts.) |
| 92 | * <p> |
| 93 | * We want to defer initialization until the first use by an app, post-zygote. |
| 94 | * <p> |
| 95 | * We're okay if multiple threads call here simultaneously -- the native state is |
| 96 | * synchronized, and sEnabledTags is volatile (prevents word tearing). |
| 97 | */ |
| 98 | private static long cacheEnabledTags() { |
| 99 | long tags = nativeGetEnabledTags(); |
Andy McFadden | 325be8a | 2012-10-29 16:42:41 -0700 | [diff] [blame] | 100 | if (tags == TRACE_TAG_NOT_READY) { |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 101 | Log.w(TAG, "Unexpected value from nativeGetEnabledTags: " + tags); |
| 102 | // keep going |
| 103 | } |
| 104 | sEnabledTags = tags; |
| 105 | return tags; |
| 106 | } |
| 107 | |
| 108 | /** |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 109 | * Returns true if a trace tag is enabled. |
| 110 | * |
| 111 | * @param traceTag The trace tag to check. |
| 112 | * @return True if the trace tag is valid. |
| 113 | */ |
| 114 | public static boolean isTagEnabled(long traceTag) { |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 115 | long tags = sEnabledTags; |
Andy McFadden | 325be8a | 2012-10-29 16:42:41 -0700 | [diff] [blame] | 116 | if (tags == TRACE_TAG_NOT_READY) { |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 117 | tags = cacheEnabledTags(); |
| 118 | } |
| 119 | return (tags & traceTag) != 0; |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | /** |
| 123 | * Writes trace message to indicate the value of a given counter. |
| 124 | * |
| 125 | * @param traceTag The trace tag. |
| 126 | * @param counterName The counter name to appear in the trace. |
| 127 | * @param counterValue The counter value. |
| 128 | */ |
| 129 | public static void traceCounter(long traceTag, String counterName, int counterValue) { |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 130 | if (isTagEnabled(traceTag)) { |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 131 | nativeTraceCounter(traceTag, counterName, counterValue); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | /** |
| 136 | * Writes a trace message to indicate that a given method has begun. |
| 137 | * Must be followed by a call to {@link #traceEnd} using the same tag. |
| 138 | * |
| 139 | * @param traceTag The trace tag. |
| 140 | * @param methodName The method name to appear in the trace. |
| 141 | */ |
| 142 | public static void traceBegin(long traceTag, String methodName) { |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 143 | if (isTagEnabled(traceTag)) { |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 144 | nativeTraceBegin(traceTag, methodName); |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | /** |
| 149 | * Writes a trace message to indicate that the current method has ended. |
| 150 | * Must be called exactly once for each call to {@link #traceBegin} using the same tag. |
| 151 | * |
| 152 | * @param traceTag The trace tag. |
| 153 | */ |
| 154 | public static void traceEnd(long traceTag) { |
Andy McFadden | d11ca4d | 2012-10-22 16:16:06 -0700 | [diff] [blame] | 155 | if (isTagEnabled(traceTag)) { |
Jeff Brown | 481c157 | 2012-03-09 14:41:15 -0800 | [diff] [blame] | 156 | nativeTraceEnd(traceTag); |
| 157 | } |
| 158 | } |
| 159 | } |