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