Debug.java revision 172da26d4515f295d938864e47f5ce0309728571
1/* 2 * Copyright (C) 2007 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 17package android.os; 18 19import com.android.internal.util.FastPrintWriter; 20import com.android.internal.util.TypedProperties; 21 22import android.util.Log; 23 24import java.io.FileDescriptor; 25import java.io.FileNotFoundException; 26import java.io.FileOutputStream; 27import java.io.FileReader; 28import java.io.IOException; 29import java.io.PrintWriter; 30import java.io.Reader; 31import java.lang.reflect.Field; 32import java.lang.reflect.Modifier; 33import java.lang.annotation.Target; 34import java.lang.annotation.ElementType; 35import java.lang.annotation.Retention; 36import java.lang.annotation.RetentionPolicy; 37 38import org.apache.harmony.dalvik.ddmc.Chunk; 39import org.apache.harmony.dalvik.ddmc.ChunkHandler; 40import org.apache.harmony.dalvik.ddmc.DdmServer; 41 42import dalvik.bytecode.OpcodeInfo; 43import dalvik.system.VMDebug; 44 45 46/** 47 * Provides various debugging methods for Android applications, including 48 * tracing and allocation counts. 49 * <p><strong>Logging Trace Files</strong></p> 50 * <p>Debug can create log files that give details about an application, such as 51 * a call stack and start/stop times for any running methods. See <a 52href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 53 * information about reading trace files. To start logging trace files, call one 54 * of the startMethodTracing() methods. To stop tracing, call 55 * {@link #stopMethodTracing()}. 56 */ 57public final class Debug 58{ 59 private static final String TAG = "Debug"; 60 61 /** 62 * Flags for startMethodTracing(). These can be ORed together. 63 * 64 * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the 65 * trace key file. 66 * 67 * @deprecated Accurate counting is a burden on the runtime and may be removed. 68 */ 69 @Deprecated 70 public static final int TRACE_COUNT_ALLOCS = VMDebug.TRACE_COUNT_ALLOCS; 71 72 /** 73 * Flags for printLoadedClasses(). Default behavior is to only show 74 * the class name. 75 */ 76 public static final int SHOW_FULL_DETAIL = 1; 77 public static final int SHOW_CLASSLOADER = (1 << 1); 78 public static final int SHOW_INITIALIZED = (1 << 2); 79 80 // set/cleared by waitForDebugger() 81 private static volatile boolean mWaiting = false; 82 83 private Debug() {} 84 85 /* 86 * How long to wait for the debugger to finish sending requests. I've 87 * seen this hit 800msec on the device while waiting for a response 88 * to travel over USB and get processed, so we take that and add 89 * half a second. 90 */ 91 private static final int MIN_DEBUGGER_IDLE = 1300; // msec 92 93 /* how long to sleep when polling for activity */ 94 private static final int SPIN_DELAY = 200; // msec 95 96 /** 97 * Default trace file path and file 98 */ 99 private static final String DEFAULT_TRACE_PATH_PREFIX = 100 Environment.getLegacyExternalStorageDirectory().getPath() + "/"; 101 private static final String DEFAULT_TRACE_BODY = "dmtrace"; 102 private static final String DEFAULT_TRACE_EXTENSION = ".trace"; 103 private static final String DEFAULT_TRACE_FILE_PATH = 104 DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY 105 + DEFAULT_TRACE_EXTENSION; 106 107 108 /** 109 * This class is used to retrieved various statistics about the memory mappings for this 110 * process. The returned info is broken down by dalvik, native, and other. All results are in kB. 111 */ 112 public static class MemoryInfo implements Parcelable { 113 /** The proportional set size for dalvik heap. (Doesn't include other Dalvik overhead.) */ 114 public int dalvikPss; 115 /** The proportional set size that is swappable for dalvik heap. */ 116 /** @hide We may want to expose this, eventually. */ 117 public int dalvikSwappablePss; 118 /** The private dirty pages used by dalvik heap. */ 119 public int dalvikPrivateDirty; 120 /** The shared dirty pages used by dalvik heap. */ 121 public int dalvikSharedDirty; 122 /** The private clean pages used by dalvik heap. */ 123 /** @hide We may want to expose this, eventually. */ 124 public int dalvikPrivateClean; 125 /** The shared clean pages used by dalvik heap. */ 126 /** @hide We may want to expose this, eventually. */ 127 public int dalvikSharedClean; 128 /** The dirty dalvik pages that have been swapped out. */ 129 /** @hide We may want to expose this, eventually. */ 130 public int dalvikSwappedOut; 131 132 /** The proportional set size for the native heap. */ 133 public int nativePss; 134 /** The proportional set size that is swappable for the native heap. */ 135 /** @hide We may want to expose this, eventually. */ 136 public int nativeSwappablePss; 137 /** The private dirty pages used by the native heap. */ 138 public int nativePrivateDirty; 139 /** The shared dirty pages used by the native heap. */ 140 public int nativeSharedDirty; 141 /** The private clean pages used by the native heap. */ 142 /** @hide We may want to expose this, eventually. */ 143 public int nativePrivateClean; 144 /** The shared clean pages used by the native heap. */ 145 /** @hide We may want to expose this, eventually. */ 146 public int nativeSharedClean; 147 /** The dirty native pages that have been swapped out. */ 148 /** @hide We may want to expose this, eventually. */ 149 public int nativeSwappedOut; 150 151 /** The proportional set size for everything else. */ 152 public int otherPss; 153 /** The proportional set size that is swappable for everything else. */ 154 /** @hide We may want to expose this, eventually. */ 155 public int otherSwappablePss; 156 /** The private dirty pages used by everything else. */ 157 public int otherPrivateDirty; 158 /** The shared dirty pages used by everything else. */ 159 public int otherSharedDirty; 160 /** The private clean pages used by everything else. */ 161 /** @hide We may want to expose this, eventually. */ 162 public int otherPrivateClean; 163 /** The shared clean pages used by everything else. */ 164 /** @hide We may want to expose this, eventually. */ 165 public int otherSharedClean; 166 /** The dirty pages used by anyting else that have been swapped out. */ 167 /** @hide We may want to expose this, eventually. */ 168 public int otherSwappedOut; 169 170 /** @hide */ 171 public static final int NUM_OTHER_STATS = 17; 172 173 /** @hide */ 174 public static final int NUM_DVK_STATS = 8; 175 176 /** @hide */ 177 public static final int NUM_CATEGORIES = 7; 178 179 /** @hide */ 180 public static final int offsetPss = 0; 181 /** @hide */ 182 public static final int offsetSwappablePss = 1; 183 /** @hide */ 184 public static final int offsetPrivateDirty = 2; 185 /** @hide */ 186 public static final int offsetSharedDirty = 3; 187 /** @hide */ 188 public static final int offsetPrivateClean = 4; 189 /** @hide */ 190 public static final int offsetSharedClean = 5; 191 /** @hide */ 192 public static final int offsetSwappedOut = 6; 193 194 private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES]; 195 196 public MemoryInfo() { 197 } 198 199 /** 200 * Return total PSS memory usage in kB. 201 */ 202 public int getTotalPss() { 203 return dalvikPss + nativePss + otherPss; 204 } 205 206 /** 207 * @hide Return total PSS memory usage in kB. 208 */ 209 public int getTotalUss() { 210 return dalvikPrivateClean + dalvikPrivateDirty 211 + nativePrivateClean + nativePrivateDirty 212 + otherPrivateClean + otherPrivateDirty; 213 } 214 215 /** 216 * Return total PSS memory usage in kB. 217 */ 218 public int getTotalSwappablePss() { 219 return dalvikSwappablePss + nativeSwappablePss + otherSwappablePss; 220 } 221 222 /** 223 * Return total private dirty memory usage in kB. 224 */ 225 public int getTotalPrivateDirty() { 226 return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty; 227 } 228 229 /** 230 * Return total shared dirty memory usage in kB. 231 */ 232 public int getTotalSharedDirty() { 233 return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty; 234 } 235 236 /** 237 * Return total shared clean memory usage in kB. 238 */ 239 public int getTotalPrivateClean() { 240 return dalvikPrivateClean + nativePrivateClean + otherPrivateClean; 241 } 242 243 /** 244 * Return total shared clean memory usage in kB. 245 */ 246 public int getTotalSharedClean() { 247 return dalvikSharedClean + nativeSharedClean + otherSharedClean; 248 } 249 250 /** 251 * Return total swapped out memory in kB. 252 * @hide 253 */ 254 public int getTotalSwappedOut() { 255 return dalvikSwappedOut + nativeSwappedOut + otherSwappedOut; 256 } 257 258 /** @hide */ 259 public int getOtherPss(int which) { 260 return otherStats[which*NUM_CATEGORIES + offsetPss]; 261 } 262 263 264 /** @hide */ 265 public int getOtherSwappablePss(int which) { 266 return otherStats[which*NUM_CATEGORIES + offsetSwappablePss]; 267 } 268 269 270 /** @hide */ 271 public int getOtherPrivateDirty(int which) { 272 return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty]; 273 } 274 275 /** @hide */ 276 public int getOtherSharedDirty(int which) { 277 return otherStats[which*NUM_CATEGORIES + offsetSharedDirty]; 278 } 279 280 /** @hide */ 281 public int getOtherPrivateClean(int which) { 282 return otherStats[which*NUM_CATEGORIES + offsetPrivateClean]; 283 } 284 285 /** @hide */ 286 public int getOtherSharedClean(int which) { 287 return otherStats[which*NUM_CATEGORIES + offsetSharedClean]; 288 } 289 290 /** @hide */ 291 public int getOtherSwappedOut(int which) { 292 return otherStats[which*NUM_CATEGORIES + offsetSwappedOut]; 293 } 294 295 /** @hide */ 296 public static String getOtherLabel(int which) { 297 switch (which) { 298 case 0: return "Dalvik Other"; 299 case 1: return "Stack"; 300 case 2: return "Cursor"; 301 case 3: return "Ashmem"; 302 case 4: return "Gfx dev"; 303 case 5: return "Other dev"; 304 case 6: return ".so mmap"; 305 case 7: return ".jar mmap"; 306 case 8: return ".apk mmap"; 307 case 9: return ".ttf mmap"; 308 case 10: return ".dex mmap"; 309 case 11: return ".oat mmap"; 310 case 12: return ".art mmap"; 311 case 13: return "Other mmap"; 312 case 14: return "EGL mtrack"; 313 case 15: return "GL mtrack"; 314 case 16: return "Other mtrack"; 315 case 17: return ".Heap"; 316 case 18: return ".LOS"; 317 case 19: return ".LinearAlloc"; 318 case 20: return ".GC"; 319 case 21: return ".JITCache"; 320 case 22: return ".Zygote"; 321 case 23: return ".NonMoving"; 322 case 24: return ".IndirectRef"; 323 default: return "????"; 324 } 325 } 326 327 public int describeContents() { 328 return 0; 329 } 330 331 public void writeToParcel(Parcel dest, int flags) { 332 dest.writeInt(dalvikPss); 333 dest.writeInt(dalvikSwappablePss); 334 dest.writeInt(dalvikPrivateDirty); 335 dest.writeInt(dalvikSharedDirty); 336 dest.writeInt(dalvikPrivateClean); 337 dest.writeInt(dalvikSharedClean); 338 dest.writeInt(dalvikSwappedOut); 339 dest.writeInt(nativePss); 340 dest.writeInt(nativeSwappablePss); 341 dest.writeInt(nativePrivateDirty); 342 dest.writeInt(nativeSharedDirty); 343 dest.writeInt(nativePrivateClean); 344 dest.writeInt(nativeSharedClean); 345 dest.writeInt(nativeSwappedOut); 346 dest.writeInt(otherPss); 347 dest.writeInt(otherSwappablePss); 348 dest.writeInt(otherPrivateDirty); 349 dest.writeInt(otherSharedDirty); 350 dest.writeInt(otherPrivateClean); 351 dest.writeInt(otherSharedClean); 352 dest.writeInt(otherSwappedOut); 353 dest.writeIntArray(otherStats); 354 } 355 356 public void readFromParcel(Parcel source) { 357 dalvikPss = source.readInt(); 358 dalvikSwappablePss = source.readInt(); 359 dalvikPrivateDirty = source.readInt(); 360 dalvikSharedDirty = source.readInt(); 361 dalvikPrivateClean = source.readInt(); 362 dalvikSharedClean = source.readInt(); 363 dalvikSwappedOut = source.readInt(); 364 nativePss = source.readInt(); 365 nativeSwappablePss = source.readInt(); 366 nativePrivateDirty = source.readInt(); 367 nativeSharedDirty = source.readInt(); 368 nativePrivateClean = source.readInt(); 369 nativeSharedClean = source.readInt(); 370 nativeSwappedOut = source.readInt(); 371 otherPss = source.readInt(); 372 otherSwappablePss = source.readInt(); 373 otherPrivateDirty = source.readInt(); 374 otherSharedDirty = source.readInt(); 375 otherPrivateClean = source.readInt(); 376 otherSharedClean = source.readInt(); 377 otherSwappedOut = source.readInt(); 378 otherStats = source.createIntArray(); 379 } 380 381 public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() { 382 public MemoryInfo createFromParcel(Parcel source) { 383 return new MemoryInfo(source); 384 } 385 public MemoryInfo[] newArray(int size) { 386 return new MemoryInfo[size]; 387 } 388 }; 389 390 private MemoryInfo(Parcel source) { 391 readFromParcel(source); 392 } 393 } 394 395 396 /** 397 * Wait until a debugger attaches. As soon as the debugger attaches, 398 * this returns, so you will need to place a breakpoint after the 399 * waitForDebugger() call if you want to start tracing immediately. 400 */ 401 public static void waitForDebugger() { 402 if (!VMDebug.isDebuggingEnabled()) { 403 //System.out.println("debugging not enabled, not waiting"); 404 return; 405 } 406 if (isDebuggerConnected()) 407 return; 408 409 // if DDMS is listening, inform them of our plight 410 System.out.println("Sending WAIT chunk"); 411 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger" 412 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1); 413 DdmServer.sendChunk(waitChunk); 414 415 mWaiting = true; 416 while (!isDebuggerConnected()) { 417 try { Thread.sleep(SPIN_DELAY); } 418 catch (InterruptedException ie) {} 419 } 420 mWaiting = false; 421 422 System.out.println("Debugger has connected"); 423 424 /* 425 * There is no "ready to go" signal from the debugger, and we're 426 * not allowed to suspend ourselves -- the debugger expects us to 427 * be running happily, and gets confused if we aren't. We need to 428 * allow the debugger a chance to set breakpoints before we start 429 * running again. 430 * 431 * Sit and spin until the debugger has been idle for a short while. 432 */ 433 while (true) { 434 long delta = VMDebug.lastDebuggerActivity(); 435 if (delta < 0) { 436 System.out.println("debugger detached?"); 437 break; 438 } 439 440 if (delta < MIN_DEBUGGER_IDLE) { 441 System.out.println("waiting for debugger to settle..."); 442 try { Thread.sleep(SPIN_DELAY); } 443 catch (InterruptedException ie) {} 444 } else { 445 System.out.println("debugger has settled (" + delta + ")"); 446 break; 447 } 448 } 449 } 450 451 /** 452 * Returns "true" if one or more threads is waiting for a debugger 453 * to attach. 454 */ 455 public static boolean waitingForDebugger() { 456 return mWaiting; 457 } 458 459 /** 460 * Determine if a debugger is currently attached. 461 */ 462 public static boolean isDebuggerConnected() { 463 return VMDebug.isDebuggerConnected(); 464 } 465 466 /** 467 * Returns an array of strings that identify VM features. This is 468 * used by DDMS to determine what sorts of operations the VM can 469 * perform. 470 * 471 * @hide 472 */ 473 public static String[] getVmFeatureList() { 474 return VMDebug.getVmFeatureList(); 475 } 476 477 /** 478 * Change the JDWP port. 479 * 480 * @deprecated no longer needed or useful 481 */ 482 @Deprecated 483 public static void changeDebugPort(int port) {} 484 485 /** 486 * This is the pathname to the sysfs file that enables and disables 487 * tracing on the qemu emulator. 488 */ 489 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state"; 490 491 /** 492 * Enable qemu tracing. For this to work requires running everything inside 493 * the qemu emulator; otherwise, this method will have no effect. The trace 494 * file is specified on the command line when the emulator is started. For 495 * example, the following command line <br /> 496 * <code>emulator -trace foo</code><br /> 497 * will start running the emulator and create a trace file named "foo". This 498 * method simply enables writing the trace records to the trace file. 499 * 500 * <p> 501 * The main differences between this and {@link #startMethodTracing()} are 502 * that tracing in the qemu emulator traces every cpu instruction of every 503 * process, including kernel code, so we have more complete information, 504 * including all context switches. We can also get more detailed information 505 * such as cache misses. The sequence of calls is determined by 506 * post-processing the instruction trace. The qemu tracing is also done 507 * without modifying the application or perturbing the timing of calls 508 * because no instrumentation is added to the application being traced. 509 * </p> 510 * 511 * <p> 512 * One limitation of using this method compared to using 513 * {@link #startMethodTracing()} on the real device is that the emulator 514 * does not model all of the real hardware effects such as memory and 515 * bus contention. The emulator also has a simple cache model and cannot 516 * capture all the complexities of a real cache. 517 * </p> 518 */ 519 public static void startNativeTracing() { 520 // Open the sysfs file for writing and write "1" to it. 521 PrintWriter outStream = null; 522 try { 523 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE); 524 outStream = new FastPrintWriter(fos); 525 outStream.println("1"); 526 } catch (Exception e) { 527 } finally { 528 if (outStream != null) 529 outStream.close(); 530 } 531 532 VMDebug.startEmulatorTracing(); 533 } 534 535 /** 536 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing. 537 * 538 * <p>Tracing can be started and stopped as many times as desired. When 539 * the qemu emulator itself is stopped then the buffered trace records 540 * are flushed and written to the trace file. In fact, it is not necessary 541 * to call this method at all; simply killing qemu is sufficient. But 542 * starting and stopping a trace is useful for examining a specific 543 * region of code.</p> 544 */ 545 public static void stopNativeTracing() { 546 VMDebug.stopEmulatorTracing(); 547 548 // Open the sysfs file for writing and write "0" to it. 549 PrintWriter outStream = null; 550 try { 551 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE); 552 outStream = new FastPrintWriter(fos); 553 outStream.println("0"); 554 } catch (Exception e) { 555 // We could print an error message here but we probably want 556 // to quietly ignore errors if we are not running in the emulator. 557 } finally { 558 if (outStream != null) 559 outStream.close(); 560 } 561 } 562 563 /** 564 * Enable "emulator traces", in which information about the current 565 * method is made available to the "emulator -trace" feature. There 566 * is no corresponding "disable" call -- this is intended for use by 567 * the framework when tracing should be turned on and left that way, so 568 * that traces captured with F9/F10 will include the necessary data. 569 * 570 * This puts the VM into "profile" mode, which has performance 571 * consequences. 572 * 573 * To temporarily enable tracing, use {@link #startNativeTracing()}. 574 */ 575 public static void enableEmulatorTraceOutput() { 576 VMDebug.startEmulatorTracing(); 577 } 578 579 /** 580 * Start method tracing with default log name and buffer size. See <a 581href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 582 * information about reading these files. Call stopMethodTracing() to stop 583 * tracing. 584 */ 585 public static void startMethodTracing() { 586 VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0, false, 0); 587 } 588 589 /** 590 * Start method tracing, specifying the trace log file name. The trace 591 * file will be put under "/sdcard" unless an absolute path is given. 592 * See <a 593 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 594 * information about reading trace files. 595 * 596 * @param traceName Name for the trace log file to create. 597 * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace". 598 * If the files already exist, they will be truncated. 599 * If the trace file given does not end in ".trace", it will be appended for you. 600 */ 601 public static void startMethodTracing(String traceName) { 602 startMethodTracing(traceName, 0, 0); 603 } 604 605 /** 606 * Start method tracing, specifying the trace log file name and the 607 * buffer size. The trace files will be put under "/sdcard" unless an 608 * absolute path is given. See <a 609 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 610 * information about reading trace files. 611 * @param traceName Name for the trace log file to create. 612 * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace". 613 * If the files already exist, they will be truncated. 614 * If the trace file given does not end in ".trace", it will be appended for you. 615 * 616 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB. 617 */ 618 public static void startMethodTracing(String traceName, int bufferSize) { 619 startMethodTracing(traceName, bufferSize, 0); 620 } 621 622 /** 623 * Start method tracing, specifying the trace log file name and the 624 * buffer size. The trace files will be put under "/sdcard" unless an 625 * absolute path is given. See <a 626 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 627 * information about reading trace files. 628 * 629 * <p> 630 * When method tracing is enabled, the VM will run more slowly than 631 * usual, so the timings from the trace files should only be considered 632 * in relative terms (e.g. was run #1 faster than run #2). The times 633 * for native methods will not change, so don't try to use this to 634 * compare the performance of interpreted and native implementations of the 635 * same method. As an alternative, consider using sampling-based method 636 * tracing via {@link #startMethodTracingSampling(String, int, int)} or 637 * "native" tracing in the emulator via {@link #startNativeTracing()}. 638 * </p> 639 * 640 * @param traceName Name for the trace log file to create. 641 * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace". 642 * If the files already exist, they will be truncated. 643 * If the trace file given does not end in ".trace", it will be appended for you. 644 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB. 645 * @param flags Flags to control method tracing. The only one that is currently defined is {@link #TRACE_COUNT_ALLOCS}. 646 */ 647 public static void startMethodTracing(String traceName, int bufferSize, 648 int flags) { 649 VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, flags, false, 0); 650 } 651 652 /** 653 * Start sampling-based method tracing, specifying the trace log file name, 654 * the buffer size, and the sampling interval. The trace files will be put 655 * under "/sdcard" unless an absolute path is given. See <a 656 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> 657 * for information about reading trace files. 658 * 659 * @param traceName Name for the trace log file to create. 660 * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace". 661 * If the files already exist, they will be truncated. 662 * If the trace file given does not end in ".trace", it will be appended for you. 663 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB. 664 * @param intervalUs The amount of time between each sample in microseconds. 665 */ 666 public static void startMethodTracingSampling(String traceName, 667 int bufferSize, int intervalUs) { 668 VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, 0, true, intervalUs); 669 } 670 671 /** 672 * Formats name of trace log file for method tracing. 673 */ 674 private static String fixTraceName(String traceName) { 675 if (traceName == null) 676 traceName = DEFAULT_TRACE_FILE_PATH; 677 if (traceName.charAt(0) != '/') 678 traceName = DEFAULT_TRACE_PATH_PREFIX + traceName; 679 if (!traceName.endsWith(DEFAULT_TRACE_EXTENSION)) 680 traceName = traceName + DEFAULT_TRACE_EXTENSION; 681 682 return traceName; 683 } 684 685 /** 686 * Like startMethodTracing(String, int, int), but taking an already-opened 687 * FileDescriptor in which the trace is written. The file name is also 688 * supplied simply for logging. Makes a dup of the file descriptor. 689 * 690 * Not exposed in the SDK unless we are really comfortable with supporting 691 * this and find it would be useful. 692 * @hide 693 */ 694 public static void startMethodTracing(String traceName, FileDescriptor fd, 695 int bufferSize, int flags) { 696 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0); 697 } 698 699 /** 700 * Starts method tracing without a backing file. When stopMethodTracing 701 * is called, the result is sent directly to DDMS. (If DDMS is not 702 * attached when tracing ends, the profiling data will be discarded.) 703 * 704 * @hide 705 */ 706 public static void startMethodTracingDdms(int bufferSize, int flags, 707 boolean samplingEnabled, int intervalUs) { 708 VMDebug.startMethodTracingDdms(bufferSize, flags, samplingEnabled, intervalUs); 709 } 710 711 /** 712 * Determine whether method tracing is currently active and what type is 713 * active. 714 * 715 * @hide 716 */ 717 public static int getMethodTracingMode() { 718 return VMDebug.getMethodTracingMode(); 719 } 720 721 /** 722 * Stop method tracing. 723 */ 724 public static void stopMethodTracing() { 725 VMDebug.stopMethodTracing(); 726 } 727 728 /** 729 * Get an indication of thread CPU usage. The value returned 730 * indicates the amount of time that the current thread has spent 731 * executing code or waiting for certain types of I/O. 732 * 733 * The time is expressed in nanoseconds, and is only meaningful 734 * when compared to the result from an earlier call. Note that 735 * nanosecond resolution does not imply nanosecond accuracy. 736 * 737 * On system which don't support this operation, the call returns -1. 738 */ 739 public static long threadCpuTimeNanos() { 740 return VMDebug.threadCpuTimeNanos(); 741 } 742 743 /** 744 * Start counting the number and aggregate size of memory allocations. 745 * 746 * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting. 747 * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis 748 * code doesn't cause additional allocations. The various <code>get</code> methods return 749 * the specified value. And the various <code>reset</code> methods reset the specified 750 * count.</p> 751 * 752 * <p>Counts are kept for the system as a whole (global) and for each thread. 753 * The per-thread counts for threads other than the current thread 754 * are not cleared by the "reset" or "start" calls.</p> 755 * 756 * @deprecated Accurate counting is a burden on the runtime and may be removed. 757 */ 758 @Deprecated 759 public static void startAllocCounting() { 760 VMDebug.startAllocCounting(); 761 } 762 763 /** 764 * Stop counting the number and aggregate size of memory allocations. 765 * 766 * @deprecated Accurate counting is a burden on the runtime and may be removed. 767 */ 768 @Deprecated 769 public static void stopAllocCounting() { 770 VMDebug.stopAllocCounting(); 771 } 772 773 /** 774 * Returns the global count of objects allocated by the runtime between a 775 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 776 * 777 * @deprecated Accurate counting is a burden on the runtime and may be removed. 778 */ 779 @Deprecated 780 public static int getGlobalAllocCount() { 781 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS); 782 } 783 784 /** 785 * Clears the global count of objects allocated. 786 * @see #getGlobalAllocCount() 787 * 788 * @deprecated Accurate counting is a burden on the runtime and may be removed. 789 */ 790 @Deprecated 791 public static void resetGlobalAllocCount() { 792 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS); 793 } 794 795 /** 796 * Returns the global size, in bytes, of objects allocated by the runtime between a 797 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 798 * 799 * @deprecated Accurate counting is a burden on the runtime and may be removed. 800 */ 801 @Deprecated 802 public static int getGlobalAllocSize() { 803 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES); 804 } 805 806 /** 807 * Clears the global size of objects allocated. 808 * @see #getGlobalAllocSize() 809 * 810 * @deprecated Accurate counting is a burden on the runtime and may be removed. 811 */ 812 @Deprecated 813 public static void resetGlobalAllocSize() { 814 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES); 815 } 816 817 /** 818 * Returns the global count of objects freed by the runtime between a 819 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 820 * 821 * @deprecated Accurate counting is a burden on the runtime and may be removed. 822 */ 823 @Deprecated 824 public static int getGlobalFreedCount() { 825 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS); 826 } 827 828 /** 829 * Clears the global count of objects freed. 830 * @see #getGlobalFreedCount() 831 * 832 * @deprecated Accurate counting is a burden on the runtime and may be removed. 833 */ 834 @Deprecated 835 public static void resetGlobalFreedCount() { 836 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS); 837 } 838 839 /** 840 * Returns the global size, in bytes, of objects freed by the runtime between a 841 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 842 * 843 * @deprecated Accurate counting is a burden on the runtime and may be removed. 844 */ 845 @Deprecated 846 public static int getGlobalFreedSize() { 847 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES); 848 } 849 850 /** 851 * Clears the global size of objects freed. 852 * @see #getGlobalFreedSize() 853 * 854 * @deprecated Accurate counting is a burden on the runtime and may be removed. 855 */ 856 @Deprecated 857 public static void resetGlobalFreedSize() { 858 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES); 859 } 860 861 /** 862 * Returns the number of non-concurrent GC invocations between a 863 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 864 * 865 * @deprecated Accurate counting is a burden on the runtime and may be removed. 866 */ 867 @Deprecated 868 public static int getGlobalGcInvocationCount() { 869 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS); 870 } 871 872 /** 873 * Clears the count of non-concurrent GC invocations. 874 * @see #getGlobalGcInvocationCount() 875 * 876 * @deprecated Accurate counting is a burden on the runtime and may be removed. 877 */ 878 @Deprecated 879 public static void resetGlobalGcInvocationCount() { 880 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS); 881 } 882 883 /** 884 * Returns the number of classes successfully initialized (ie those that executed without 885 * throwing an exception) between a {@link #startAllocCounting() start} and 886 * {@link #stopAllocCounting() stop}. 887 * 888 * @deprecated Accurate counting is a burden on the runtime and may be removed. 889 */ 890 @Deprecated 891 public static int getGlobalClassInitCount() { 892 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT); 893 } 894 895 /** 896 * Clears the count of classes initialized. 897 * @see #getGlobalClassInitCount() 898 * 899 * @deprecated Accurate counting is a burden on the runtime and may be removed. 900 */ 901 @Deprecated 902 public static void resetGlobalClassInitCount() { 903 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT); 904 } 905 906 /** 907 * Returns the time spent successfully initializing classes between a 908 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 909 * 910 * @deprecated Accurate counting is a burden on the runtime and may be removed. 911 */ 912 @Deprecated 913 public static int getGlobalClassInitTime() { 914 /* cumulative elapsed time for class initialization, in usec */ 915 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME); 916 } 917 918 /** 919 * Clears the count of time spent initializing classes. 920 * @see #getGlobalClassInitTime() 921 * 922 * @deprecated Accurate counting is a burden on the runtime and may be removed. 923 */ 924 @Deprecated 925 public static void resetGlobalClassInitTime() { 926 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME); 927 } 928 929 /** 930 * This method exists for compatibility and always returns 0. 931 * @deprecated This method is now obsolete. 932 */ 933 @Deprecated 934 public static int getGlobalExternalAllocCount() { 935 return 0; 936 } 937 938 /** 939 * This method exists for compatibility and has no effect. 940 * @deprecated This method is now obsolete. 941 */ 942 @Deprecated 943 public static void resetGlobalExternalAllocSize() {} 944 945 /** 946 * This method exists for compatibility and has no effect. 947 * @deprecated This method is now obsolete. 948 */ 949 @Deprecated 950 public static void resetGlobalExternalAllocCount() {} 951 952 /** 953 * This method exists for compatibility and always returns 0. 954 * @deprecated This method is now obsolete. 955 */ 956 @Deprecated 957 public static int getGlobalExternalAllocSize() { 958 return 0; 959 } 960 961 /** 962 * This method exists for compatibility and always returns 0. 963 * @deprecated This method is now obsolete. 964 */ 965 @Deprecated 966 public static int getGlobalExternalFreedCount() { 967 return 0; 968 } 969 970 /** 971 * This method exists for compatibility and has no effect. 972 * @deprecated This method is now obsolete. 973 */ 974 @Deprecated 975 public static void resetGlobalExternalFreedCount() {} 976 977 /** 978 * This method exists for compatibility and has no effect. 979 * @deprecated This method is now obsolete. 980 */ 981 @Deprecated 982 public static int getGlobalExternalFreedSize() { 983 return 0; 984 } 985 986 /** 987 * This method exists for compatibility and has no effect. 988 * @deprecated This method is now obsolete. 989 */ 990 @Deprecated 991 public static void resetGlobalExternalFreedSize() {} 992 993 /** 994 * Returns the thread-local count of objects allocated by the runtime between a 995 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 996 * 997 * @deprecated Accurate counting is a burden on the runtime and may be removed. 998 */ 999 @Deprecated 1000 public static int getThreadAllocCount() { 1001 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS); 1002 } 1003 1004 /** 1005 * Clears the thread-local count of objects allocated. 1006 * @see #getThreadAllocCount() 1007 * 1008 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1009 */ 1010 @Deprecated 1011 public static void resetThreadAllocCount() { 1012 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS); 1013 } 1014 1015 /** 1016 * Returns the thread-local size of objects allocated by the runtime between a 1017 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1018 * @return The allocated size in bytes. 1019 * 1020 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1021 */ 1022 @Deprecated 1023 public static int getThreadAllocSize() { 1024 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES); 1025 } 1026 1027 /** 1028 * Clears the thread-local count of objects allocated. 1029 * @see #getThreadAllocSize() 1030 * 1031 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1032 */ 1033 @Deprecated 1034 public static void resetThreadAllocSize() { 1035 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES); 1036 } 1037 1038 /** 1039 * This method exists for compatibility and has no effect. 1040 * @deprecated This method is now obsolete. 1041 */ 1042 @Deprecated 1043 public static int getThreadExternalAllocCount() { 1044 return 0; 1045 } 1046 1047 /** 1048 * This method exists for compatibility and has no effect. 1049 * @deprecated This method is now obsolete. 1050 */ 1051 @Deprecated 1052 public static void resetThreadExternalAllocCount() {} 1053 1054 /** 1055 * This method exists for compatibility and has no effect. 1056 * @deprecated This method is now obsolete. 1057 */ 1058 @Deprecated 1059 public static int getThreadExternalAllocSize() { 1060 return 0; 1061 } 1062 1063 /** 1064 * This method exists for compatibility and has no effect. 1065 * @deprecated This method is now obsolete. 1066 */ 1067 @Deprecated 1068 public static void resetThreadExternalAllocSize() {} 1069 1070 /** 1071 * Returns the number of thread-local non-concurrent GC invocations between a 1072 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1073 * 1074 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1075 */ 1076 @Deprecated 1077 public static int getThreadGcInvocationCount() { 1078 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS); 1079 } 1080 1081 /** 1082 * Clears the thread-local count of non-concurrent GC invocations. 1083 * @see #getThreadGcInvocationCount() 1084 * 1085 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1086 */ 1087 @Deprecated 1088 public static void resetThreadGcInvocationCount() { 1089 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS); 1090 } 1091 1092 /** 1093 * Clears all the global and thread-local memory allocation counters. 1094 * @see #startAllocCounting() 1095 * 1096 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1097 */ 1098 @Deprecated 1099 public static void resetAllCounts() { 1100 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS); 1101 } 1102 1103 /** 1104 * Returns the size of the native heap. 1105 * @return The size of the native heap in bytes. 1106 */ 1107 public static native long getNativeHeapSize(); 1108 1109 /** 1110 * Returns the amount of allocated memory in the native heap. 1111 * @return The allocated size in bytes. 1112 */ 1113 public static native long getNativeHeapAllocatedSize(); 1114 1115 /** 1116 * Returns the amount of free memory in the native heap. 1117 * @return The freed size in bytes. 1118 */ 1119 public static native long getNativeHeapFreeSize(); 1120 1121 /** 1122 * Retrieves information about this processes memory usages. This information is broken down by 1123 * how much is in use by dalivk, the native heap, and everything else. 1124 */ 1125 public static native void getMemoryInfo(MemoryInfo memoryInfo); 1126 1127 /** 1128 * Note: currently only works when the requested pid has the same UID 1129 * as the caller. 1130 * @hide 1131 */ 1132 public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo); 1133 1134 /** 1135 * Retrieves the PSS memory used by the process as given by the 1136 * smaps. 1137 */ 1138 public static native long getPss(); 1139 1140 /** 1141 * Retrieves the PSS memory used by the process as given by the 1142 * smaps. Optionally supply a long array of 1 entry to also 1143 * receive the uss of the process, and another array to also 1144 * retrieve the separate memtrack size. @hide 1145 */ 1146 public static native long getPss(int pid, long[] outUss, long[] outMemtrack); 1147 1148 /** @hide */ 1149 public static final int MEMINFO_TOTAL = 0; 1150 /** @hide */ 1151 public static final int MEMINFO_FREE = 1; 1152 /** @hide */ 1153 public static final int MEMINFO_BUFFERS = 2; 1154 /** @hide */ 1155 public static final int MEMINFO_CACHED = 3; 1156 /** @hide */ 1157 public static final int MEMINFO_SHMEM = 4; 1158 /** @hide */ 1159 public static final int MEMINFO_SLAB = 5; 1160 /** @hide */ 1161 public static final int MEMINFO_SWAP_TOTAL = 6; 1162 /** @hide */ 1163 public static final int MEMINFO_SWAP_FREE = 7; 1164 /** @hide */ 1165 public static final int MEMINFO_ZRAM_TOTAL = 8; 1166 /** @hide */ 1167 public static final int MEMINFO_MAPPED = 9; 1168 /** @hide */ 1169 public static final int MEMINFO_VM_ALLOC_USED = 10; 1170 /** @hide */ 1171 public static final int MEMINFO_PAGE_TABLES = 11; 1172 /** @hide */ 1173 public static final int MEMINFO_KERNEL_STACK = 12; 1174 /** @hide */ 1175 public static final int MEMINFO_COUNT = 13; 1176 1177 /** 1178 * Retrieves /proc/meminfo. outSizes is filled with fields 1179 * as defined by MEMINFO_* offsets. 1180 * @hide 1181 */ 1182 public static native void getMemInfo(long[] outSizes); 1183 1184 /** 1185 * Establish an object allocation limit in the current thread. 1186 * This feature was never enabled in release builds. The 1187 * allocation limits feature was removed in Honeycomb. This 1188 * method exists for compatibility and always returns -1 and has 1189 * no effect. 1190 * 1191 * @deprecated This method is now obsolete. 1192 */ 1193 @Deprecated 1194 public static int setAllocationLimit(int limit) { 1195 return -1; 1196 } 1197 1198 /** 1199 * Establish a global object allocation limit. This feature was 1200 * never enabled in release builds. The allocation limits feature 1201 * was removed in Honeycomb. This method exists for compatibility 1202 * and always returns -1 and has no effect. 1203 * 1204 * @deprecated This method is now obsolete. 1205 */ 1206 @Deprecated 1207 public static int setGlobalAllocationLimit(int limit) { 1208 return -1; 1209 } 1210 1211 /** 1212 * Dump a list of all currently loaded class to the log file. 1213 * 1214 * @param flags See constants above. 1215 */ 1216 public static void printLoadedClasses(int flags) { 1217 VMDebug.printLoadedClasses(flags); 1218 } 1219 1220 /** 1221 * Get the number of loaded classes. 1222 * @return the number of loaded classes. 1223 */ 1224 public static int getLoadedClassCount() { 1225 return VMDebug.getLoadedClassCount(); 1226 } 1227 1228 /** 1229 * Dump "hprof" data to the specified file. This may cause a GC. 1230 * 1231 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof"). 1232 * @throws UnsupportedOperationException if the VM was built without 1233 * HPROF support. 1234 * @throws IOException if an error occurs while opening or writing files. 1235 */ 1236 public static void dumpHprofData(String fileName) throws IOException { 1237 VMDebug.dumpHprofData(fileName); 1238 } 1239 1240 /** 1241 * Like dumpHprofData(String), but takes an already-opened 1242 * FileDescriptor to which the trace is written. The file name is also 1243 * supplied simply for logging. Makes a dup of the file descriptor. 1244 * 1245 * Primarily for use by the "am" shell command. 1246 * 1247 * @hide 1248 */ 1249 public static void dumpHprofData(String fileName, FileDescriptor fd) 1250 throws IOException { 1251 VMDebug.dumpHprofData(fileName, fd); 1252 } 1253 1254 /** 1255 * Collect "hprof" and send it to DDMS. This may cause a GC. 1256 * 1257 * @throws UnsupportedOperationException if the VM was built without 1258 * HPROF support. 1259 * @hide 1260 */ 1261 public static void dumpHprofDataDdms() { 1262 VMDebug.dumpHprofDataDdms(); 1263 } 1264 1265 /** 1266 * Writes native heap data to the specified file descriptor. 1267 * 1268 * @hide 1269 */ 1270 public static native void dumpNativeHeap(FileDescriptor fd); 1271 1272 /** 1273 * Returns a count of the extant instances of a class. 1274 * 1275 * @hide 1276 */ 1277 public static long countInstancesOfClass(Class cls) { 1278 return VMDebug.countInstancesOfClass(cls, true); 1279 } 1280 1281 /** 1282 * Returns the number of sent transactions from this process. 1283 * @return The number of sent transactions or -1 if it could not read t. 1284 */ 1285 public static native int getBinderSentTransactions(); 1286 1287 /** 1288 * Returns the number of received transactions from the binder driver. 1289 * @return The number of received transactions or -1 if it could not read the stats. 1290 */ 1291 public static native int getBinderReceivedTransactions(); 1292 1293 /** 1294 * Returns the number of active local Binder objects that exist in the 1295 * current process. 1296 */ 1297 public static final native int getBinderLocalObjectCount(); 1298 1299 /** 1300 * Returns the number of references to remote proxy Binder objects that 1301 * exist in the current process. 1302 */ 1303 public static final native int getBinderProxyObjectCount(); 1304 1305 /** 1306 * Returns the number of death notification links to Binder objects that 1307 * exist in the current process. 1308 */ 1309 public static final native int getBinderDeathObjectCount(); 1310 1311 /** 1312 * Primes the register map cache. 1313 * 1314 * Only works for classes in the bootstrap class loader. Does not 1315 * cause classes to be loaded if they're not already present. 1316 * 1317 * The classAndMethodDesc argument is a concatentation of the VM-internal 1318 * class descriptor, method name, and method descriptor. Examples: 1319 * Landroid/os/Looper;.loop:()V 1320 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V 1321 * 1322 * @param classAndMethodDesc the method to prepare 1323 * 1324 * @hide 1325 */ 1326 public static final boolean cacheRegisterMap(String classAndMethodDesc) { 1327 return VMDebug.cacheRegisterMap(classAndMethodDesc); 1328 } 1329 1330 /** 1331 * Dumps the contents of VM reference tables (e.g. JNI locals and 1332 * globals) to the log file. 1333 * 1334 * @hide 1335 */ 1336 public static final void dumpReferenceTables() { 1337 VMDebug.dumpReferenceTables(); 1338 } 1339 1340 /** 1341 * API for gathering and querying instruction counts. 1342 * 1343 * Example usage: 1344 * <pre> 1345 * Debug.InstructionCount icount = new Debug.InstructionCount(); 1346 * icount.resetAndStart(); 1347 * [... do lots of stuff ...] 1348 * if (icount.collect()) { 1349 * System.out.println("Total instructions executed: " 1350 * + icount.globalTotal()); 1351 * System.out.println("Method invocations: " 1352 * + icount.globalMethodInvocations()); 1353 * } 1354 * </pre> 1355 * 1356 * @deprecated Instruction counting is no longer supported. 1357 */ 1358 @Deprecated 1359 public static class InstructionCount { 1360 private static final int NUM_INSTR = 1361 OpcodeInfo.MAXIMUM_PACKED_VALUE + 1; 1362 1363 private int[] mCounts; 1364 1365 public InstructionCount() { 1366 mCounts = new int[NUM_INSTR]; 1367 } 1368 1369 /** 1370 * Reset counters and ensure counts are running. Counts may 1371 * have already been running. 1372 * 1373 * @return true if counting was started 1374 */ 1375 public boolean resetAndStart() { 1376 try { 1377 VMDebug.startInstructionCounting(); 1378 VMDebug.resetInstructionCount(); 1379 } catch (UnsupportedOperationException uoe) { 1380 return false; 1381 } 1382 return true; 1383 } 1384 1385 /** 1386 * Collect instruction counts. May or may not stop the 1387 * counting process. 1388 */ 1389 public boolean collect() { 1390 try { 1391 VMDebug.stopInstructionCounting(); 1392 VMDebug.getInstructionCount(mCounts); 1393 } catch (UnsupportedOperationException uoe) { 1394 return false; 1395 } 1396 return true; 1397 } 1398 1399 /** 1400 * Return the total number of instructions executed globally (i.e. in 1401 * all threads). 1402 */ 1403 public int globalTotal() { 1404 int count = 0; 1405 1406 for (int i = 0; i < NUM_INSTR; i++) { 1407 count += mCounts[i]; 1408 } 1409 1410 return count; 1411 } 1412 1413 /** 1414 * Return the total number of method-invocation instructions 1415 * executed globally. 1416 */ 1417 public int globalMethodInvocations() { 1418 int count = 0; 1419 1420 for (int i = 0; i < NUM_INSTR; i++) { 1421 if (OpcodeInfo.isInvoke(i)) { 1422 count += mCounts[i]; 1423 } 1424 } 1425 1426 return count; 1427 } 1428 } 1429 1430 /** 1431 * A Map of typed debug properties. 1432 */ 1433 private static final TypedProperties debugProperties; 1434 1435 /* 1436 * Load the debug properties from the standard files into debugProperties. 1437 */ 1438 static { 1439 if (false) { 1440 final String TAG = "DebugProperties"; 1441 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" }; 1442 final TypedProperties tp = new TypedProperties(); 1443 1444 // Read the properties from each of the files, if present. 1445 for (String file : files) { 1446 Reader r; 1447 try { 1448 r = new FileReader(file); 1449 } catch (FileNotFoundException ex) { 1450 // It's ok if a file is missing. 1451 continue; 1452 } 1453 1454 try { 1455 tp.load(r); 1456 } catch (Exception ex) { 1457 throw new RuntimeException("Problem loading " + file, ex); 1458 } finally { 1459 try { 1460 r.close(); 1461 } catch (IOException ex) { 1462 // Ignore this error. 1463 } 1464 } 1465 } 1466 1467 debugProperties = tp.isEmpty() ? null : tp; 1468 } else { 1469 debugProperties = null; 1470 } 1471 } 1472 1473 1474 /** 1475 * Returns true if the type of the field matches the specified class. 1476 * Handles the case where the class is, e.g., java.lang.Boolean, but 1477 * the field is of the primitive "boolean" type. Also handles all of 1478 * the java.lang.Number subclasses. 1479 */ 1480 private static boolean fieldTypeMatches(Field field, Class<?> cl) { 1481 Class<?> fieldClass = field.getType(); 1482 if (fieldClass == cl) { 1483 return true; 1484 } 1485 Field primitiveTypeField; 1486 try { 1487 /* All of the classes we care about (Boolean, Integer, etc.) 1488 * have a Class field called "TYPE" that points to the corresponding 1489 * primitive class. 1490 */ 1491 primitiveTypeField = cl.getField("TYPE"); 1492 } catch (NoSuchFieldException ex) { 1493 return false; 1494 } 1495 try { 1496 return fieldClass == (Class<?>) primitiveTypeField.get(null); 1497 } catch (IllegalAccessException ex) { 1498 return false; 1499 } 1500 } 1501 1502 1503 /** 1504 * Looks up the property that corresponds to the field, and sets the field's value 1505 * if the types match. 1506 */ 1507 private static void modifyFieldIfSet(final Field field, final TypedProperties properties, 1508 final String propertyName) { 1509 if (field.getType() == java.lang.String.class) { 1510 int stringInfo = properties.getStringInfo(propertyName); 1511 switch (stringInfo) { 1512 case TypedProperties.STRING_SET: 1513 // Handle as usual below. 1514 break; 1515 case TypedProperties.STRING_NULL: 1516 try { 1517 field.set(null, null); // null object for static fields; null string 1518 } catch (IllegalAccessException ex) { 1519 throw new IllegalArgumentException( 1520 "Cannot set field for " + propertyName, ex); 1521 } 1522 return; 1523 case TypedProperties.STRING_NOT_SET: 1524 return; 1525 case TypedProperties.STRING_TYPE_MISMATCH: 1526 throw new IllegalArgumentException( 1527 "Type of " + propertyName + " " + 1528 " does not match field type (" + field.getType() + ")"); 1529 default: 1530 throw new IllegalStateException( 1531 "Unexpected getStringInfo(" + propertyName + ") return value " + 1532 stringInfo); 1533 } 1534 } 1535 Object value = properties.get(propertyName); 1536 if (value != null) { 1537 if (!fieldTypeMatches(field, value.getClass())) { 1538 throw new IllegalArgumentException( 1539 "Type of " + propertyName + " (" + value.getClass() + ") " + 1540 " does not match field type (" + field.getType() + ")"); 1541 } 1542 try { 1543 field.set(null, value); // null object for static fields 1544 } catch (IllegalAccessException ex) { 1545 throw new IllegalArgumentException( 1546 "Cannot set field for " + propertyName, ex); 1547 } 1548 } 1549 } 1550 1551 1552 /** 1553 * Equivalent to <code>setFieldsOn(cl, false)</code>. 1554 * 1555 * @see #setFieldsOn(Class, boolean) 1556 * 1557 * @hide 1558 */ 1559 public static void setFieldsOn(Class<?> cl) { 1560 setFieldsOn(cl, false); 1561 } 1562 1563 /** 1564 * Reflectively sets static fields of a class based on internal debugging 1565 * properties. This method is a no-op if false is 1566 * false. 1567 * <p> 1568 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will 1569 * always be false in release builds. This API is typically only useful 1570 * for platform developers. 1571 * </p> 1572 * Class setup: define a class whose only fields are non-final, static 1573 * primitive types (except for "char") or Strings. In a static block 1574 * after the field definitions/initializations, pass the class to 1575 * this method, Debug.setFieldsOn(). Example: 1576 * <pre> 1577 * package com.example; 1578 * 1579 * import android.os.Debug; 1580 * 1581 * public class MyDebugVars { 1582 * public static String s = "a string"; 1583 * public static String s2 = "second string"; 1584 * public static String ns = null; 1585 * public static boolean b = false; 1586 * public static int i = 5; 1587 * @Debug.DebugProperty 1588 * public static float f = 0.1f; 1589 * @@Debug.DebugProperty 1590 * public static double d = 0.5d; 1591 * 1592 * // This MUST appear AFTER all fields are defined and initialized! 1593 * static { 1594 * // Sets all the fields 1595 * Debug.setFieldsOn(MyDebugVars.class); 1596 * 1597 * // Sets only the fields annotated with @Debug.DebugProperty 1598 * // Debug.setFieldsOn(MyDebugVars.class, true); 1599 * } 1600 * } 1601 * </pre> 1602 * setFieldsOn() may override the value of any field in the class based 1603 * on internal properties that are fixed at boot time. 1604 * <p> 1605 * These properties are only set during platform debugging, and are not 1606 * meant to be used as a general-purpose properties store. 1607 * 1608 * {@hide} 1609 * 1610 * @param cl The class to (possibly) modify 1611 * @param partial If false, sets all static fields, otherwise, only set 1612 * fields with the {@link android.os.Debug.DebugProperty} 1613 * annotation 1614 * @throws IllegalArgumentException if any fields are final or non-static, 1615 * or if the type of the field does not match the type of 1616 * the internal debugging property value. 1617 */ 1618 public static void setFieldsOn(Class<?> cl, boolean partial) { 1619 if (false) { 1620 if (debugProperties != null) { 1621 /* Only look for fields declared directly by the class, 1622 * so we don't mysteriously change static fields in superclasses. 1623 */ 1624 for (Field field : cl.getDeclaredFields()) { 1625 if (!partial || field.getAnnotation(DebugProperty.class) != null) { 1626 final String propertyName = cl.getName() + "." + field.getName(); 1627 boolean isStatic = Modifier.isStatic(field.getModifiers()); 1628 boolean isFinal = Modifier.isFinal(field.getModifiers()); 1629 1630 if (!isStatic || isFinal) { 1631 throw new IllegalArgumentException(propertyName + 1632 " must be static and non-final"); 1633 } 1634 modifyFieldIfSet(field, debugProperties, propertyName); 1635 } 1636 } 1637 } 1638 } else { 1639 Log.wtf(TAG, 1640 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) + 1641 ") called in non-DEBUG build"); 1642 } 1643 } 1644 1645 /** 1646 * Annotation to put on fields you want to set with 1647 * {@link Debug#setFieldsOn(Class, boolean)}. 1648 * 1649 * @hide 1650 */ 1651 @Target({ ElementType.FIELD }) 1652 @Retention(RetentionPolicy.RUNTIME) 1653 public @interface DebugProperty { 1654 } 1655 1656 /** 1657 * Get a debugging dump of a system service by name. 1658 * 1659 * <p>Most services require the caller to hold android.permission.DUMP. 1660 * 1661 * @param name of the service to dump 1662 * @param fd to write dump output to (usually an output log file) 1663 * @param args to pass to the service's dump method, may be null 1664 * @return true if the service was dumped successfully, false if 1665 * the service could not be found or had an error while dumping 1666 */ 1667 public static boolean dumpService(String name, FileDescriptor fd, String[] args) { 1668 IBinder service = ServiceManager.getService(name); 1669 if (service == null) { 1670 Log.e(TAG, "Can't find service to dump: " + name); 1671 return false; 1672 } 1673 1674 try { 1675 service.dump(fd, args); 1676 return true; 1677 } catch (RemoteException e) { 1678 Log.e(TAG, "Can't dump service: " + name, e); 1679 return false; 1680 } 1681 } 1682 1683 /** 1684 * Have the stack traces of the given native process dumped to the 1685 * specified file. Will be appended to the file. 1686 * @hide 1687 */ 1688 public static native void dumpNativeBacktraceToFile(int pid, String file); 1689 1690 /** 1691 * Return a String describing the calling method and location at a particular stack depth. 1692 * @param callStack the Thread stack 1693 * @param depth the depth of stack to return information for. 1694 * @return the String describing the caller at that depth. 1695 */ 1696 private static String getCaller(StackTraceElement callStack[], int depth) { 1697 // callStack[4] is the caller of the method that called getCallers() 1698 if (4 + depth >= callStack.length) { 1699 return "<bottom of call stack>"; 1700 } 1701 StackTraceElement caller = callStack[4 + depth]; 1702 return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber(); 1703 } 1704 1705 /** 1706 * Return a string consisting of methods and locations at multiple call stack levels. 1707 * @param depth the number of levels to return, starting with the immediate caller. 1708 * @return a string describing the call stack. 1709 * {@hide} 1710 */ 1711 public static String getCallers(final int depth) { 1712 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); 1713 StringBuffer sb = new StringBuffer(); 1714 for (int i = 0; i < depth; i++) { 1715 sb.append(getCaller(callStack, i)).append(" "); 1716 } 1717 return sb.toString(); 1718 } 1719 1720 /** 1721 * Return a string consisting of methods and locations at multiple call stack levels. 1722 * @param depth the number of levels to return, starting with the immediate caller. 1723 * @return a string describing the call stack. 1724 * {@hide} 1725 */ 1726 public static String getCallers(final int start, int depth) { 1727 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); 1728 StringBuffer sb = new StringBuffer(); 1729 depth += start; 1730 for (int i = start; i < depth; i++) { 1731 sb.append(getCaller(callStack, i)).append(" "); 1732 } 1733 return sb.toString(); 1734 } 1735 1736 /** 1737 * Like {@link #getCallers(int)}, but each location is append to the string 1738 * as a new line with <var>linePrefix</var> in front of it. 1739 * @param depth the number of levels to return, starting with the immediate caller. 1740 * @param linePrefix prefix to put in front of each location. 1741 * @return a string describing the call stack. 1742 * {@hide} 1743 */ 1744 public static String getCallers(final int depth, String linePrefix) { 1745 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); 1746 StringBuffer sb = new StringBuffer(); 1747 for (int i = 0; i < depth; i++) { 1748 sb.append(linePrefix).append(getCaller(callStack, i)).append("\n"); 1749 } 1750 return sb.toString(); 1751 } 1752 1753 /** 1754 * @return a String describing the immediate caller of the calling method. 1755 * {@hide} 1756 */ 1757 public static String getCaller() { 1758 return getCaller(Thread.currentThread().getStackTrace(), 0); 1759 } 1760} 1761