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 17 package android.os; 18 19 import com.android.internal.util.FastPrintWriter; 20 import com.android.internal.util.TypedProperties; 21 22 import android.app.AppGlobals; 23 import android.content.Context; 24 import android.util.Log; 25 26 import java.io.File; 27 import java.io.FileDescriptor; 28 import java.io.FileNotFoundException; 29 import java.io.FileOutputStream; 30 import java.io.FileReader; 31 import java.io.IOException; 32 import java.io.PrintWriter; 33 import java.io.Reader; 34 import java.lang.reflect.Field; 35 import java.lang.reflect.Modifier; 36 import java.lang.annotation.Target; 37 import java.lang.annotation.ElementType; 38 import java.lang.annotation.Retention; 39 import java.lang.annotation.RetentionPolicy; 40 import java.util.HashMap; 41 import java.util.Map; 42 43 import org.apache.harmony.dalvik.ddmc.Chunk; 44 import org.apache.harmony.dalvik.ddmc.ChunkHandler; 45 import org.apache.harmony.dalvik.ddmc.DdmServer; 46 47 import dalvik.bytecode.OpcodeInfo; 48 import dalvik.system.VMDebug; 49 50 51 /** 52 * Provides various debugging methods for Android applications, including 53 * tracing and allocation counts. 54 * <p><strong>Logging Trace Files</strong></p> 55 * <p>Debug can create log files that give details about an application, such as 56 * a call stack and start/stop times for any running methods. See <a 57 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for 58 * information about reading trace files. To start logging trace files, call one 59 * of the startMethodTracing() methods. To stop tracing, call 60 * {@link #stopMethodTracing()}. 61 */ 62 public final class Debug 63 { 64 private static final String TAG = "Debug"; 65 66 /** 67 * Flags for startMethodTracing(). These can be ORed together. 68 * 69 * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the 70 * trace key file. 71 * 72 * @deprecated Accurate counting is a burden on the runtime and may be removed. 73 */ 74 @Deprecated 75 public static final int TRACE_COUNT_ALLOCS = VMDebug.TRACE_COUNT_ALLOCS; 76 77 /** 78 * Flags for printLoadedClasses(). Default behavior is to only show 79 * the class name. 80 */ 81 public static final int SHOW_FULL_DETAIL = 1; 82 public static final int SHOW_CLASSLOADER = (1 << 1); 83 public static final int SHOW_INITIALIZED = (1 << 2); 84 85 // set/cleared by waitForDebugger() 86 private static volatile boolean mWaiting = false; 87 Debug()88 private Debug() {} 89 90 /* 91 * How long to wait for the debugger to finish sending requests. I've 92 * seen this hit 800msec on the device while waiting for a response 93 * to travel over USB and get processed, so we take that and add 94 * half a second. 95 */ 96 private static final int MIN_DEBUGGER_IDLE = 1300; // msec 97 98 /* how long to sleep when polling for activity */ 99 private static final int SPIN_DELAY = 200; // msec 100 101 /** 102 * Default trace file path and file 103 */ 104 private static final String DEFAULT_TRACE_BODY = "dmtrace"; 105 private static final String DEFAULT_TRACE_EXTENSION = ".trace"; 106 107 /** 108 * This class is used to retrieved various statistics about the memory mappings for this 109 * process. The returned info is broken down by dalvik, native, and other. All results are in kB. 110 */ 111 public static class MemoryInfo implements Parcelable { 112 /** The proportional set size for dalvik heap. (Doesn't include other Dalvik overhead.) */ 113 public int dalvikPss; 114 /** The proportional set size that is swappable for dalvik heap. */ 115 /** @hide We may want to expose this, eventually. */ 116 public int dalvikSwappablePss; 117 /** The private dirty pages used by dalvik heap. */ 118 public int dalvikPrivateDirty; 119 /** The shared dirty pages used by dalvik heap. */ 120 public int dalvikSharedDirty; 121 /** The private clean pages used by dalvik heap. */ 122 /** @hide We may want to expose this, eventually. */ 123 public int dalvikPrivateClean; 124 /** The shared clean pages used by dalvik heap. */ 125 /** @hide We may want to expose this, eventually. */ 126 public int dalvikSharedClean; 127 /** The dirty dalvik pages that have been swapped out. */ 128 /** @hide We may want to expose this, eventually. */ 129 public int dalvikSwappedOut; 130 /** The dirty dalvik pages that have been swapped out, proportional. */ 131 /** @hide We may want to expose this, eventually. */ 132 public int dalvikSwappedOutPss; 133 134 /** The proportional set size for the native heap. */ 135 public int nativePss; 136 /** The proportional set size that is swappable for the native heap. */ 137 /** @hide We may want to expose this, eventually. */ 138 public int nativeSwappablePss; 139 /** The private dirty pages used by the native heap. */ 140 public int nativePrivateDirty; 141 /** The shared dirty pages used by the native heap. */ 142 public int nativeSharedDirty; 143 /** The private clean pages used by the native heap. */ 144 /** @hide We may want to expose this, eventually. */ 145 public int nativePrivateClean; 146 /** The shared clean pages used by the native heap. */ 147 /** @hide We may want to expose this, eventually. */ 148 public int nativeSharedClean; 149 /** The dirty native pages that have been swapped out. */ 150 /** @hide We may want to expose this, eventually. */ 151 public int nativeSwappedOut; 152 /** The dirty native pages that have been swapped out, proportional. */ 153 /** @hide We may want to expose this, eventually. */ 154 public int nativeSwappedOutPss; 155 156 /** The proportional set size for everything else. */ 157 public int otherPss; 158 /** The proportional set size that is swappable for everything else. */ 159 /** @hide We may want to expose this, eventually. */ 160 public int otherSwappablePss; 161 /** The private dirty pages used by everything else. */ 162 public int otherPrivateDirty; 163 /** The shared dirty pages used by everything else. */ 164 public int otherSharedDirty; 165 /** The private clean pages used by everything else. */ 166 /** @hide We may want to expose this, eventually. */ 167 public int otherPrivateClean; 168 /** The shared clean pages used by everything else. */ 169 /** @hide We may want to expose this, eventually. */ 170 public int otherSharedClean; 171 /** The dirty pages used by anyting else that have been swapped out. */ 172 /** @hide We may want to expose this, eventually. */ 173 public int otherSwappedOut; 174 /** The dirty pages used by anyting else that have been swapped out, proportional. */ 175 /** @hide We may want to expose this, eventually. */ 176 public int otherSwappedOutPss; 177 178 /** Whether the kernel reports proportional swap usage */ 179 /** @hide */ 180 public boolean hasSwappedOutPss; 181 182 /** @hide */ 183 public static final int HEAP_UNKNOWN = 0; 184 /** @hide */ 185 public static final int HEAP_DALVIK = 1; 186 /** @hide */ 187 public static final int HEAP_NATIVE = 2; 188 189 /** @hide */ 190 public static final int OTHER_DALVIK_OTHER = 0; 191 /** @hide */ 192 public static final int OTHER_STACK = 1; 193 /** @hide */ 194 public static final int OTHER_CURSOR = 2; 195 /** @hide */ 196 public static final int OTHER_ASHMEM = 3; 197 /** @hide */ 198 public static final int OTHER_GL_DEV = 4; 199 /** @hide */ 200 public static final int OTHER_UNKNOWN_DEV = 5; 201 /** @hide */ 202 public static final int OTHER_SO = 6; 203 /** @hide */ 204 public static final int OTHER_JAR = 7; 205 /** @hide */ 206 public static final int OTHER_APK = 8; 207 /** @hide */ 208 public static final int OTHER_TTF = 9; 209 /** @hide */ 210 public static final int OTHER_DEX = 10; 211 /** @hide */ 212 public static final int OTHER_OAT = 11; 213 /** @hide */ 214 public static final int OTHER_ART = 12; 215 /** @hide */ 216 public static final int OTHER_UNKNOWN_MAP = 13; 217 /** @hide */ 218 public static final int OTHER_GRAPHICS = 14; 219 /** @hide */ 220 public static final int OTHER_GL = 15; 221 /** @hide */ 222 public static final int OTHER_OTHER_MEMTRACK = 16; 223 224 /** @hide */ 225 public static final int OTHER_DALVIK_NORMAL = 17; 226 /** @hide */ 227 public static final int OTHER_DALVIK_LARGE = 18; 228 /** @hide */ 229 public static final int OTHER_DALVIK_LINEARALLOC = 19; 230 /** @hide */ 231 public static final int OTHER_DALVIK_ACCOUNTING = 20; 232 /** @hide */ 233 public static final int OTHER_DALVIK_CODE_CACHE = 21; 234 /** @hide */ 235 public static final int OTHER_DALVIK_ZYGOTE = 22; 236 /** @hide */ 237 public static final int OTHER_DALVIK_NON_MOVING = 23; 238 /** @hide */ 239 public static final int OTHER_DALVIK_INDIRECT_REFERENCE_TABLE = 24; 240 241 /** @hide */ 242 public static final int NUM_OTHER_STATS = 17; 243 244 /** @hide */ 245 public static final int NUM_DVK_STATS = 8; 246 247 /** @hide */ 248 public static final int NUM_CATEGORIES = 8; 249 250 /** @hide */ 251 public static final int offsetPss = 0; 252 /** @hide */ 253 public static final int offsetSwappablePss = 1; 254 /** @hide */ 255 public static final int offsetPrivateDirty = 2; 256 /** @hide */ 257 public static final int offsetSharedDirty = 3; 258 /** @hide */ 259 public static final int offsetPrivateClean = 4; 260 /** @hide */ 261 public static final int offsetSharedClean = 5; 262 /** @hide */ 263 public static final int offsetSwappedOut = 6; 264 /** @hide */ 265 public static final int offsetSwappedOutPss = 7; 266 267 private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES]; 268 MemoryInfo()269 public MemoryInfo() { 270 } 271 272 /** 273 * Return total PSS memory usage in kB. 274 */ getTotalPss()275 public int getTotalPss() { 276 return dalvikPss + nativePss + otherPss + getTotalSwappedOutPss(); 277 } 278 279 /** 280 * @hide Return total PSS memory usage in kB. 281 */ getTotalUss()282 public int getTotalUss() { 283 return dalvikPrivateClean + dalvikPrivateDirty 284 + nativePrivateClean + nativePrivateDirty 285 + otherPrivateClean + otherPrivateDirty; 286 } 287 288 /** 289 * Return total PSS memory usage in kB mapping a file of one of the following extension: 290 * .so, .jar, .apk, .ttf, .dex, .odex, .oat, .art . 291 */ getTotalSwappablePss()292 public int getTotalSwappablePss() { 293 return dalvikSwappablePss + nativeSwappablePss + otherSwappablePss; 294 } 295 296 /** 297 * Return total private dirty memory usage in kB. 298 */ getTotalPrivateDirty()299 public int getTotalPrivateDirty() { 300 return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty; 301 } 302 303 /** 304 * Return total shared dirty memory usage in kB. 305 */ getTotalSharedDirty()306 public int getTotalSharedDirty() { 307 return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty; 308 } 309 310 /** 311 * Return total shared clean memory usage in kB. 312 */ getTotalPrivateClean()313 public int getTotalPrivateClean() { 314 return dalvikPrivateClean + nativePrivateClean + otherPrivateClean; 315 } 316 317 /** 318 * Return total shared clean memory usage in kB. 319 */ getTotalSharedClean()320 public int getTotalSharedClean() { 321 return dalvikSharedClean + nativeSharedClean + otherSharedClean; 322 } 323 324 /** 325 * Return total swapped out memory in kB. 326 * @hide 327 */ getTotalSwappedOut()328 public int getTotalSwappedOut() { 329 return dalvikSwappedOut + nativeSwappedOut + otherSwappedOut; 330 } 331 332 /** 333 * Return total swapped out memory in kB, proportional. 334 * @hide 335 */ getTotalSwappedOutPss()336 public int getTotalSwappedOutPss() { 337 return dalvikSwappedOutPss + nativeSwappedOutPss + otherSwappedOutPss; 338 } 339 340 /** @hide */ getOtherPss(int which)341 public int getOtherPss(int which) { 342 return otherStats[which*NUM_CATEGORIES + offsetPss]; 343 } 344 345 346 /** @hide */ getOtherSwappablePss(int which)347 public int getOtherSwappablePss(int which) { 348 return otherStats[which*NUM_CATEGORIES + offsetSwappablePss]; 349 } 350 351 352 /** @hide */ getOtherPrivateDirty(int which)353 public int getOtherPrivateDirty(int which) { 354 return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty]; 355 } 356 357 /** @hide */ getOtherSharedDirty(int which)358 public int getOtherSharedDirty(int which) { 359 return otherStats[which*NUM_CATEGORIES + offsetSharedDirty]; 360 } 361 362 /** @hide */ getOtherPrivateClean(int which)363 public int getOtherPrivateClean(int which) { 364 return otherStats[which*NUM_CATEGORIES + offsetPrivateClean]; 365 } 366 367 /** @hide */ getOtherPrivate(int which)368 public int getOtherPrivate(int which) { 369 return getOtherPrivateClean(which) + getOtherPrivateDirty(which); 370 } 371 372 /** @hide */ getOtherSharedClean(int which)373 public int getOtherSharedClean(int which) { 374 return otherStats[which*NUM_CATEGORIES + offsetSharedClean]; 375 } 376 377 /** @hide */ getOtherSwappedOut(int which)378 public int getOtherSwappedOut(int which) { 379 return otherStats[which*NUM_CATEGORIES + offsetSwappedOut]; 380 } 381 382 /** @hide */ getOtherSwappedOutPss(int which)383 public int getOtherSwappedOutPss(int which) { 384 return otherStats[which*NUM_CATEGORIES + offsetSwappedOutPss]; 385 } 386 387 /** @hide */ getOtherLabel(int which)388 public static String getOtherLabel(int which) { 389 switch (which) { 390 case OTHER_DALVIK_OTHER: return "Dalvik Other"; 391 case OTHER_STACK: return "Stack"; 392 case OTHER_CURSOR: return "Cursor"; 393 case OTHER_ASHMEM: return "Ashmem"; 394 case OTHER_GL_DEV: return "Gfx dev"; 395 case OTHER_UNKNOWN_DEV: return "Other dev"; 396 case OTHER_SO: return ".so mmap"; 397 case OTHER_JAR: return ".jar mmap"; 398 case OTHER_APK: return ".apk mmap"; 399 case OTHER_TTF: return ".ttf mmap"; 400 case OTHER_DEX: return ".dex mmap"; 401 case OTHER_OAT: return ".oat mmap"; 402 case OTHER_ART: return ".art mmap"; 403 case OTHER_UNKNOWN_MAP: return "Other mmap"; 404 case OTHER_GRAPHICS: return "EGL mtrack"; 405 case OTHER_GL: return "GL mtrack"; 406 case OTHER_OTHER_MEMTRACK: return "Other mtrack"; 407 case OTHER_DALVIK_NORMAL: return ".Heap"; 408 case OTHER_DALVIK_LARGE: return ".LOS"; 409 case OTHER_DALVIK_LINEARALLOC: return ".LinearAlloc"; 410 case OTHER_DALVIK_ACCOUNTING: return ".GC"; 411 case OTHER_DALVIK_CODE_CACHE: return ".JITCache"; 412 case OTHER_DALVIK_ZYGOTE: return ".Zygote"; 413 case OTHER_DALVIK_NON_MOVING: return ".NonMoving"; 414 case OTHER_DALVIK_INDIRECT_REFERENCE_TABLE: return ".IndirectRef"; 415 default: return "????"; 416 } 417 } 418 419 /** 420 * Returns the value of a particular memory statistic or {@code null} if no 421 * such memory statistic exists. 422 * 423 * <p>The following table lists the memory statistics that are supported. 424 * Note that memory statistics may be added or removed in a future API level.</p> 425 * 426 * <table> 427 * <thead> 428 * <tr> 429 * <th>Memory statistic name</th> 430 * <th>Meaning</th> 431 * <th>Example</th> 432 * <th>Supported (API Levels)</th> 433 * </tr> 434 * </thead> 435 * <tbody> 436 * <tr> 437 * <td>summary.java-heap</td> 438 * <td>The private Java Heap usage in kB. This corresponds to the Java Heap field 439 * in the App Summary section output by dumpsys meminfo.</td> 440 * <td>{@code 1442}</td> 441 * <td>23</td> 442 * </tr> 443 * <tr> 444 * <td>summary.native-heap</td> 445 * <td>The private Native Heap usage in kB. This corresponds to the Native Heap 446 * field in the App Summary section output by dumpsys meminfo.</td> 447 * <td>{@code 1442}</td> 448 * <td>23</td> 449 * </tr> 450 * <tr> 451 * <td>summary.code</td> 452 * <td>The memory usage for static code and resources in kB. This corresponds to 453 * the Code field in the App Summary section output by dumpsys meminfo.</td> 454 * <td>{@code 1442}</td> 455 * <td>23</td> 456 * </tr> 457 * <tr> 458 * <td>summary.stack</td> 459 * <td>The stack usage in kB. This corresponds to the Stack field in the 460 * App Summary section output by dumpsys meminfo.</td> 461 * <td>{@code 1442}</td> 462 * <td>23</td> 463 * </tr> 464 * <tr> 465 * <td>summary.graphics</td> 466 * <td>The graphics usage in kB. This corresponds to the Graphics field in the 467 * App Summary section output by dumpsys meminfo.</td> 468 * <td>{@code 1442}</td> 469 * <td>23</td> 470 * </tr> 471 * <tr> 472 * <td>summary.private-other</td> 473 * <td>Other private memory usage in kB. This corresponds to the Private Other 474 * field output in the App Summary section by dumpsys meminfo.</td> 475 * <td>{@code 1442}</td> 476 * <td>23</td> 477 * </tr> 478 * <tr> 479 * <td>summary.system</td> 480 * <td>Shared and system memory usage in kB. This corresponds to the System 481 * field output in the App Summary section by dumpsys meminfo.</td> 482 * <td>{@code 1442}</td> 483 * <td>23</td> 484 * </tr> 485 * <tr> 486 * <td>summary.total-pss</td> 487 * <td>Total PPS memory usage in kB.</td> 488 * <td>{@code 1442}</td> 489 * <td>23</td> 490 * </tr> 491 * <tr> 492 * <td>summary.total-swap</td> 493 * <td>Total swap usage in kB.</td> 494 * <td>{@code 1442}</td> 495 * <td>23</td> 496 * </tr> 497 * </tbody> 498 * </table> 499 */ getMemoryStat(String statName)500 public String getMemoryStat(String statName) { 501 switch(statName) { 502 case "summary.java-heap": 503 return Integer.toString(getSummaryJavaHeap()); 504 case "summary.native-heap": 505 return Integer.toString(getSummaryNativeHeap()); 506 case "summary.code": 507 return Integer.toString(getSummaryCode()); 508 case "summary.stack": 509 return Integer.toString(getSummaryStack()); 510 case "summary.graphics": 511 return Integer.toString(getSummaryGraphics()); 512 case "summary.private-other": 513 return Integer.toString(getSummaryPrivateOther()); 514 case "summary.system": 515 return Integer.toString(getSummarySystem()); 516 case "summary.total-pss": 517 return Integer.toString(getSummaryTotalPss()); 518 case "summary.total-swap": 519 return Integer.toString(getSummaryTotalSwap()); 520 default: 521 return null; 522 } 523 } 524 525 /** 526 * Returns a map of the names/values of the memory statistics 527 * that {@link #getMemoryStat(String)} supports. 528 * 529 * @return a map of the names/values of the supported memory statistics. 530 */ getMemoryStats()531 public Map<String, String> getMemoryStats() { 532 Map<String, String> stats = new HashMap<String, String>(); 533 stats.put("summary.java-heap", Integer.toString(getSummaryJavaHeap())); 534 stats.put("summary.native-heap", Integer.toString(getSummaryNativeHeap())); 535 stats.put("summary.code", Integer.toString(getSummaryCode())); 536 stats.put("summary.stack", Integer.toString(getSummaryStack())); 537 stats.put("summary.graphics", Integer.toString(getSummaryGraphics())); 538 stats.put("summary.private-other", Integer.toString(getSummaryPrivateOther())); 539 stats.put("summary.system", Integer.toString(getSummarySystem())); 540 stats.put("summary.total-pss", Integer.toString(getSummaryTotalPss())); 541 stats.put("summary.total-swap", Integer.toString(getSummaryTotalSwap())); 542 return stats; 543 } 544 545 /** 546 * Pss of Java Heap bytes in KB due to the application. 547 * Notes: 548 * * OTHER_ART is the boot image. Anything private here is blamed on 549 * the application, not the system. 550 * * dalvikPrivateDirty includes private zygote, which means the 551 * application dirtied something allocated by the zygote. We blame 552 * the application for that memory, not the system. 553 * * Does not include OTHER_DALVIK_OTHER, which is considered VM 554 * Overhead and lumped into Private Other. 555 * * We don't include dalvikPrivateClean, because there should be no 556 * such thing as private clean for the Java Heap. 557 * @hide 558 */ getSummaryJavaHeap()559 public int getSummaryJavaHeap() { 560 return dalvikPrivateDirty + getOtherPrivate(OTHER_ART); 561 } 562 563 /** 564 * Pss of Native Heap bytes in KB due to the application. 565 * Notes: 566 * * Includes private dirty malloc space. 567 * * We don't include nativePrivateClean, because there should be no 568 * such thing as private clean for the Native Heap. 569 * @hide 570 */ getSummaryNativeHeap()571 public int getSummaryNativeHeap() { 572 return nativePrivateDirty; 573 } 574 575 /** 576 * Pss of code and other static resource bytes in KB due to 577 * the application. 578 * @hide 579 */ getSummaryCode()580 public int getSummaryCode() { 581 return getOtherPrivate(OTHER_SO) 582 + getOtherPrivate(OTHER_JAR) 583 + getOtherPrivate(OTHER_APK) 584 + getOtherPrivate(OTHER_TTF) 585 + getOtherPrivate(OTHER_DEX) 586 + getOtherPrivate(OTHER_OAT); 587 } 588 589 /** 590 * Pss in KB of the stack due to the application. 591 * Notes: 592 * * Includes private dirty stack, which includes both Java and Native 593 * stack. 594 * * Does not include private clean stack, because there should be no 595 * such thing as private clean for the stack. 596 * @hide 597 */ getSummaryStack()598 public int getSummaryStack() { 599 return getOtherPrivateDirty(OTHER_STACK); 600 } 601 602 /** 603 * Pss in KB of graphics due to the application. 604 * Notes: 605 * * Includes private Gfx, EGL, and GL. 606 * * Warning: These numbers can be misreported by the graphics drivers. 607 * * We don't include shared graphics. It may make sense to, because 608 * shared graphics are likely buffers due to the application 609 * anyway, but it's simpler to implement to just group all shared 610 * memory into the System category. 611 * @hide 612 */ getSummaryGraphics()613 public int getSummaryGraphics() { 614 return getOtherPrivate(OTHER_GL_DEV) 615 + getOtherPrivate(OTHER_GRAPHICS) 616 + getOtherPrivate(OTHER_GL); 617 } 618 619 /** 620 * Pss in KB due to the application that haven't otherwise been 621 * accounted for. 622 * @hide 623 */ getSummaryPrivateOther()624 public int getSummaryPrivateOther() { 625 return getTotalPrivateClean() 626 + getTotalPrivateDirty() 627 - getSummaryJavaHeap() 628 - getSummaryNativeHeap() 629 - getSummaryCode() 630 - getSummaryStack() 631 - getSummaryGraphics(); 632 } 633 634 /** 635 * Pss in KB due to the system. 636 * Notes: 637 * * Includes all shared memory. 638 * @hide 639 */ getSummarySystem()640 public int getSummarySystem() { 641 return getTotalPss() 642 - getTotalPrivateClean() 643 - getTotalPrivateDirty(); 644 } 645 646 /** 647 * Total Pss in KB. 648 * @hide 649 */ getSummaryTotalPss()650 public int getSummaryTotalPss() { 651 return getTotalPss(); 652 } 653 654 /** 655 * Total Swap in KB. 656 * Notes: 657 * * Some of this memory belongs in other categories, but we don't 658 * know if the Swap memory is shared or private, so we don't know 659 * what to blame on the application and what on the system. 660 * For now, just lump all the Swap in one place. 661 * For kernels reporting SwapPss {@link #getSummaryTotalSwapPss()} 662 * will report the application proportional Swap. 663 * @hide 664 */ getSummaryTotalSwap()665 public int getSummaryTotalSwap() { 666 return getTotalSwappedOut(); 667 } 668 669 /** 670 * Total proportional Swap in KB. 671 * Notes: 672 * * Always 0 if {@link #hasSwappedOutPss} is false. 673 * @hide 674 */ getSummaryTotalSwapPss()675 public int getSummaryTotalSwapPss() { 676 return getTotalSwappedOutPss(); 677 } 678 679 /** 680 * Return true if the kernel is reporting pss swapped out... that is, if 681 * {@link #getSummaryTotalSwapPss()} will return non-0 values. 682 * @hide 683 */ hasSwappedOutPss()684 public boolean hasSwappedOutPss() { 685 return hasSwappedOutPss; 686 } 687 describeContents()688 public int describeContents() { 689 return 0; 690 } 691 writeToParcel(Parcel dest, int flags)692 public void writeToParcel(Parcel dest, int flags) { 693 dest.writeInt(dalvikPss); 694 dest.writeInt(dalvikSwappablePss); 695 dest.writeInt(dalvikPrivateDirty); 696 dest.writeInt(dalvikSharedDirty); 697 dest.writeInt(dalvikPrivateClean); 698 dest.writeInt(dalvikSharedClean); 699 dest.writeInt(dalvikSwappedOut); 700 dest.writeInt(nativePss); 701 dest.writeInt(nativeSwappablePss); 702 dest.writeInt(nativePrivateDirty); 703 dest.writeInt(nativeSharedDirty); 704 dest.writeInt(nativePrivateClean); 705 dest.writeInt(nativeSharedClean); 706 dest.writeInt(nativeSwappedOut); 707 dest.writeInt(otherPss); 708 dest.writeInt(otherSwappablePss); 709 dest.writeInt(otherPrivateDirty); 710 dest.writeInt(otherSharedDirty); 711 dest.writeInt(otherPrivateClean); 712 dest.writeInt(otherSharedClean); 713 dest.writeInt(otherSwappedOut); 714 dest.writeInt(hasSwappedOutPss ? 1 : 0); 715 dest.writeInt(otherSwappedOutPss); 716 dest.writeIntArray(otherStats); 717 } 718 readFromParcel(Parcel source)719 public void readFromParcel(Parcel source) { 720 dalvikPss = source.readInt(); 721 dalvikSwappablePss = source.readInt(); 722 dalvikPrivateDirty = source.readInt(); 723 dalvikSharedDirty = source.readInt(); 724 dalvikPrivateClean = source.readInt(); 725 dalvikSharedClean = source.readInt(); 726 dalvikSwappedOut = source.readInt(); 727 nativePss = source.readInt(); 728 nativeSwappablePss = source.readInt(); 729 nativePrivateDirty = source.readInt(); 730 nativeSharedDirty = source.readInt(); 731 nativePrivateClean = source.readInt(); 732 nativeSharedClean = source.readInt(); 733 nativeSwappedOut = source.readInt(); 734 otherPss = source.readInt(); 735 otherSwappablePss = source.readInt(); 736 otherPrivateDirty = source.readInt(); 737 otherSharedDirty = source.readInt(); 738 otherPrivateClean = source.readInt(); 739 otherSharedClean = source.readInt(); 740 otherSwappedOut = source.readInt(); 741 hasSwappedOutPss = source.readInt() != 0; 742 otherSwappedOutPss = source.readInt(); 743 otherStats = source.createIntArray(); 744 } 745 746 public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() { 747 public MemoryInfo createFromParcel(Parcel source) { 748 return new MemoryInfo(source); 749 } 750 public MemoryInfo[] newArray(int size) { 751 return new MemoryInfo[size]; 752 } 753 }; 754 MemoryInfo(Parcel source)755 private MemoryInfo(Parcel source) { 756 readFromParcel(source); 757 } 758 } 759 760 761 /** 762 * Wait until a debugger attaches. As soon as the debugger attaches, 763 * this returns, so you will need to place a breakpoint after the 764 * waitForDebugger() call if you want to start tracing immediately. 765 */ waitForDebugger()766 public static void waitForDebugger() { 767 if (!VMDebug.isDebuggingEnabled()) { 768 //System.out.println("debugging not enabled, not waiting"); 769 return; 770 } 771 if (isDebuggerConnected()) 772 return; 773 774 // if DDMS is listening, inform them of our plight 775 System.out.println("Sending WAIT chunk"); 776 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger" 777 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1); 778 DdmServer.sendChunk(waitChunk); 779 780 mWaiting = true; 781 while (!isDebuggerConnected()) { 782 try { Thread.sleep(SPIN_DELAY); } 783 catch (InterruptedException ie) {} 784 } 785 mWaiting = false; 786 787 System.out.println("Debugger has connected"); 788 789 /* 790 * There is no "ready to go" signal from the debugger, and we're 791 * not allowed to suspend ourselves -- the debugger expects us to 792 * be running happily, and gets confused if we aren't. We need to 793 * allow the debugger a chance to set breakpoints before we start 794 * running again. 795 * 796 * Sit and spin until the debugger has been idle for a short while. 797 */ 798 while (true) { 799 long delta = VMDebug.lastDebuggerActivity(); 800 if (delta < 0) { 801 System.out.println("debugger detached?"); 802 break; 803 } 804 805 if (delta < MIN_DEBUGGER_IDLE) { 806 System.out.println("waiting for debugger to settle..."); 807 try { Thread.sleep(SPIN_DELAY); } 808 catch (InterruptedException ie) {} 809 } else { 810 System.out.println("debugger has settled (" + delta + ")"); 811 break; 812 } 813 } 814 } 815 816 /** 817 * Returns "true" if one or more threads is waiting for a debugger 818 * to attach. 819 */ waitingForDebugger()820 public static boolean waitingForDebugger() { 821 return mWaiting; 822 } 823 824 /** 825 * Determine if a debugger is currently attached. 826 */ isDebuggerConnected()827 public static boolean isDebuggerConnected() { 828 return VMDebug.isDebuggerConnected(); 829 } 830 831 /** 832 * Returns an array of strings that identify VM features. This is 833 * used by DDMS to determine what sorts of operations the VM can 834 * perform. 835 * 836 * @hide 837 */ getVmFeatureList()838 public static String[] getVmFeatureList() { 839 return VMDebug.getVmFeatureList(); 840 } 841 842 /** 843 * Change the JDWP port. 844 * 845 * @deprecated no longer needed or useful 846 */ 847 @Deprecated changeDebugPort(int port)848 public static void changeDebugPort(int port) {} 849 850 /** 851 * This is the pathname to the sysfs file that enables and disables 852 * tracing on the qemu emulator. 853 */ 854 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state"; 855 856 /** 857 * Enable qemu tracing. For this to work requires running everything inside 858 * the qemu emulator; otherwise, this method will have no effect. The trace 859 * file is specified on the command line when the emulator is started. For 860 * example, the following command line <br /> 861 * <code>emulator -trace foo</code><br /> 862 * will start running the emulator and create a trace file named "foo". This 863 * method simply enables writing the trace records to the trace file. 864 * 865 * <p> 866 * The main differences between this and {@link #startMethodTracing()} are 867 * that tracing in the qemu emulator traces every cpu instruction of every 868 * process, including kernel code, so we have more complete information, 869 * including all context switches. We can also get more detailed information 870 * such as cache misses. The sequence of calls is determined by 871 * post-processing the instruction trace. The qemu tracing is also done 872 * without modifying the application or perturbing the timing of calls 873 * because no instrumentation is added to the application being traced. 874 * </p> 875 * 876 * <p> 877 * One limitation of using this method compared to using 878 * {@link #startMethodTracing()} on the real device is that the emulator 879 * does not model all of the real hardware effects such as memory and 880 * bus contention. The emulator also has a simple cache model and cannot 881 * capture all the complexities of a real cache. 882 * </p> 883 */ startNativeTracing()884 public static void startNativeTracing() { 885 // Open the sysfs file for writing and write "1" to it. 886 PrintWriter outStream = null; 887 try { 888 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE); 889 outStream = new FastPrintWriter(fos); 890 outStream.println("1"); 891 } catch (Exception e) { 892 } finally { 893 if (outStream != null) 894 outStream.close(); 895 } 896 897 VMDebug.startEmulatorTracing(); 898 } 899 900 /** 901 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing. 902 * 903 * <p>Tracing can be started and stopped as many times as desired. When 904 * the qemu emulator itself is stopped then the buffered trace records 905 * are flushed and written to the trace file. In fact, it is not necessary 906 * to call this method at all; simply killing qemu is sufficient. But 907 * starting and stopping a trace is useful for examining a specific 908 * region of code.</p> 909 */ stopNativeTracing()910 public static void stopNativeTracing() { 911 VMDebug.stopEmulatorTracing(); 912 913 // Open the sysfs file for writing and write "0" to it. 914 PrintWriter outStream = null; 915 try { 916 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE); 917 outStream = new FastPrintWriter(fos); 918 outStream.println("0"); 919 } catch (Exception e) { 920 // We could print an error message here but we probably want 921 // to quietly ignore errors if we are not running in the emulator. 922 } finally { 923 if (outStream != null) 924 outStream.close(); 925 } 926 } 927 928 /** 929 * Enable "emulator traces", in which information about the current 930 * method is made available to the "emulator -trace" feature. There 931 * is no corresponding "disable" call -- this is intended for use by 932 * the framework when tracing should be turned on and left that way, so 933 * that traces captured with F9/F10 will include the necessary data. 934 * 935 * This puts the VM into "profile" mode, which has performance 936 * consequences. 937 * 938 * To temporarily enable tracing, use {@link #startNativeTracing()}. 939 */ enableEmulatorTraceOutput()940 public static void enableEmulatorTraceOutput() { 941 VMDebug.startEmulatorTracing(); 942 } 943 944 /** 945 * Start method tracing with default log name and buffer size. 946 * <p> 947 * By default, the trace file is called "dmtrace.trace" and it's placed 948 * under your package-specific directory on primary shared/external storage, 949 * as returned by {@link Context#getExternalFilesDir(String)}. 950 * <p> 951 * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview: 952 * A Graphical Log Viewer</a> for information about reading trace files. 953 * <p class="note"> 954 * When method tracing is enabled, the VM will run more slowly than usual, 955 * so the timings from the trace files should only be considered in relative 956 * terms (e.g. was run #1 faster than run #2). The times for native methods 957 * will not change, so don't try to use this to compare the performance of 958 * interpreted and native implementations of the same method. As an 959 * alternative, consider using sampling-based method tracing via 960 * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing 961 * in the emulator via {@link #startNativeTracing()}. 962 * </p> 963 */ startMethodTracing()964 public static void startMethodTracing() { 965 VMDebug.startMethodTracing(fixTracePath(null), 0, 0, false, 0); 966 } 967 968 /** 969 * Start method tracing, specifying the trace log file path. 970 * <p> 971 * When a relative file path is given, the trace file will be placed under 972 * your package-specific directory on primary shared/external storage, as 973 * returned by {@link Context#getExternalFilesDir(String)}. 974 * <p> 975 * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview: 976 * A Graphical Log Viewer</a> for information about reading trace files. 977 * <p class="note"> 978 * When method tracing is enabled, the VM will run more slowly than usual, 979 * so the timings from the trace files should only be considered in relative 980 * terms (e.g. was run #1 faster than run #2). The times for native methods 981 * will not change, so don't try to use this to compare the performance of 982 * interpreted and native implementations of the same method. As an 983 * alternative, consider using sampling-based method tracing via 984 * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing 985 * in the emulator via {@link #startNativeTracing()}. 986 * </p> 987 * 988 * @param tracePath Path to the trace log file to create. If {@code null}, 989 * this will default to "dmtrace.trace". If the file already 990 * exists, it will be truncated. If the path given does not end 991 * in ".trace", it will be appended for you. 992 */ startMethodTracing(String tracePath)993 public static void startMethodTracing(String tracePath) { 994 startMethodTracing(tracePath, 0, 0); 995 } 996 997 /** 998 * Start method tracing, specifying the trace log file name and the buffer 999 * size. 1000 * <p> 1001 * When a relative file path is given, the trace file will be placed under 1002 * your package-specific directory on primary shared/external storage, as 1003 * returned by {@link Context#getExternalFilesDir(String)}. 1004 * <p> 1005 * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview: 1006 * A Graphical Log Viewer</a> for information about reading trace files. 1007 * <p class="note"> 1008 * When method tracing is enabled, the VM will run more slowly than usual, 1009 * so the timings from the trace files should only be considered in relative 1010 * terms (e.g. was run #1 faster than run #2). The times for native methods 1011 * will not change, so don't try to use this to compare the performance of 1012 * interpreted and native implementations of the same method. As an 1013 * alternative, consider using sampling-based method tracing via 1014 * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing 1015 * in the emulator via {@link #startNativeTracing()}. 1016 * </p> 1017 * 1018 * @param tracePath Path to the trace log file to create. If {@code null}, 1019 * this will default to "dmtrace.trace". If the file already 1020 * exists, it will be truncated. If the path given does not end 1021 * in ".trace", it will be appended for you. 1022 * @param bufferSize The maximum amount of trace data we gather. If not 1023 * given, it defaults to 8MB. 1024 */ startMethodTracing(String tracePath, int bufferSize)1025 public static void startMethodTracing(String tracePath, int bufferSize) { 1026 startMethodTracing(tracePath, bufferSize, 0); 1027 } 1028 1029 /** 1030 * Start method tracing, specifying the trace log file name, the buffer 1031 * size, and flags. 1032 * <p> 1033 * When a relative file path is given, the trace file will be placed under 1034 * your package-specific directory on primary shared/external storage, as 1035 * returned by {@link Context#getExternalFilesDir(String)}. 1036 * <p> 1037 * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview: 1038 * A Graphical Log Viewer</a> for information about reading trace files. 1039 * <p class="note"> 1040 * When method tracing is enabled, the VM will run more slowly than usual, 1041 * so the timings from the trace files should only be considered in relative 1042 * terms (e.g. was run #1 faster than run #2). The times for native methods 1043 * will not change, so don't try to use this to compare the performance of 1044 * interpreted and native implementations of the same method. As an 1045 * alternative, consider using sampling-based method tracing via 1046 * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing 1047 * in the emulator via {@link #startNativeTracing()}. 1048 * </p> 1049 * 1050 * @param tracePath Path to the trace log file to create. If {@code null}, 1051 * this will default to "dmtrace.trace". If the file already 1052 * exists, it will be truncated. If the path given does not end 1053 * in ".trace", it will be appended for you. 1054 * @param bufferSize The maximum amount of trace data we gather. If not 1055 * given, it defaults to 8MB. 1056 * @param flags Flags to control method tracing. The only one that is 1057 * currently defined is {@link #TRACE_COUNT_ALLOCS}. 1058 */ startMethodTracing(String tracePath, int bufferSize, int flags)1059 public static void startMethodTracing(String tracePath, int bufferSize, int flags) { 1060 VMDebug.startMethodTracing(fixTracePath(tracePath), bufferSize, flags, false, 0); 1061 } 1062 1063 /** 1064 * Start sampling-based method tracing, specifying the trace log file name, 1065 * the buffer size, and the sampling interval. 1066 * <p> 1067 * When a relative file path is given, the trace file will be placed under 1068 * your package-specific directory on primary shared/external storage, as 1069 * returned by {@link Context#getExternalFilesDir(String)}. 1070 * <p> 1071 * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview: 1072 * A Graphical Log Viewer</a> for information about reading trace files. 1073 * 1074 * @param tracePath Path to the trace log file to create. If {@code null}, 1075 * this will default to "dmtrace.trace". If the file already 1076 * exists, it will be truncated. If the path given does not end 1077 * in ".trace", it will be appended for you. 1078 * @param bufferSize The maximum amount of trace data we gather. If not 1079 * given, it defaults to 8MB. 1080 * @param intervalUs The amount of time between each sample in microseconds. 1081 */ startMethodTracingSampling(String tracePath, int bufferSize, int intervalUs)1082 public static void startMethodTracingSampling(String tracePath, int bufferSize, 1083 int intervalUs) { 1084 VMDebug.startMethodTracing(fixTracePath(tracePath), bufferSize, 0, true, intervalUs); 1085 } 1086 1087 /** 1088 * Formats name of trace log file for method tracing. 1089 */ fixTracePath(String tracePath)1090 private static String fixTracePath(String tracePath) { 1091 if (tracePath == null || tracePath.charAt(0) != '/') { 1092 final Context context = AppGlobals.getInitialApplication(); 1093 final File dir; 1094 if (context != null) { 1095 dir = context.getExternalFilesDir(null); 1096 } else { 1097 dir = Environment.getExternalStorageDirectory(); 1098 } 1099 1100 if (tracePath == null) { 1101 tracePath = new File(dir, DEFAULT_TRACE_BODY).getAbsolutePath(); 1102 } else { 1103 tracePath = new File(dir, tracePath).getAbsolutePath(); 1104 } 1105 } 1106 if (!tracePath.endsWith(DEFAULT_TRACE_EXTENSION)) { 1107 tracePath += DEFAULT_TRACE_EXTENSION; 1108 } 1109 return tracePath; 1110 } 1111 1112 /** 1113 * Like startMethodTracing(String, int, int), but taking an already-opened 1114 * FileDescriptor in which the trace is written. The file name is also 1115 * supplied simply for logging. Makes a dup of the file descriptor. 1116 * 1117 * Not exposed in the SDK unless we are really comfortable with supporting 1118 * this and find it would be useful. 1119 * @hide 1120 */ startMethodTracing(String traceName, FileDescriptor fd, int bufferSize, int flags)1121 public static void startMethodTracing(String traceName, FileDescriptor fd, 1122 int bufferSize, int flags) { 1123 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0); 1124 } 1125 1126 /** 1127 * Starts method tracing without a backing file. When stopMethodTracing 1128 * is called, the result is sent directly to DDMS. (If DDMS is not 1129 * attached when tracing ends, the profiling data will be discarded.) 1130 * 1131 * @hide 1132 */ startMethodTracingDdms(int bufferSize, int flags, boolean samplingEnabled, int intervalUs)1133 public static void startMethodTracingDdms(int bufferSize, int flags, 1134 boolean samplingEnabled, int intervalUs) { 1135 VMDebug.startMethodTracingDdms(bufferSize, flags, samplingEnabled, intervalUs); 1136 } 1137 1138 /** 1139 * Determine whether method tracing is currently active and what type is 1140 * active. 1141 * 1142 * @hide 1143 */ getMethodTracingMode()1144 public static int getMethodTracingMode() { 1145 return VMDebug.getMethodTracingMode(); 1146 } 1147 1148 /** 1149 * Stop method tracing. 1150 */ stopMethodTracing()1151 public static void stopMethodTracing() { 1152 VMDebug.stopMethodTracing(); 1153 } 1154 1155 /** 1156 * Get an indication of thread CPU usage. The value returned 1157 * indicates the amount of time that the current thread has spent 1158 * executing code or waiting for certain types of I/O. 1159 * 1160 * The time is expressed in nanoseconds, and is only meaningful 1161 * when compared to the result from an earlier call. Note that 1162 * nanosecond resolution does not imply nanosecond accuracy. 1163 * 1164 * On system which don't support this operation, the call returns -1. 1165 */ threadCpuTimeNanos()1166 public static long threadCpuTimeNanos() { 1167 return VMDebug.threadCpuTimeNanos(); 1168 } 1169 1170 /** 1171 * Start counting the number and aggregate size of memory allocations. 1172 * 1173 * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting. 1174 * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis 1175 * code doesn't cause additional allocations. The various <code>get</code> methods return 1176 * the specified value. And the various <code>reset</code> methods reset the specified 1177 * count.</p> 1178 * 1179 * <p>Counts are kept for the system as a whole (global) and for each thread. 1180 * The per-thread counts for threads other than the current thread 1181 * are not cleared by the "reset" or "start" calls.</p> 1182 * 1183 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1184 */ 1185 @Deprecated startAllocCounting()1186 public static void startAllocCounting() { 1187 VMDebug.startAllocCounting(); 1188 } 1189 1190 /** 1191 * Stop counting the number and aggregate size of memory allocations. 1192 * 1193 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1194 */ 1195 @Deprecated stopAllocCounting()1196 public static void stopAllocCounting() { 1197 VMDebug.stopAllocCounting(); 1198 } 1199 1200 /** 1201 * Returns the global count of objects allocated by the runtime between a 1202 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1203 * 1204 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1205 */ 1206 @Deprecated getGlobalAllocCount()1207 public static int getGlobalAllocCount() { 1208 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS); 1209 } 1210 1211 /** 1212 * Clears the global count of objects allocated. 1213 * @see #getGlobalAllocCount() 1214 * 1215 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1216 */ 1217 @Deprecated resetGlobalAllocCount()1218 public static void resetGlobalAllocCount() { 1219 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS); 1220 } 1221 1222 /** 1223 * Returns the global size, in bytes, of objects allocated by the runtime between a 1224 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1225 * 1226 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1227 */ 1228 @Deprecated getGlobalAllocSize()1229 public static int getGlobalAllocSize() { 1230 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES); 1231 } 1232 1233 /** 1234 * Clears the global size of objects allocated. 1235 * @see #getGlobalAllocSize() 1236 * 1237 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1238 */ 1239 @Deprecated resetGlobalAllocSize()1240 public static void resetGlobalAllocSize() { 1241 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES); 1242 } 1243 1244 /** 1245 * Returns the global count of objects freed by the runtime between a 1246 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1247 * 1248 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1249 */ 1250 @Deprecated getGlobalFreedCount()1251 public static int getGlobalFreedCount() { 1252 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS); 1253 } 1254 1255 /** 1256 * Clears the global count of objects freed. 1257 * @see #getGlobalFreedCount() 1258 * 1259 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1260 */ 1261 @Deprecated resetGlobalFreedCount()1262 public static void resetGlobalFreedCount() { 1263 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS); 1264 } 1265 1266 /** 1267 * Returns the global size, in bytes, of objects freed by the runtime between a 1268 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1269 * 1270 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1271 */ 1272 @Deprecated getGlobalFreedSize()1273 public static int getGlobalFreedSize() { 1274 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES); 1275 } 1276 1277 /** 1278 * Clears the global size of objects freed. 1279 * @see #getGlobalFreedSize() 1280 * 1281 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1282 */ 1283 @Deprecated resetGlobalFreedSize()1284 public static void resetGlobalFreedSize() { 1285 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES); 1286 } 1287 1288 /** 1289 * Returns the number of non-concurrent GC invocations between a 1290 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1291 * 1292 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1293 */ 1294 @Deprecated getGlobalGcInvocationCount()1295 public static int getGlobalGcInvocationCount() { 1296 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS); 1297 } 1298 1299 /** 1300 * Clears the count of non-concurrent GC invocations. 1301 * @see #getGlobalGcInvocationCount() 1302 * 1303 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1304 */ 1305 @Deprecated resetGlobalGcInvocationCount()1306 public static void resetGlobalGcInvocationCount() { 1307 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS); 1308 } 1309 1310 /** 1311 * Returns the number of classes successfully initialized (ie those that executed without 1312 * throwing an exception) between a {@link #startAllocCounting() start} and 1313 * {@link #stopAllocCounting() stop}. 1314 * 1315 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1316 */ 1317 @Deprecated getGlobalClassInitCount()1318 public static int getGlobalClassInitCount() { 1319 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT); 1320 } 1321 1322 /** 1323 * Clears the count of classes initialized. 1324 * @see #getGlobalClassInitCount() 1325 * 1326 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1327 */ 1328 @Deprecated resetGlobalClassInitCount()1329 public static void resetGlobalClassInitCount() { 1330 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT); 1331 } 1332 1333 /** 1334 * Returns the time spent successfully initializing classes between a 1335 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1336 * 1337 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1338 */ 1339 @Deprecated getGlobalClassInitTime()1340 public static int getGlobalClassInitTime() { 1341 /* cumulative elapsed time for class initialization, in usec */ 1342 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME); 1343 } 1344 1345 /** 1346 * Clears the count of time spent initializing classes. 1347 * @see #getGlobalClassInitTime() 1348 * 1349 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1350 */ 1351 @Deprecated resetGlobalClassInitTime()1352 public static void resetGlobalClassInitTime() { 1353 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME); 1354 } 1355 1356 /** 1357 * This method exists for compatibility and always returns 0. 1358 * @deprecated This method is now obsolete. 1359 */ 1360 @Deprecated getGlobalExternalAllocCount()1361 public static int getGlobalExternalAllocCount() { 1362 return 0; 1363 } 1364 1365 /** 1366 * This method exists for compatibility and has no effect. 1367 * @deprecated This method is now obsolete. 1368 */ 1369 @Deprecated resetGlobalExternalAllocSize()1370 public static void resetGlobalExternalAllocSize() {} 1371 1372 /** 1373 * This method exists for compatibility and has no effect. 1374 * @deprecated This method is now obsolete. 1375 */ 1376 @Deprecated resetGlobalExternalAllocCount()1377 public static void resetGlobalExternalAllocCount() {} 1378 1379 /** 1380 * This method exists for compatibility and always returns 0. 1381 * @deprecated This method is now obsolete. 1382 */ 1383 @Deprecated getGlobalExternalAllocSize()1384 public static int getGlobalExternalAllocSize() { 1385 return 0; 1386 } 1387 1388 /** 1389 * This method exists for compatibility and always returns 0. 1390 * @deprecated This method is now obsolete. 1391 */ 1392 @Deprecated getGlobalExternalFreedCount()1393 public static int getGlobalExternalFreedCount() { 1394 return 0; 1395 } 1396 1397 /** 1398 * This method exists for compatibility and has no effect. 1399 * @deprecated This method is now obsolete. 1400 */ 1401 @Deprecated resetGlobalExternalFreedCount()1402 public static void resetGlobalExternalFreedCount() {} 1403 1404 /** 1405 * This method exists for compatibility and has no effect. 1406 * @deprecated This method is now obsolete. 1407 */ 1408 @Deprecated getGlobalExternalFreedSize()1409 public static int getGlobalExternalFreedSize() { 1410 return 0; 1411 } 1412 1413 /** 1414 * This method exists for compatibility and has no effect. 1415 * @deprecated This method is now obsolete. 1416 */ 1417 @Deprecated resetGlobalExternalFreedSize()1418 public static void resetGlobalExternalFreedSize() {} 1419 1420 /** 1421 * Returns the thread-local count of objects allocated by the runtime between a 1422 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1423 * 1424 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1425 */ 1426 @Deprecated getThreadAllocCount()1427 public static int getThreadAllocCount() { 1428 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS); 1429 } 1430 1431 /** 1432 * Clears the thread-local count of objects allocated. 1433 * @see #getThreadAllocCount() 1434 * 1435 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1436 */ 1437 @Deprecated resetThreadAllocCount()1438 public static void resetThreadAllocCount() { 1439 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS); 1440 } 1441 1442 /** 1443 * Returns the thread-local size of objects allocated by the runtime between a 1444 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1445 * @return The allocated size in bytes. 1446 * 1447 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1448 */ 1449 @Deprecated getThreadAllocSize()1450 public static int getThreadAllocSize() { 1451 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES); 1452 } 1453 1454 /** 1455 * Clears the thread-local count of objects allocated. 1456 * @see #getThreadAllocSize() 1457 * 1458 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1459 */ 1460 @Deprecated resetThreadAllocSize()1461 public static void resetThreadAllocSize() { 1462 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES); 1463 } 1464 1465 /** 1466 * This method exists for compatibility and has no effect. 1467 * @deprecated This method is now obsolete. 1468 */ 1469 @Deprecated getThreadExternalAllocCount()1470 public static int getThreadExternalAllocCount() { 1471 return 0; 1472 } 1473 1474 /** 1475 * This method exists for compatibility and has no effect. 1476 * @deprecated This method is now obsolete. 1477 */ 1478 @Deprecated resetThreadExternalAllocCount()1479 public static void resetThreadExternalAllocCount() {} 1480 1481 /** 1482 * This method exists for compatibility and has no effect. 1483 * @deprecated This method is now obsolete. 1484 */ 1485 @Deprecated getThreadExternalAllocSize()1486 public static int getThreadExternalAllocSize() { 1487 return 0; 1488 } 1489 1490 /** 1491 * This method exists for compatibility and has no effect. 1492 * @deprecated This method is now obsolete. 1493 */ 1494 @Deprecated resetThreadExternalAllocSize()1495 public static void resetThreadExternalAllocSize() {} 1496 1497 /** 1498 * Returns the number of thread-local non-concurrent GC invocations between a 1499 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}. 1500 * 1501 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1502 */ 1503 @Deprecated getThreadGcInvocationCount()1504 public static int getThreadGcInvocationCount() { 1505 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS); 1506 } 1507 1508 /** 1509 * Clears the thread-local count of non-concurrent GC invocations. 1510 * @see #getThreadGcInvocationCount() 1511 * 1512 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1513 */ 1514 @Deprecated resetThreadGcInvocationCount()1515 public static void resetThreadGcInvocationCount() { 1516 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS); 1517 } 1518 1519 /** 1520 * Clears all the global and thread-local memory allocation counters. 1521 * @see #startAllocCounting() 1522 * 1523 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1524 */ 1525 @Deprecated resetAllCounts()1526 public static void resetAllCounts() { 1527 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS); 1528 } 1529 1530 /** 1531 * Returns the value of a particular runtime statistic or {@code null} if no 1532 * such runtime statistic exists. 1533 * 1534 * <p>The following table lists the runtime statistics that the runtime supports. 1535 * Note runtime statistics may be added or removed in a future API level.</p> 1536 * 1537 * <table> 1538 * <thead> 1539 * <tr> 1540 * <th>Runtime statistic name</th> 1541 * <th>Meaning</th> 1542 * <th>Example</th> 1543 * <th>Supported (API Levels)</th> 1544 * </tr> 1545 * </thead> 1546 * <tbody> 1547 * <tr> 1548 * <td>art.gc.gc-count</td> 1549 * <td>The number of garbage collection runs.</td> 1550 * <td>{@code 164}</td> 1551 * <td>23</td> 1552 * </tr> 1553 * <tr> 1554 * <td>art.gc.gc-time</td> 1555 * <td>The total duration of garbage collection runs in ms.</td> 1556 * <td>{@code 62364}</td> 1557 * <td>23</td> 1558 * </tr> 1559 * <tr> 1560 * <td>art.gc.bytes-allocated</td> 1561 * <td>The total number of bytes that the application allocated.</td> 1562 * <td>{@code 1463948408}</td> 1563 * <td>23</td> 1564 * </tr> 1565 * <tr> 1566 * <td>art.gc.bytes-freed</td> 1567 * <td>The total number of bytes that garbage collection reclaimed.</td> 1568 * <td>{@code 1313493084}</td> 1569 * <td>23</td> 1570 * </tr> 1571 * <tr> 1572 * <td>art.gc.blocking-gc-count</td> 1573 * <td>The number of blocking garbage collection runs.</td> 1574 * <td>{@code 2}</td> 1575 * <td>23</td> 1576 * </tr> 1577 * <tr> 1578 * <td>art.gc.blocking-gc-time</td> 1579 * <td>The total duration of blocking garbage collection runs in ms.</td> 1580 * <td>{@code 804}</td> 1581 * <td>23</td> 1582 * </tr> 1583 * <tr> 1584 * <td>art.gc.gc-count-rate-histogram</td> 1585 * <td>Every 10 seconds, the gc-count-rate is computed as the number of garbage 1586 * collection runs that have occurred over the last 10 1587 * seconds. art.gc.gc-count-rate-histogram is a histogram of the gc-count-rate 1588 * samples taken since the process began. The histogram can be used to identify 1589 * instances of high rates of garbage collection runs. For example, a histogram 1590 * of "0:34503,1:45350,2:11281,3:8088,4:43,5:8" shows that most of the time 1591 * there are between 0 and 2 garbage collection runs every 10 seconds, but there 1592 * were 8 distinct 10-second intervals in which 5 garbage collection runs 1593 * occurred.</td> 1594 * <td>{@code 0:34503,1:45350,2:11281,3:8088,4:43,5:8}</td> 1595 * <td>23</td> 1596 * </tr> 1597 * <tr> 1598 * <td>art.gc.blocking-gc-count-rate-histogram</td> 1599 * <td>Every 10 seconds, the blocking-gc-count-rate is computed as the number of 1600 * blocking garbage collection runs that have occurred over the last 10 1601 * seconds. art.gc.blocking-gc-count-rate-histogram is a histogram of the 1602 * blocking-gc-count-rate samples taken since the process began. The histogram 1603 * can be used to identify instances of high rates of blocking garbage 1604 * collection runs. For example, a histogram of "0:99269,1:1,2:1" shows that 1605 * most of the time there are zero blocking garbage collection runs every 10 1606 * seconds, but there was one 10-second interval in which one blocking garbage 1607 * collection run occurred, and there was one interval in which two blocking 1608 * garbage collection runs occurred.</td> 1609 * <td>{@code 0:99269,1:1,2:1}</td> 1610 * <td>23</td> 1611 * </tr> 1612 * </tbody> 1613 * </table> 1614 * 1615 * @param statName 1616 * the name of the runtime statistic to look up. 1617 * @return the value of the specified runtime statistic or {@code null} if the 1618 * runtime statistic doesn't exist. 1619 */ getRuntimeStat(String statName)1620 public static String getRuntimeStat(String statName) { 1621 return VMDebug.getRuntimeStat(statName); 1622 } 1623 1624 /** 1625 * Returns a map of the names/values of the runtime statistics 1626 * that {@link #getRuntimeStat(String)} supports. 1627 * 1628 * @return a map of the names/values of the supported runtime statistics. 1629 */ getRuntimeStats()1630 public static Map<String, String> getRuntimeStats() { 1631 return VMDebug.getRuntimeStats(); 1632 } 1633 1634 /** 1635 * Returns the size of the native heap. 1636 * @return The size of the native heap in bytes. 1637 */ getNativeHeapSize()1638 public static native long getNativeHeapSize(); 1639 1640 /** 1641 * Returns the amount of allocated memory in the native heap. 1642 * @return The allocated size in bytes. 1643 */ getNativeHeapAllocatedSize()1644 public static native long getNativeHeapAllocatedSize(); 1645 1646 /** 1647 * Returns the amount of free memory in the native heap. 1648 * @return The freed size in bytes. 1649 */ getNativeHeapFreeSize()1650 public static native long getNativeHeapFreeSize(); 1651 1652 /** 1653 * Retrieves information about this processes memory usages. This information is broken down by 1654 * how much is in use by dalvik, the native heap, and everything else. 1655 * 1656 * <p><b>Note:</b> this method directly retrieves memory information for the give process 1657 * from low-level data available to it. It may not be able to retrieve information about 1658 * some protected allocations, such as graphics. If you want to be sure you can see 1659 * all information about allocations by the process, use instead 1660 * {@link android.app.ActivityManager#getProcessMemoryInfo(int[])}.</p> 1661 */ getMemoryInfo(MemoryInfo memoryInfo)1662 public static native void getMemoryInfo(MemoryInfo memoryInfo); 1663 1664 /** 1665 * Note: currently only works when the requested pid has the same UID 1666 * as the caller. 1667 * @hide 1668 */ getMemoryInfo(int pid, MemoryInfo memoryInfo)1669 public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo); 1670 1671 /** 1672 * Retrieves the PSS memory used by the process as given by the 1673 * smaps. 1674 */ getPss()1675 public static native long getPss(); 1676 1677 /** 1678 * Retrieves the PSS memory used by the process as given by the 1679 * smaps. Optionally supply a long array of 2 entries to also 1680 * receive the Uss and SwapPss of the process, and another array to also 1681 * retrieve the separate memtrack size. 1682 * @hide 1683 */ getPss(int pid, long[] outUssSwapPss, long[] outMemtrack)1684 public static native long getPss(int pid, long[] outUssSwapPss, long[] outMemtrack); 1685 1686 /** @hide */ 1687 public static final int MEMINFO_TOTAL = 0; 1688 /** @hide */ 1689 public static final int MEMINFO_FREE = 1; 1690 /** @hide */ 1691 public static final int MEMINFO_BUFFERS = 2; 1692 /** @hide */ 1693 public static final int MEMINFO_CACHED = 3; 1694 /** @hide */ 1695 public static final int MEMINFO_SHMEM = 4; 1696 /** @hide */ 1697 public static final int MEMINFO_SLAB = 5; 1698 /** @hide */ 1699 public static final int MEMINFO_SWAP_TOTAL = 6; 1700 /** @hide */ 1701 public static final int MEMINFO_SWAP_FREE = 7; 1702 /** @hide */ 1703 public static final int MEMINFO_ZRAM_TOTAL = 8; 1704 /** @hide */ 1705 public static final int MEMINFO_MAPPED = 9; 1706 /** @hide */ 1707 public static final int MEMINFO_VM_ALLOC_USED = 10; 1708 /** @hide */ 1709 public static final int MEMINFO_PAGE_TABLES = 11; 1710 /** @hide */ 1711 public static final int MEMINFO_KERNEL_STACK = 12; 1712 /** @hide */ 1713 public static final int MEMINFO_COUNT = 13; 1714 1715 /** 1716 * Retrieves /proc/meminfo. outSizes is filled with fields 1717 * as defined by MEMINFO_* offsets. 1718 * @hide 1719 */ getMemInfo(long[] outSizes)1720 public static native void getMemInfo(long[] outSizes); 1721 1722 /** 1723 * Establish an object allocation limit in the current thread. 1724 * This feature was never enabled in release builds. The 1725 * allocation limits feature was removed in Honeycomb. This 1726 * method exists for compatibility and always returns -1 and has 1727 * no effect. 1728 * 1729 * @deprecated This method is now obsolete. 1730 */ 1731 @Deprecated setAllocationLimit(int limit)1732 public static int setAllocationLimit(int limit) { 1733 return -1; 1734 } 1735 1736 /** 1737 * Establish a global object allocation limit. This feature was 1738 * never enabled in release builds. The allocation limits feature 1739 * was removed in Honeycomb. This method exists for compatibility 1740 * and always returns -1 and has no effect. 1741 * 1742 * @deprecated This method is now obsolete. 1743 */ 1744 @Deprecated setGlobalAllocationLimit(int limit)1745 public static int setGlobalAllocationLimit(int limit) { 1746 return -1; 1747 } 1748 1749 /** 1750 * Dump a list of all currently loaded class to the log file. 1751 * 1752 * @param flags See constants above. 1753 */ printLoadedClasses(int flags)1754 public static void printLoadedClasses(int flags) { 1755 VMDebug.printLoadedClasses(flags); 1756 } 1757 1758 /** 1759 * Get the number of loaded classes. 1760 * @return the number of loaded classes. 1761 */ getLoadedClassCount()1762 public static int getLoadedClassCount() { 1763 return VMDebug.getLoadedClassCount(); 1764 } 1765 1766 /** 1767 * Dump "hprof" data to the specified file. This may cause a GC. 1768 * 1769 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof"). 1770 * @throws UnsupportedOperationException if the VM was built without 1771 * HPROF support. 1772 * @throws IOException if an error occurs while opening or writing files. 1773 */ dumpHprofData(String fileName)1774 public static void dumpHprofData(String fileName) throws IOException { 1775 VMDebug.dumpHprofData(fileName); 1776 } 1777 1778 /** 1779 * Like dumpHprofData(String), but takes an already-opened 1780 * FileDescriptor to which the trace is written. The file name is also 1781 * supplied simply for logging. Makes a dup of the file descriptor. 1782 * 1783 * Primarily for use by the "am" shell command. 1784 * 1785 * @hide 1786 */ dumpHprofData(String fileName, FileDescriptor fd)1787 public static void dumpHprofData(String fileName, FileDescriptor fd) 1788 throws IOException { 1789 VMDebug.dumpHprofData(fileName, fd); 1790 } 1791 1792 /** 1793 * Collect "hprof" and send it to DDMS. This may cause a GC. 1794 * 1795 * @throws UnsupportedOperationException if the VM was built without 1796 * HPROF support. 1797 * @hide 1798 */ dumpHprofDataDdms()1799 public static void dumpHprofDataDdms() { 1800 VMDebug.dumpHprofDataDdms(); 1801 } 1802 1803 /** 1804 * Writes native heap data to the specified file descriptor. 1805 * 1806 * @hide 1807 */ dumpNativeHeap(FileDescriptor fd)1808 public static native void dumpNativeHeap(FileDescriptor fd); 1809 1810 /** 1811 * Returns a count of the extant instances of a class. 1812 * 1813 * @hide 1814 */ countInstancesOfClass(Class cls)1815 public static long countInstancesOfClass(Class cls) { 1816 return VMDebug.countInstancesOfClass(cls, true); 1817 } 1818 1819 /** 1820 * Returns the number of sent transactions from this process. 1821 * @return The number of sent transactions or -1 if it could not read t. 1822 */ getBinderSentTransactions()1823 public static native int getBinderSentTransactions(); 1824 1825 /** 1826 * Returns the number of received transactions from the binder driver. 1827 * @return The number of received transactions or -1 if it could not read the stats. 1828 */ getBinderReceivedTransactions()1829 public static native int getBinderReceivedTransactions(); 1830 1831 /** 1832 * Returns the number of active local Binder objects that exist in the 1833 * current process. 1834 */ getBinderLocalObjectCount()1835 public static final native int getBinderLocalObjectCount(); 1836 1837 /** 1838 * Returns the number of references to remote proxy Binder objects that 1839 * exist in the current process. 1840 */ getBinderProxyObjectCount()1841 public static final native int getBinderProxyObjectCount(); 1842 1843 /** 1844 * Returns the number of death notification links to Binder objects that 1845 * exist in the current process. 1846 */ getBinderDeathObjectCount()1847 public static final native int getBinderDeathObjectCount(); 1848 1849 /** 1850 * Primes the register map cache. 1851 * 1852 * Only works for classes in the bootstrap class loader. Does not 1853 * cause classes to be loaded if they're not already present. 1854 * 1855 * The classAndMethodDesc argument is a concatentation of the VM-internal 1856 * class descriptor, method name, and method descriptor. Examples: 1857 * Landroid/os/Looper;.loop:()V 1858 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V 1859 * 1860 * @param classAndMethodDesc the method to prepare 1861 * 1862 * @hide 1863 */ cacheRegisterMap(String classAndMethodDesc)1864 public static final boolean cacheRegisterMap(String classAndMethodDesc) { 1865 return VMDebug.cacheRegisterMap(classAndMethodDesc); 1866 } 1867 1868 /** 1869 * Dumps the contents of VM reference tables (e.g. JNI locals and 1870 * globals) to the log file. 1871 * 1872 * @hide 1873 */ dumpReferenceTables()1874 public static final void dumpReferenceTables() { 1875 VMDebug.dumpReferenceTables(); 1876 } 1877 1878 /** 1879 * API for gathering and querying instruction counts. 1880 * 1881 * Example usage: 1882 * <pre> 1883 * Debug.InstructionCount icount = new Debug.InstructionCount(); 1884 * icount.resetAndStart(); 1885 * [... do lots of stuff ...] 1886 * if (icount.collect()) { 1887 * System.out.println("Total instructions executed: " 1888 * + icount.globalTotal()); 1889 * System.out.println("Method invocations: " 1890 * + icount.globalMethodInvocations()); 1891 * } 1892 * </pre> 1893 * 1894 * @deprecated Instruction counting is no longer supported. 1895 */ 1896 @Deprecated 1897 public static class InstructionCount { 1898 private static final int NUM_INSTR = 1899 OpcodeInfo.MAXIMUM_PACKED_VALUE + 1; 1900 1901 private int[] mCounts; 1902 InstructionCount()1903 public InstructionCount() { 1904 mCounts = new int[NUM_INSTR]; 1905 } 1906 1907 /** 1908 * Reset counters and ensure counts are running. Counts may 1909 * have already been running. 1910 * 1911 * @return true if counting was started 1912 */ resetAndStart()1913 public boolean resetAndStart() { 1914 try { 1915 VMDebug.startInstructionCounting(); 1916 VMDebug.resetInstructionCount(); 1917 } catch (UnsupportedOperationException uoe) { 1918 return false; 1919 } 1920 return true; 1921 } 1922 1923 /** 1924 * Collect instruction counts. May or may not stop the 1925 * counting process. 1926 */ collect()1927 public boolean collect() { 1928 try { 1929 VMDebug.stopInstructionCounting(); 1930 VMDebug.getInstructionCount(mCounts); 1931 } catch (UnsupportedOperationException uoe) { 1932 return false; 1933 } 1934 return true; 1935 } 1936 1937 /** 1938 * Return the total number of instructions executed globally (i.e. in 1939 * all threads). 1940 */ globalTotal()1941 public int globalTotal() { 1942 int count = 0; 1943 1944 for (int i = 0; i < NUM_INSTR; i++) { 1945 count += mCounts[i]; 1946 } 1947 1948 return count; 1949 } 1950 1951 /** 1952 * Return the total number of method-invocation instructions 1953 * executed globally. 1954 */ globalMethodInvocations()1955 public int globalMethodInvocations() { 1956 int count = 0; 1957 1958 for (int i = 0; i < NUM_INSTR; i++) { 1959 if (OpcodeInfo.isInvoke(i)) { 1960 count += mCounts[i]; 1961 } 1962 } 1963 1964 return count; 1965 } 1966 } 1967 1968 /** 1969 * A Map of typed debug properties. 1970 */ 1971 private static final TypedProperties debugProperties; 1972 1973 /* 1974 * Load the debug properties from the standard files into debugProperties. 1975 */ 1976 static { 1977 if (false) { 1978 final String TAG = "DebugProperties"; 1979 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" }; 1980 final TypedProperties tp = new TypedProperties(); 1981 1982 // Read the properties from each of the files, if present. 1983 for (String file : files) { 1984 Reader r; 1985 try { 1986 r = new FileReader(file); 1987 } catch (FileNotFoundException ex) { 1988 // It's ok if a file is missing. 1989 continue; 1990 } 1991 1992 try { 1993 tp.load(r); 1994 } catch (Exception ex) { 1995 throw new RuntimeException("Problem loading " + file, ex); 1996 } finally { 1997 try { r.close()1998 r.close(); 1999 } catch (IOException ex) { 2000 // Ignore this error. 2001 } 2002 } 2003 } 2004 2005 debugProperties = tp.isEmpty() ? null : tp; 2006 } else { 2007 debugProperties = null; 2008 } 2009 } 2010 2011 2012 /** 2013 * Returns true if the type of the field matches the specified class. 2014 * Handles the case where the class is, e.g., java.lang.Boolean, but 2015 * the field is of the primitive "boolean" type. Also handles all of 2016 * the java.lang.Number subclasses. 2017 */ fieldTypeMatches(Field field, Class<?> cl)2018 private static boolean fieldTypeMatches(Field field, Class<?> cl) { 2019 Class<?> fieldClass = field.getType(); 2020 if (fieldClass == cl) { 2021 return true; 2022 } 2023 Field primitiveTypeField; 2024 try { 2025 /* All of the classes we care about (Boolean, Integer, etc.) 2026 * have a Class field called "TYPE" that points to the corresponding 2027 * primitive class. 2028 */ 2029 primitiveTypeField = cl.getField("TYPE"); 2030 } catch (NoSuchFieldException ex) { 2031 return false; 2032 } 2033 try { 2034 return fieldClass == (Class<?>) primitiveTypeField.get(null); 2035 } catch (IllegalAccessException ex) { 2036 return false; 2037 } 2038 } 2039 2040 2041 /** 2042 * Looks up the property that corresponds to the field, and sets the field's value 2043 * if the types match. 2044 */ modifyFieldIfSet(final Field field, final TypedProperties properties, final String propertyName)2045 private static void modifyFieldIfSet(final Field field, final TypedProperties properties, 2046 final String propertyName) { 2047 if (field.getType() == java.lang.String.class) { 2048 int stringInfo = properties.getStringInfo(propertyName); 2049 switch (stringInfo) { 2050 case TypedProperties.STRING_SET: 2051 // Handle as usual below. 2052 break; 2053 case TypedProperties.STRING_NULL: 2054 try { 2055 field.set(null, null); // null object for static fields; null string 2056 } catch (IllegalAccessException ex) { 2057 throw new IllegalArgumentException( 2058 "Cannot set field for " + propertyName, ex); 2059 } 2060 return; 2061 case TypedProperties.STRING_NOT_SET: 2062 return; 2063 case TypedProperties.STRING_TYPE_MISMATCH: 2064 throw new IllegalArgumentException( 2065 "Type of " + propertyName + " " + 2066 " does not match field type (" + field.getType() + ")"); 2067 default: 2068 throw new IllegalStateException( 2069 "Unexpected getStringInfo(" + propertyName + ") return value " + 2070 stringInfo); 2071 } 2072 } 2073 Object value = properties.get(propertyName); 2074 if (value != null) { 2075 if (!fieldTypeMatches(field, value.getClass())) { 2076 throw new IllegalArgumentException( 2077 "Type of " + propertyName + " (" + value.getClass() + ") " + 2078 " does not match field type (" + field.getType() + ")"); 2079 } 2080 try { 2081 field.set(null, value); // null object for static fields 2082 } catch (IllegalAccessException ex) { 2083 throw new IllegalArgumentException( 2084 "Cannot set field for " + propertyName, ex); 2085 } 2086 } 2087 } 2088 2089 2090 /** 2091 * Equivalent to <code>setFieldsOn(cl, false)</code>. 2092 * 2093 * @see #setFieldsOn(Class, boolean) 2094 * 2095 * @hide 2096 */ setFieldsOn(Class<?> cl)2097 public static void setFieldsOn(Class<?> cl) { 2098 setFieldsOn(cl, false); 2099 } 2100 2101 /** 2102 * Reflectively sets static fields of a class based on internal debugging 2103 * properties. This method is a no-op if false is 2104 * false. 2105 * <p> 2106 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will 2107 * always be false in release builds. This API is typically only useful 2108 * for platform developers. 2109 * </p> 2110 * Class setup: define a class whose only fields are non-final, static 2111 * primitive types (except for "char") or Strings. In a static block 2112 * after the field definitions/initializations, pass the class to 2113 * this method, Debug.setFieldsOn(). Example: 2114 * <pre> 2115 * package com.example; 2116 * 2117 * import android.os.Debug; 2118 * 2119 * public class MyDebugVars { 2120 * public static String s = "a string"; 2121 * public static String s2 = "second string"; 2122 * public static String ns = null; 2123 * public static boolean b = false; 2124 * public static int i = 5; 2125 * @Debug.DebugProperty 2126 * public static float f = 0.1f; 2127 * @@Debug.DebugProperty 2128 * public static double d = 0.5d; 2129 * 2130 * // This MUST appear AFTER all fields are defined and initialized! 2131 * static { 2132 * // Sets all the fields 2133 * Debug.setFieldsOn(MyDebugVars.class); 2134 * 2135 * // Sets only the fields annotated with @Debug.DebugProperty 2136 * // Debug.setFieldsOn(MyDebugVars.class, true); 2137 * } 2138 * } 2139 * </pre> 2140 * setFieldsOn() may override the value of any field in the class based 2141 * on internal properties that are fixed at boot time. 2142 * <p> 2143 * These properties are only set during platform debugging, and are not 2144 * meant to be used as a general-purpose properties store. 2145 * 2146 * {@hide} 2147 * 2148 * @param cl The class to (possibly) modify 2149 * @param partial If false, sets all static fields, otherwise, only set 2150 * fields with the {@link android.os.Debug.DebugProperty} 2151 * annotation 2152 * @throws IllegalArgumentException if any fields are final or non-static, 2153 * or if the type of the field does not match the type of 2154 * the internal debugging property value. 2155 */ setFieldsOn(Class<?> cl, boolean partial)2156 public static void setFieldsOn(Class<?> cl, boolean partial) { 2157 if (false) { 2158 if (debugProperties != null) { 2159 /* Only look for fields declared directly by the class, 2160 * so we don't mysteriously change static fields in superclasses. 2161 */ 2162 for (Field field : cl.getDeclaredFields()) { 2163 if (!partial || field.getAnnotation(DebugProperty.class) != null) { 2164 final String propertyName = cl.getName() + "." + field.getName(); 2165 boolean isStatic = Modifier.isStatic(field.getModifiers()); 2166 boolean isFinal = Modifier.isFinal(field.getModifiers()); 2167 2168 if (!isStatic || isFinal) { 2169 throw new IllegalArgumentException(propertyName + 2170 " must be static and non-final"); 2171 } 2172 modifyFieldIfSet(field, debugProperties, propertyName); 2173 } 2174 } 2175 } 2176 } else { 2177 Log.wtf(TAG, 2178 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) + 2179 ") called in non-DEBUG build"); 2180 } 2181 } 2182 2183 /** 2184 * Annotation to put on fields you want to set with 2185 * {@link Debug#setFieldsOn(Class, boolean)}. 2186 * 2187 * @hide 2188 */ 2189 @Target({ ElementType.FIELD }) 2190 @Retention(RetentionPolicy.RUNTIME) 2191 public @interface DebugProperty { 2192 } 2193 2194 /** 2195 * Get a debugging dump of a system service by name. 2196 * 2197 * <p>Most services require the caller to hold android.permission.DUMP. 2198 * 2199 * @param name of the service to dump 2200 * @param fd to write dump output to (usually an output log file) 2201 * @param args to pass to the service's dump method, may be null 2202 * @return true if the service was dumped successfully, false if 2203 * the service could not be found or had an error while dumping 2204 */ dumpService(String name, FileDescriptor fd, String[] args)2205 public static boolean dumpService(String name, FileDescriptor fd, String[] args) { 2206 IBinder service = ServiceManager.getService(name); 2207 if (service == null) { 2208 Log.e(TAG, "Can't find service to dump: " + name); 2209 return false; 2210 } 2211 2212 try { 2213 service.dump(fd, args); 2214 return true; 2215 } catch (RemoteException e) { 2216 Log.e(TAG, "Can't dump service: " + name, e); 2217 return false; 2218 } 2219 } 2220 2221 /** 2222 * Have the stack traces of the given native process dumped to the 2223 * specified file. Will be appended to the file. 2224 * @hide 2225 */ dumpNativeBacktraceToFile(int pid, String file)2226 public static native void dumpNativeBacktraceToFile(int pid, String file); 2227 2228 /** 2229 * Get description of unreachable native memory. 2230 * @param limit the number of leaks to provide info on, 0 to only get a summary. 2231 * @param contents true to include a hex dump of the contents of unreachable memory. 2232 * @return the String containing a description of unreachable memory. 2233 * @hide */ getUnreachableMemory(int limit, boolean contents)2234 public static native String getUnreachableMemory(int limit, boolean contents); 2235 2236 /** 2237 * Return a String describing the calling method and location at a particular stack depth. 2238 * @param callStack the Thread stack 2239 * @param depth the depth of stack to return information for. 2240 * @return the String describing the caller at that depth. 2241 */ getCaller(StackTraceElement callStack[], int depth)2242 private static String getCaller(StackTraceElement callStack[], int depth) { 2243 // callStack[4] is the caller of the method that called getCallers() 2244 if (4 + depth >= callStack.length) { 2245 return "<bottom of call stack>"; 2246 } 2247 StackTraceElement caller = callStack[4 + depth]; 2248 return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber(); 2249 } 2250 2251 /** 2252 * Return a string consisting of methods and locations at multiple call stack levels. 2253 * @param depth the number of levels to return, starting with the immediate caller. 2254 * @return a string describing the call stack. 2255 * {@hide} 2256 */ getCallers(final int depth)2257 public static String getCallers(final int depth) { 2258 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); 2259 StringBuffer sb = new StringBuffer(); 2260 for (int i = 0; i < depth; i++) { 2261 sb.append(getCaller(callStack, i)).append(" "); 2262 } 2263 return sb.toString(); 2264 } 2265 2266 /** 2267 * Return a string consisting of methods and locations at multiple call stack levels. 2268 * @param depth the number of levels to return, starting with the immediate caller. 2269 * @return a string describing the call stack. 2270 * {@hide} 2271 */ getCallers(final int start, int depth)2272 public static String getCallers(final int start, int depth) { 2273 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); 2274 StringBuffer sb = new StringBuffer(); 2275 depth += start; 2276 for (int i = start; i < depth; i++) { 2277 sb.append(getCaller(callStack, i)).append(" "); 2278 } 2279 return sb.toString(); 2280 } 2281 2282 /** 2283 * Like {@link #getCallers(int)}, but each location is append to the string 2284 * as a new line with <var>linePrefix</var> in front of it. 2285 * @param depth the number of levels to return, starting with the immediate caller. 2286 * @param linePrefix prefix to put in front of each location. 2287 * @return a string describing the call stack. 2288 * {@hide} 2289 */ getCallers(final int depth, String linePrefix)2290 public static String getCallers(final int depth, String linePrefix) { 2291 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); 2292 StringBuffer sb = new StringBuffer(); 2293 for (int i = 0; i < depth; i++) { 2294 sb.append(linePrefix).append(getCaller(callStack, i)).append("\n"); 2295 } 2296 return sb.toString(); 2297 } 2298 2299 /** 2300 * @return a String describing the immediate caller of the calling method. 2301 * {@hide} 2302 */ getCaller()2303 public static String getCaller() { 2304 return getCaller(Thread.currentThread().getStackTrace(), 0); 2305 } 2306 } 2307