Debug.java revision afed82bca9e173cabe2c2f25314b202e5c1ccbca
16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* 26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Copyright (C) 2007 The Android Open Source Project 36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * 46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Licensed under the Apache License, Version 2.0 (the "License"); 56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * you may not use this file except in compliance with the License. 66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * You may obtain a copy of the License at 76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * 86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * http://www.apache.org/licenses/LICENSE-2.0 96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * 106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Unless required by applicable law or agreed to in writing, software 116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * distributed under the License is distributed on an "AS IS" BASIS, 126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * See the License for the specific language governing permissions and 146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * limitations under the License. 156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennpackage android.os; 186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport com.android.internal.util.TypedProperties; 206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport android.util.Config; 226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport android.util.Log; 236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.io.FileDescriptor; 256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.io.FileNotFoundException; 266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.io.FileOutputStream; 276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.io.FileReader; 286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.io.IOException; 296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.io.OutputStreamWriter; 306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.io.PrintWriter; 316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.io.Reader; 326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.lang.reflect.Field; 336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.lang.reflect.Modifier; 346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.lang.annotation.Target; 356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.lang.annotation.ElementType; 366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.lang.annotation.Retention; 376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport java.lang.annotation.RetentionPolicy; 386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport org.apache.harmony.dalvik.ddmc.Chunk; 406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport org.apache.harmony.dalvik.ddmc.ChunkHandler; 416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport org.apache.harmony.dalvik.ddmc.DdmServer; 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport dalvik.bytecode.Opcodes; 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennimport dalvik.system.VMDebug; 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/** 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Provides various debugging functions for Android applications, including 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * tracing and allocation counts. 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * <p><strong>Logging Trace Files</strong></p> 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * <p>Debug can create log files that give details about an application, such as 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * a call stack and start/stop times for any running methods. See <a 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennhref="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * information about reading trace files. To start logging trace files, call one 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * of the startMethodTracing() methods. To stop tracing, call 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * {@link #stopMethodTracing()}. 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennpublic final class Debug 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Flags for startMethodTracing(). These can be ORed together. 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * trace key file. 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public static final int TRACE_COUNT_ALLOCS = VMDebug.TRACE_COUNT_ALLOCS; 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Flags for printLoadedClasses(). Default behavior is to only show 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * the class name. 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public static final int SHOW_FULL_DETAIL = 1; 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public static final int SHOW_CLASSLOADER = (1 << 1); 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public static final int SHOW_INITIALIZED = (1 << 2); 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // set/cleared by waitForDebugger() 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn private static volatile boolean mWaiting = false; 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn private Debug() {} 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * How long to wait for the debugger to finish sending requests. I've 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * seen this hit 800msec on the device while waiting for a response 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * to travel over USB and get processed, so we take that and add 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * half a second. 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn private static final int MIN_DEBUGGER_IDLE = 1300; // msec 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* how long to sleep when polling for activity */ 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn private static final int SPIN_DELAY = 200; // msec 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Default trace file path and file 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn private static final String DEFAULT_TRACE_PATH_PREFIX = "/sdcard/"; 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn private static final String DEFAULT_TRACE_BODY = "dmtrace"; 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn private static final String DEFAULT_TRACE_EXTENSION = ".trace"; 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn private static final String DEFAULT_TRACE_FILE_PATH = 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn + DEFAULT_TRACE_EXTENSION; 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * This class is used to retrieved various statistics about the memory mappings for this 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * process. The returns info broken down by dalvik, native, and other. All results are in kB. 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public static class MemoryInfo { 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** The proportional set size for dalvik. */ 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public int dalvikPss; 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** The private dirty pages used by dalvik. */ 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public int dalvikPrivateDirty; 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** The shared dirty pages used by dalvik. */ 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public int dalvikSharedDirty; 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** The proportional set size for the native heap. */ 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public int nativePss; 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** The private dirty pages used by the native heap. */ 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public int nativePrivateDirty; 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /** The shared dirty pages used by the native heap. */ 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn public int nativeSharedDirty; 121 122 /** The proportional set size for everything else. */ 123 public int otherPss; 124 /** The private dirty pages used by everything else. */ 125 public int otherPrivateDirty; 126 /** The shared dirty pages used by everything else. */ 127 public int otherSharedDirty; 128 } 129 130 131 /** 132 * Wait until a debugger attaches. As soon as the debugger attaches, 133 * this returns, so you will need to place a breakpoint after the 134 * waitForDebugger() call if you want to start tracing immediately. 135 */ 136 public static void waitForDebugger() { 137 if (!VMDebug.isDebuggingEnabled()) { 138 //System.out.println("debugging not enabled, not waiting"); 139 return; 140 } 141 if (isDebuggerConnected()) 142 return; 143 144 // if DDMS is listening, inform them of our plight 145 System.out.println("Sending WAIT chunk"); 146 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger" 147 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1); 148 DdmServer.sendChunk(waitChunk); 149 150 mWaiting = true; 151 while (!isDebuggerConnected()) { 152 try { Thread.sleep(SPIN_DELAY); } 153 catch (InterruptedException ie) {} 154 } 155 mWaiting = false; 156 157 System.out.println("Debugger has connected"); 158 159 /* 160 * There is no "ready to go" signal from the debugger, and we're 161 * not allowed to suspend ourselves -- the debugger expects us to 162 * be running happily, and gets confused if we aren't. We need to 163 * allow the debugger a chance to set breakpoints before we start 164 * running again. 165 * 166 * Sit and spin until the debugger has been idle for a short while. 167 */ 168 while (true) { 169 long delta = VMDebug.lastDebuggerActivity(); 170 if (delta < 0) { 171 System.out.println("debugger detached?"); 172 break; 173 } 174 175 if (delta < MIN_DEBUGGER_IDLE) { 176 System.out.println("waiting for debugger to settle..."); 177 try { Thread.sleep(SPIN_DELAY); } 178 catch (InterruptedException ie) {} 179 } else { 180 System.out.println("debugger has settled (" + delta + ")"); 181 break; 182 } 183 } 184 } 185 186 /** 187 * Returns "true" if one or more threads is waiting for a debugger 188 * to attach. 189 */ 190 public static boolean waitingForDebugger() { 191 return mWaiting; 192 } 193 194 /** 195 * Determine if a debugger is currently attached. 196 */ 197 public static boolean isDebuggerConnected() { 198 return VMDebug.isDebuggerConnected(); 199 } 200 201 /** 202 * Change the JDWP port. 203 * 204 * @deprecated no longer needed or useful 205 */ 206 @Deprecated 207 public static void changeDebugPort(int port) {} 208 209 /** 210 * This is the pathname to the sysfs file that enables and disables 211 * tracing on the qemu emulator. 212 */ 213 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state"; 214 215 /** 216 * Enable qemu tracing. For this to work requires running everything inside 217 * the qemu emulator; otherwise, this method will have no effect. The trace 218 * file is specified on the command line when the emulator is started. For 219 * example, the following command line <br /> 220 * <code>emulator -trace foo</code><br /> 221 * will start running the emulator and create a trace file named "foo". This 222 * method simply enables writing the trace records to the trace file. 223 * 224 * <p> 225 * The main differences between this and {@link #startMethodTracing()} are 226 * that tracing in the qemu emulator traces every cpu instruction of every 227 * process, including kernel code, so we have more complete information, 228 * including all context switches. We can also get more detailed information 229 * such as cache misses. The sequence of calls is determined by 230 * post-processing the instruction trace. The qemu tracing is also done 231 * without modifying the application or perturbing the timing of calls 232 * because no instrumentation is added to the application being traced. 233 * </p> 234 * 235 * <p> 236 * One limitation of using this method compared to using 237 * {@link #startMethodTracing()} on the real device is that the emulator 238 * does not model all of the real hardware effects such as memory and 239 * bus contention. The emulator also has a simple cache model and cannot 240 * capture all the complexities of a real cache. 241 * </p> 242 */ 243 public static void startNativeTracing() { 244 // Open the sysfs file for writing and write "1" to it. 245 PrintWriter outStream = null; 246 try { 247 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE); 248 outStream = new PrintWriter(new OutputStreamWriter(fos)); 249 outStream.println("1"); 250 } catch (Exception e) { 251 } finally { 252 if (outStream != null) 253 outStream.close(); 254 } 255 256 VMDebug.startEmulatorTracing(); 257 } 258 259 /** 260 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing. 261 * 262 * <p>Tracing can be started and stopped as many times as desired. When 263 * the qemu emulator itself is stopped then the buffered trace records 264 * are flushed and written to the trace file. In fact, it is not necessary 265 * to call this method at all; simply killing qemu is sufficient. But 266 * starting and stopping a trace is useful for examining a specific 267 * region of code.</p> 268 */ 269 public static void stopNativeTracing() { 270 VMDebug.stopEmulatorTracing(); 271 272 // Open the sysfs file for writing and write "0" to it. 273 PrintWriter outStream = null; 274 try { 275 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE); 276 outStream = new PrintWriter(new OutputStreamWriter(fos)); 277 outStream.println("0"); 278 } catch (Exception e) { 279 // We could print an error message here but we probably want 280 // to quietly ignore errors if we are not running in the emulator. 281 } finally { 282 if (outStream != null) 283 outStream.close(); 284 } 285 } 286 287 /** 288 * Enable "emulator traces", in which information about the current 289 * method is made available to the "emulator -trace" feature. There 290 * is no corresponding "disable" call -- this is intended for use by 291 * the framework when tracing should be turned on and left that way, so 292 * that traces captured with F9/F10 will include the necessary data. 293 * 294 * This puts the VM into "profile" mode, which has performance 295 * consequences. 296 * 297 * To temporarily enable tracing, use {@link #startNativeTracing()}. 298 */ 299 public static void enableEmulatorTraceOutput() { 300 VMDebug.startEmulatorTracing(); 301 } 302 303 /** 304 * Start method tracing with default log name and buffer size. See <a 305href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 306 * information about reading these files. Call stopMethodTracing() to stop 307 * tracing. 308 */ 309 public static void startMethodTracing() { 310 VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0); 311 } 312 313 /** 314 * Start method tracing, specifying the trace log file name. The trace 315 * file will be put under "/sdcard" unless an absolute path is given. 316 * See <a 317 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 318 * information about reading trace files. 319 * 320 * @param traceName Name for the trace log file to create. 321 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace". 322 * If the files already exist, they will be truncated. 323 * If the trace file given does not end in ".trace", it will be appended for you. 324 */ 325 public static void startMethodTracing(String traceName) { 326 startMethodTracing(traceName, 0, 0); 327 } 328 329 /** 330 * Start method tracing, specifying the trace log file name and the 331 * buffer size. The trace files will be put under "/sdcard" unless an 332 * absolute path is given. See <a 333 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 334 * information about reading trace files. 335 * @param traceName Name for the trace log file to create. 336 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace". 337 * If the files already exist, they will be truncated. 338 * If the trace file given does not end in ".trace", it will be appended for you. 339 * 340 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB. 341 */ 342 public static void startMethodTracing(String traceName, int bufferSize) { 343 startMethodTracing(traceName, bufferSize, 0); 344 } 345 346 /** 347 * Start method tracing, specifying the trace log file name and the 348 * buffer size. The trace files will be put under "/sdcard" unless an 349 * absolute path is given. See <a 350 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 351 * information about reading trace files. 352 * 353 * <p> 354 * When method tracing is enabled, the VM will run more slowly than 355 * usual, so the timings from the trace files should only be considered 356 * in relative terms (e.g. was run #1 faster than run #2). The times 357 * for native methods will not change, so don't try to use this to 358 * compare the performance of interpreted and native implementations of the 359 * same method. As an alternative, consider using "native" tracing 360 * in the emulator via {@link #startNativeTracing()}. 361 * </p> 362 * 363 * @param traceName Name for the trace log file to create. 364 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace". 365 * If the files already exist, they will be truncated. 366 * If the trace file given does not end in ".trace", it will be appended for you. 367 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB. 368 */ 369 public static void startMethodTracing(String traceName, int bufferSize, 370 int flags) { 371 372 String pathName = traceName; 373 if (pathName.charAt(0) != '/') 374 pathName = DEFAULT_TRACE_PATH_PREFIX + pathName; 375 if (!pathName.endsWith(DEFAULT_TRACE_EXTENSION)) 376 pathName = pathName + DEFAULT_TRACE_EXTENSION; 377 378 VMDebug.startMethodTracing(pathName, bufferSize, flags); 379 } 380 381 /** 382 * Like startMethodTracing(String, int, int), but taking an already-opened 383 * FileDescriptor in which the trace is written. The file name is also 384 * supplied simply for logging. Makes a dup of the file descriptor. 385 * 386 * Not exposed in the SDK unless we are really comfortable with supporting 387 * this and find it would be useful. 388 * @hide 389 */ 390 public static void startMethodTracing(String traceName, FileDescriptor fd, 391 int bufferSize, int flags) { 392 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags); 393 } 394 395 /** 396 * Determine whether method tracing is currently active. 397 * @hide 398 */ 399 public static boolean isMethodTracingActive() { 400 return VMDebug.isMethodTracingActive(); 401 } 402 403 /** 404 * Stop method tracing. 405 */ 406 public static void stopMethodTracing() { 407 VMDebug.stopMethodTracing(); 408 } 409 410 /** 411 * Get an indication of thread CPU usage. The value returned 412 * indicates the amount of time that the current thread has spent 413 * executing code or waiting for certain types of I/O. 414 * 415 * The time is expressed in nanoseconds, and is only meaningful 416 * when compared to the result from an earlier call. Note that 417 * nanosecond resolution does not imply nanosecond accuracy. 418 * 419 * On system which don't support this operation, the call returns -1. 420 */ 421 public static long threadCpuTimeNanos() { 422 return VMDebug.threadCpuTimeNanos(); 423 } 424 425 /** 426 * Count the number and aggregate size of memory allocations between 427 * two points. 428 * 429 * The "start" function resets the counts and enables counting. The 430 * "stop" function disables the counting so that the analysis code 431 * doesn't cause additional allocations. The "get" function returns 432 * the specified value. 433 * 434 * Counts are kept for the system as a whole and for each thread. 435 * The per-thread counts for threads other than the current thread 436 * are not cleared by the "reset" or "start" calls. 437 */ 438 public static void startAllocCounting() { 439 VMDebug.startAllocCounting(); 440 } 441 public static void stopAllocCounting() { 442 VMDebug.stopAllocCounting(); 443 } 444 445 public static int getGlobalAllocCount() { 446 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS); 447 } 448 public static int getGlobalAllocSize() { 449 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES); 450 } 451 public static int getGlobalFreedCount() { 452 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS); 453 } 454 public static int getGlobalFreedSize() { 455 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES); 456 } 457 public static int getGlobalExternalAllocCount() { 458 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_OBJECTS); 459 } 460 public static int getGlobalExternalAllocSize() { 461 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_BYTES); 462 } 463 public static int getGlobalExternalFreedCount() { 464 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_OBJECTS); 465 } 466 public static int getGlobalExternalFreedSize() { 467 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_BYTES); 468 } 469 public static int getGlobalGcInvocationCount() { 470 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS); 471 } 472 public static int getThreadAllocCount() { 473 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS); 474 } 475 public static int getThreadAllocSize() { 476 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES); 477 } 478 public static int getThreadExternalAllocCount() { 479 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_OBJECTS); 480 } 481 public static int getThreadExternalAllocSize() { 482 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_BYTES); 483 } 484 public static int getThreadGcInvocationCount() { 485 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS); 486 } 487 488 public static void resetGlobalAllocCount() { 489 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS); 490 } 491 public static void resetGlobalAllocSize() { 492 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES); 493 } 494 public static void resetGlobalFreedCount() { 495 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS); 496 } 497 public static void resetGlobalFreedSize() { 498 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES); 499 } 500 public static void resetGlobalExternalAllocCount() { 501 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_OBJECTS); 502 } 503 public static void resetGlobalExternalAllocSize() { 504 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_BYTES); 505 } 506 public static void resetGlobalExternalFreedCount() { 507 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_OBJECTS); 508 } 509 public static void resetGlobalExternalFreedSize() { 510 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_BYTES); 511 } 512 public static void resetGlobalGcInvocationCount() { 513 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS); 514 } 515 public static void resetThreadAllocCount() { 516 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS); 517 } 518 public static void resetThreadAllocSize() { 519 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES); 520 } 521 public static void resetThreadExternalAllocCount() { 522 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_OBJECTS); 523 } 524 public static void resetThreadExternalAllocSize() { 525 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_BYTES); 526 } 527 public static void resetThreadGcInvocationCount() { 528 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS); 529 } 530 public static void resetAllCounts() { 531 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS); 532 } 533 534 /** 535 * Returns the size of the native heap. 536 * @return The size of the native heap in bytes. 537 */ 538 public static native long getNativeHeapSize(); 539 540 /** 541 * Returns the amount of allocated memory in the native heap. 542 * @return The allocated size in bytes. 543 */ 544 public static native long getNativeHeapAllocatedSize(); 545 546 /** 547 * Returns the amount of free memory in the native heap. 548 * @return The freed size in bytes. 549 */ 550 public static native long getNativeHeapFreeSize(); 551 552 /** 553 * Retrieves information about this processes memory usages. This information is broken down by 554 * how much is in use by dalivk, the native heap, and everything else. 555 */ 556 public static native void getMemoryInfo(MemoryInfo memoryInfo); 557 558 /** 559 * Establish an object allocation limit in the current thread. Useful 560 * for catching regressions in code that is expected to operate 561 * without causing any allocations. 562 * 563 * Pass in the maximum number of allowed allocations. Use -1 to disable 564 * the limit. Returns the previous limit. 565 * 566 * The preferred way to use this is: 567 * 568 * int prevLimit = -1; 569 * try { 570 * prevLimit = Debug.setAllocationLimit(0); 571 * ... do stuff that's not expected to allocate memory ... 572 * } finally { 573 * Debug.setAllocationLimit(prevLimit); 574 * } 575 * 576 * This allows limits to be nested. The try/finally ensures that the 577 * limit is reset if something fails. 578 * 579 * Exceeding the limit causes a dalvik.system.AllocationLimitError to 580 * be thrown from a memory allocation call. The limit is reset to -1 581 * when this happens. 582 * 583 * The feature may be disabled in the VM configuration. If so, this 584 * call has no effect, and always returns -1. 585 */ 586 public static int setAllocationLimit(int limit) { 587 return VMDebug.setAllocationLimit(limit); 588 } 589 590 /** 591 * Establish a global object allocation limit. This is similar to 592 * {@link #setAllocationLimit(int)} but applies to all threads in 593 * the VM. It will coexist peacefully with per-thread limits. 594 * 595 * [ The value of "limit" is currently restricted to 0 (no allocations 596 * allowed) or -1 (no global limit). This may be changed in a future 597 * release. ] 598 */ 599 public static int setGlobalAllocationLimit(int limit) { 600 if (limit != 0 && limit != -1) 601 throw new IllegalArgumentException("limit must be 0 or -1"); 602 return VMDebug.setGlobalAllocationLimit(limit); 603 } 604 605 /** 606 * Dump a list of all currently loaded class to the log file. 607 * 608 * @param flags See constants above. 609 */ 610 public static void printLoadedClasses(int flags) { 611 VMDebug.printLoadedClasses(flags); 612 } 613 614 /** 615 * Get the number of loaded classes. 616 * @return the number of loaded classes. 617 */ 618 public static int getLoadedClassCount() { 619 return VMDebug.getLoadedClassCount(); 620 } 621 622 /** 623 * Dump "hprof" data to the specified file. This will cause a GC. 624 * 625 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof"). 626 * @throws UnsupportedOperationException if the VM was built without 627 * HPROF support. 628 * @throws IOException if an error occurs while opening or writing files. 629 */ 630 public static void dumpHprofData(String fileName) throws IOException { 631 VMDebug.dumpHprofData(fileName); 632 } 633 634 /** 635 * Returns the number of sent transactions from this process. 636 * @return The number of sent transactions or -1 if it could not read t. 637 */ 638 public static native int getBinderSentTransactions(); 639 640 /** 641 * Returns the number of received transactions from the binder driver. 642 * @return The number of received transactions or -1 if it could not read the stats. 643 */ 644 public static native int getBinderReceivedTransactions(); 645 646 /** 647 * Returns the number of active local Binder objects that exist in the 648 * current process. 649 */ 650 public static final native int getBinderLocalObjectCount(); 651 652 /** 653 * Returns the number of references to remote proxy Binder objects that 654 * exist in the current process. 655 */ 656 public static final native int getBinderProxyObjectCount(); 657 658 /** 659 * Returns the number of death notification links to Binder objects that 660 * exist in the current process. 661 */ 662 public static final native int getBinderDeathObjectCount(); 663 664 /** 665 * Primes the register map cache. 666 * 667 * Only works for classes in the bootstrap class loader. Does not 668 * cause classes to be loaded if they're not already present. 669 * 670 * The classAndMethodDesc argument is a concatentation of the VM-internal 671 * class descriptor, method name, and method descriptor. Examples: 672 * Landroid/os/Looper;.loop:()V 673 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V 674 * 675 * @param classAndMethodDesc the method to prepare 676 * 677 * @hide 678 */ 679 public static final boolean cacheRegisterMap(String classAndMethodDesc) { 680 return VMDebug.cacheRegisterMap(classAndMethodDesc); 681 } 682 683 /** 684 * API for gathering and querying instruction counts. 685 * 686 * Example usage: 687 * Debug.InstructionCount icount = new Debug.InstructionCount(); 688 * icount.resetAndStart(); 689 * [... do lots of stuff ...] 690 * if (icount.collect()) { 691 * System.out.println("Total instructions executed: " 692 * + icount.globalTotal()); 693 * System.out.println("Method invocations: " 694 * + icount.globalMethodInvocations()); 695 * } 696 */ 697 public static class InstructionCount { 698 private static final int NUM_INSTR = 256; 699 700 private int[] mCounts; 701 702 public InstructionCount() { 703 mCounts = new int[NUM_INSTR]; 704 } 705 706 /** 707 * Reset counters and ensure counts are running. Counts may 708 * have already been running. 709 * 710 * @return true if counting was started 711 */ 712 public boolean resetAndStart() { 713 try { 714 VMDebug.startInstructionCounting(); 715 VMDebug.resetInstructionCount(); 716 } catch (UnsupportedOperationException uoe) { 717 return false; 718 } 719 return true; 720 } 721 722 /** 723 * Collect instruction counts. May or may not stop the 724 * counting process. 725 */ 726 public boolean collect() { 727 try { 728 VMDebug.stopInstructionCounting(); 729 VMDebug.getInstructionCount(mCounts); 730 } catch (UnsupportedOperationException uoe) { 731 return false; 732 } 733 return true; 734 } 735 736 /** 737 * Return the total number of instructions executed globally (i.e. in 738 * all threads). 739 */ 740 public int globalTotal() { 741 int count = 0; 742 for (int i = 0; i < NUM_INSTR; i++) 743 count += mCounts[i]; 744 return count; 745 } 746 747 /** 748 * Return the total number of method-invocation instructions 749 * executed globally. 750 */ 751 public int globalMethodInvocations() { 752 int count = 0; 753 754 //count += mCounts[Opcodes.OP_EXECUTE_INLINE]; 755 count += mCounts[Opcodes.OP_INVOKE_VIRTUAL]; 756 count += mCounts[Opcodes.OP_INVOKE_SUPER]; 757 count += mCounts[Opcodes.OP_INVOKE_DIRECT]; 758 count += mCounts[Opcodes.OP_INVOKE_STATIC]; 759 count += mCounts[Opcodes.OP_INVOKE_INTERFACE]; 760 count += mCounts[Opcodes.OP_INVOKE_VIRTUAL_RANGE]; 761 count += mCounts[Opcodes.OP_INVOKE_SUPER_RANGE]; 762 count += mCounts[Opcodes.OP_INVOKE_DIRECT_RANGE]; 763 count += mCounts[Opcodes.OP_INVOKE_STATIC_RANGE]; 764 count += mCounts[Opcodes.OP_INVOKE_INTERFACE_RANGE]; 765 //count += mCounts[Opcodes.OP_INVOKE_DIRECT_EMPTY]; 766 count += mCounts[Opcodes.OP_INVOKE_VIRTUAL_QUICK]; 767 count += mCounts[Opcodes.OP_INVOKE_VIRTUAL_QUICK_RANGE]; 768 count += mCounts[Opcodes.OP_INVOKE_SUPER_QUICK]; 769 count += mCounts[Opcodes.OP_INVOKE_SUPER_QUICK_RANGE]; 770 return count; 771 } 772 } 773 774 775 /** 776 * A Map of typed debug properties. 777 */ 778 private static final TypedProperties debugProperties; 779 780 /* 781 * Load the debug properties from the standard files into debugProperties. 782 */ 783 static { 784 if (Config.DEBUG) { 785 final String TAG = "DebugProperties"; 786 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" }; 787 final TypedProperties tp = new TypedProperties(); 788 789 // Read the properties from each of the files, if present. 790 for (String file : files) { 791 Reader r; 792 try { 793 r = new FileReader(file); 794 } catch (FileNotFoundException ex) { 795 // It's ok if a file is missing. 796 continue; 797 } 798 799 try { 800 tp.load(r); 801 } catch (Exception ex) { 802 throw new RuntimeException("Problem loading " + file, ex); 803 } finally { 804 try { 805 r.close(); 806 } catch (IOException ex) { 807 // Ignore this error. 808 } 809 } 810 } 811 812 debugProperties = tp.isEmpty() ? null : tp; 813 } else { 814 debugProperties = null; 815 } 816 } 817 818 819 /** 820 * Returns true if the type of the field matches the specified class. 821 * Handles the case where the class is, e.g., java.lang.Boolean, but 822 * the field is of the primitive "boolean" type. Also handles all of 823 * the java.lang.Number subclasses. 824 */ 825 private static boolean fieldTypeMatches(Field field, Class<?> cl) { 826 Class<?> fieldClass = field.getType(); 827 if (fieldClass == cl) { 828 return true; 829 } 830 Field primitiveTypeField; 831 try { 832 /* All of the classes we care about (Boolean, Integer, etc.) 833 * have a Class field called "TYPE" that points to the corresponding 834 * primitive class. 835 */ 836 primitiveTypeField = cl.getField("TYPE"); 837 } catch (NoSuchFieldException ex) { 838 return false; 839 } 840 try { 841 return fieldClass == (Class<?>) primitiveTypeField.get(null); 842 } catch (IllegalAccessException ex) { 843 return false; 844 } 845 } 846 847 848 /** 849 * Looks up the property that corresponds to the field, and sets the field's value 850 * if the types match. 851 */ 852 private static void modifyFieldIfSet(final Field field, final TypedProperties properties, 853 final String propertyName) { 854 if (field.getType() == java.lang.String.class) { 855 int stringInfo = properties.getStringInfo(propertyName); 856 switch (stringInfo) { 857 case TypedProperties.STRING_SET: 858 // Handle as usual below. 859 break; 860 case TypedProperties.STRING_NULL: 861 try { 862 field.set(null, null); // null object for static fields; null string 863 } catch (IllegalAccessException ex) { 864 throw new IllegalArgumentException( 865 "Cannot set field for " + propertyName, ex); 866 } 867 return; 868 case TypedProperties.STRING_NOT_SET: 869 return; 870 case TypedProperties.STRING_TYPE_MISMATCH: 871 throw new IllegalArgumentException( 872 "Type of " + propertyName + " " + 873 " does not match field type (" + field.getType() + ")"); 874 default: 875 throw new IllegalStateException( 876 "Unexpected getStringInfo(" + propertyName + ") return value " + 877 stringInfo); 878 } 879 } 880 Object value = properties.get(propertyName); 881 if (value != null) { 882 if (!fieldTypeMatches(field, value.getClass())) { 883 throw new IllegalArgumentException( 884 "Type of " + propertyName + " (" + value.getClass() + ") " + 885 " does not match field type (" + field.getType() + ")"); 886 } 887 try { 888 field.set(null, value); // null object for static fields 889 } catch (IllegalAccessException ex) { 890 throw new IllegalArgumentException( 891 "Cannot set field for " + propertyName, ex); 892 } 893 } 894 } 895 896 897 /** 898 * Equivalent to <code>setFieldsOn(cl, false)</code>. 899 * 900 * @see #setFieldsOn(Class, boolean) 901 * 902 * @hide 903 */ 904 public static void setFieldsOn(Class<?> cl) { 905 setFieldsOn(cl, false); 906 } 907 908 /** 909 * Reflectively sets static fields of a class based on internal debugging 910 * properties. This method is a no-op if android.util.Config.DEBUG is 911 * false. 912 * <p> 913 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: Config.DEBUG will 914 * always be false in release builds. This API is typically only useful 915 * for platform developers. 916 * </p> 917 * Class setup: define a class whose only fields are non-final, static 918 * primitive types (except for "char") or Strings. In a static block 919 * after the field definitions/initializations, pass the class to 920 * this method, Debug.setFieldsOn(). Example: 921 * <pre> 922 * package com.example; 923 * 924 * import android.os.Debug; 925 * 926 * public class MyDebugVars { 927 * public static String s = "a string"; 928 * public static String s2 = "second string"; 929 * public static String ns = null; 930 * public static boolean b = false; 931 * public static int i = 5; 932 * @Debug.DebugProperty 933 * public static float f = 0.1f; 934 * @@Debug.DebugProperty 935 * public static double d = 0.5d; 936 * 937 * // This MUST appear AFTER all fields are defined and initialized! 938 * static { 939 * // Sets all the fields 940 * Debug.setFieldsOn(MyDebugVars.class); 941 * 942 * // Sets only the fields annotated with @Debug.DebugProperty 943 * // Debug.setFieldsOn(MyDebugVars.class, true); 944 * } 945 * } 946 * </pre> 947 * setFieldsOn() may override the value of any field in the class based 948 * on internal properties that are fixed at boot time. 949 * <p> 950 * These properties are only set during platform debugging, and are not 951 * meant to be used as a general-purpose properties store. 952 * 953 * {@hide} 954 * 955 * @param cl The class to (possibly) modify 956 * @param partial If false, sets all static fields, otherwise, only set 957 * fields with the {@link android.os.Debug.DebugProperty} 958 * annotation 959 * @throws IllegalArgumentException if any fields are final or non-static, 960 * or if the type of the field does not match the type of 961 * the internal debugging property value. 962 */ 963 public static void setFieldsOn(Class<?> cl, boolean partial) { 964 if (Config.DEBUG) { 965 if (debugProperties != null) { 966 /* Only look for fields declared directly by the class, 967 * so we don't mysteriously change static fields in superclasses. 968 */ 969 for (Field field : cl.getDeclaredFields()) { 970 if (!partial || field.getAnnotation(DebugProperty.class) != null) { 971 final String propertyName = cl.getName() + "." + field.getName(); 972 boolean isStatic = Modifier.isStatic(field.getModifiers()); 973 boolean isFinal = Modifier.isFinal(field.getModifiers()); 974 975 if (!isStatic || isFinal) { 976 throw new IllegalArgumentException(propertyName + 977 " must be static and non-final"); 978 } 979 modifyFieldIfSet(field, debugProperties, propertyName); 980 } 981 } 982 } 983 } else { 984 Log.w("android.os.Debug", 985 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) + 986 ") called in non-DEBUG build"); 987 } 988 } 989 990 /** 991 * Annotation to put on fields you want to set with 992 * {@link Debug#setFieldsOn(Class, boolean)}. 993 * 994 * @hide 995 */ 996 @Target({ ElementType.FIELD }) 997 @Retention(RetentionPolicy.RUNTIME) 998 public @interface DebugProperty { 999 } 1000} 1001