StrictMode.java revision e7520d89fe2c5dc9dd833ecd9769c981df855b61
1/* 2 * Copyright (C) 2010 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 */ 16package android.os; 17 18import android.animation.ValueAnimator; 19import android.app.ActivityManagerNative; 20import android.app.ActivityThread; 21import android.app.ApplicationErrorReport; 22import android.content.Intent; 23import android.util.Log; 24import android.util.Printer; 25 26import com.android.internal.os.RuntimeInit; 27 28import dalvik.system.BlockGuard; 29import dalvik.system.CloseGuard; 30 31import java.io.PrintWriter; 32import java.io.StringWriter; 33import java.util.ArrayList; 34import java.util.HashMap; 35 36/** 37 * <p>StrictMode is a developer tool which detects things you might be 38 * doing by accident and brings them to your attention so you can fix 39 * them. 40 * 41 * <p>StrictMode is most commonly used to catch accidental disk or 42 * network access on the application's main thread, where UI 43 * operations are received and animations take place. Keeping disk 44 * and network operations off the main thread makes for much smoother, 45 * more responsive applications. By keeping your application's main thread 46 * responsive, you also prevent 47 * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a> 48 * from being shown to users. 49 * 50 * <p class="note">Note that even though an Android device's disk is 51 * often on flash memory, many devices run a filesystem on top of that 52 * memory with very limited concurrency. It's often the case that 53 * almost all disk accesses are fast, but may in individual cases be 54 * dramatically slower when certain I/O is happening in the background 55 * from other processes. If possible, it's best to assume that such 56 * things are not fast.</p> 57 * 58 * <p>Example code to enable from early in your 59 * {@link android.app.Application}, {@link android.app.Activity}, or 60 * other application component's 61 * {@link android.app.Application#onCreate} method: 62 * 63 * <pre> 64 * public void onCreate() { 65 * if (DEVELOPER_MODE) { 66 * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}() 67 * .detectDiskReads() 68 * .detectDiskWrites() 69 * .detectNetwork() // or .detectAll() for all detectable problems 70 * .penaltyLog() 71 * .build()); 72 * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}() 73 * .detectLeakedSqlLiteObjects() 74 * .detectLeakedClosableObjects() 75 * .penaltyLog() 76 * .penaltyDeath() 77 * .build()); 78 * } 79 * super.onCreate(); 80 * } 81 * </pre> 82 * 83 * <p>You can decide what should happen when a violation is detected. 84 * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can 85 * watch the output of <code>adb logcat</code> while you use your 86 * application to see the violations as they happen. 87 * 88 * <p>If you find violations that you feel are problematic, there are 89 * a variety of tools to help solve them: threads, {@link android.os.Handler}, 90 * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc. 91 * But don't feel compelled to fix everything that StrictMode finds. In particular, 92 * many cases of disk access are often necessary during the normal activity lifecycle. Use 93 * StrictMode to find things you did by accident. Network requests on the UI thread 94 * are almost always a problem, though. 95 * 96 * <p class="note">StrictMode is not a security mechanism and is not 97 * guaranteed to find all disk or network accesses. While it does 98 * propagate its state across process boundaries when doing 99 * {@link android.os.Binder} calls, it's still ultimately a best 100 * effort mechanism. Notably, disk or network access from JNI calls 101 * won't necessarily trigger it. Future versions of Android may catch 102 * more (or fewer) operations, so you should never leave StrictMode 103 * enabled in shipping applications on the Android Market. 104 */ 105public final class StrictMode { 106 private static final String TAG = "StrictMode"; 107 private static final boolean LOG_V = false; 108 109 // Only log a duplicate stack trace to the logs every second. 110 private static final long MIN_LOG_INTERVAL_MS = 1000; 111 112 // Only show an annoying dialog at most every 30 seconds 113 private static final long MIN_DIALOG_INTERVAL_MS = 30000; 114 115 // How many Span tags (e.g. animations) to report. 116 private static final int MAX_SPAN_TAGS = 20; 117 118 // How many offending stacks to keep track of (and time) per loop 119 // of the Looper. 120 private static final int MAX_OFFENSES_PER_LOOP = 10; 121 122 // Thread-policy: 123 124 /** 125 * @hide 126 */ 127 public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy 128 129 /** 130 * @hide 131 */ 132 public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy 133 134 /** 135 * @hide 136 */ 137 public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy 138 139 // Process-policy: 140 141 /** 142 * Note, a "VM_" bit, not thread. 143 * @hide 144 */ 145 public static final int DETECT_VM_CURSOR_LEAKS = 0x200; // for ProcessPolicy 146 147 /** 148 * Note, a "VM_" bit, not thread. 149 * @hide 150 */ 151 public static final int DETECT_VM_CLOSABLE_LEAKS = 0x400; // for ProcessPolicy 152 153 /** 154 * @hide 155 */ 156 public static final int PENALTY_LOG = 0x10; // normal android.util.Log 157 158 // Used for both process and thread policy: 159 160 /** 161 * @hide 162 */ 163 public static final int PENALTY_DIALOG = 0x20; 164 165 /** 166 * Death on any detected violation. 167 * 168 * @hide 169 */ 170 public static final int PENALTY_DEATH = 0x40; 171 172 /** 173 * Death just for detected network usage. 174 * 175 * @hide 176 */ 177 public static final int PENALTY_DEATH_ON_NETWORK = 0x200; 178 179 /** 180 * @hide 181 */ 182 public static final int PENALTY_DROPBOX = 0x80; 183 184 /** 185 * Non-public penalty mode which overrides all the other penalty 186 * bits and signals that we're in a Binder call and we should 187 * ignore the other penalty bits and instead serialize back all 188 * our offending stack traces to the caller to ultimately handle 189 * in the originating process. 190 * 191 * This must be kept in sync with the constant in libs/binder/Parcel.cpp 192 * 193 * @hide 194 */ 195 public static final int PENALTY_GATHER = 0x100; 196 197 /** 198 * Mask of all the penalty bits. 199 */ 200 private static final int PENALTY_MASK = 201 PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER | 202 PENALTY_DEATH_ON_NETWORK; 203 204 /** 205 * The current VmPolicy in effect. 206 */ 207 private static volatile int sVmPolicyMask = 0; 208 209 private StrictMode() {} 210 211 /** 212 * {@link StrictMode} policy applied to a certain thread. 213 * 214 * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy 215 * can be retrieved with {@link #getThreadPolicy}. 216 * 217 * <p>Note that multiple penalties may be provided and they're run 218 * in order from least to most severe (logging before process 219 * death, for example). There's currently no mechanism to choose 220 * different penalties for different detected actions. 221 */ 222 public static final class ThreadPolicy { 223 /** 224 * The default, lax policy which doesn't catch anything. 225 */ 226 public static final ThreadPolicy LAX = new ThreadPolicy(0); 227 228 final int mask; 229 230 private ThreadPolicy(int mask) { 231 this.mask = mask; 232 } 233 234 @Override 235 public String toString() { 236 return "[StrictMode.ThreadPolicy; mask=" + mask + "]"; 237 } 238 239 /** 240 * Creates ThreadPolicy instances. Methods whose names start 241 * with {@code detect} specify what problems we should look 242 * for. Methods whose names start with {@code penalty} specify what 243 * we should do when we detect a problem. 244 * 245 * <p>You can call as many {@code detect} and {@code penalty} 246 * methods as you like. Currently order is insignificant: all 247 * penalties apply to all detected problems. 248 * 249 * <p>For example, detect everything and log anything that's found: 250 * <pre> 251 * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder() 252 * .detectAll() 253 * .penaltyLog() 254 * .build(); 255 * StrictMode.setVmPolicy(policy); 256 * </pre> 257 */ 258 public static final class Builder { 259 private int mMask = 0; 260 261 /** 262 * Create a Builder that detects nothing and has no 263 * violations. (but note that {@link #build} will default 264 * to enabling {@link #penaltyLog} if no other penalties 265 * are specified) 266 */ 267 public Builder() { 268 mMask = 0; 269 } 270 271 /** 272 * Initialize a Builder from an existing ThreadPolicy. 273 */ 274 public Builder(ThreadPolicy policy) { 275 mMask = policy.mask; 276 } 277 278 /** 279 * Detect everything that's potentially suspect. 280 * 281 * <p>As of the Gingerbread release this includes network and 282 * disk operations but will likely expand in future releases. 283 */ 284 public Builder detectAll() { 285 return enable(DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK); 286 } 287 288 /** 289 * Disable the detection of everything. 290 */ 291 public Builder permitAll() { 292 return disable(DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK); 293 } 294 295 /** 296 * Enable detection of network operations. 297 */ 298 public Builder detectNetwork() { 299 return enable(DETECT_NETWORK); 300 } 301 302 /** 303 * Disable detection of network operations. 304 */ 305 public Builder permitNetwork() { 306 return disable(DETECT_NETWORK); 307 } 308 309 /** 310 * Enable detection of disk reads. 311 */ 312 public Builder detectDiskReads() { 313 return enable(DETECT_DISK_READ); 314 } 315 316 /** 317 * Disable detection of disk reads. 318 */ 319 public Builder permitDiskReads() { 320 return disable(DETECT_DISK_READ); 321 } 322 323 /** 324 * Enable detection of disk writes. 325 */ 326 public Builder detectDiskWrites() { 327 return enable(DETECT_DISK_WRITE); 328 } 329 330 /** 331 * Disable detection of disk writes. 332 */ 333 public Builder permitDiskWrites() { 334 return disable(DETECT_DISK_WRITE); 335 } 336 337 /** 338 * Show an annoying dialog to the developer on detected 339 * violations, rate-limited to be only a little annoying. 340 */ 341 public Builder penaltyDialog() { 342 return enable(PENALTY_DIALOG); 343 } 344 345 /** 346 * Crash the whole process on violation. This penalty runs at 347 * the end of all enabled penalties so you'll still get 348 * see logging or other violations before the process dies. 349 * 350 * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies 351 * to disk reads, disk writes, and network usage if their 352 * corresponding detect flags are set. 353 */ 354 public Builder penaltyDeath() { 355 return enable(PENALTY_DEATH); 356 } 357 358 /** 359 * Crash the whole process on any network usage. Unlike 360 * {@link #penaltyDeath}, this penalty runs 361 * <em>before</em> anything else. You must still have 362 * called {@link #detectNetwork} to enable this. 363 * 364 * <p>In the Honeycomb or later SDKs, this is on by default. 365 */ 366 public Builder penaltyDeathOnNetwork() { 367 return enable(PENALTY_DEATH_ON_NETWORK); 368 } 369 370 /** 371 * Log detected violations to the system log. 372 */ 373 public Builder penaltyLog() { 374 return enable(PENALTY_LOG); 375 } 376 377 /** 378 * Enable detected violations log a stacktrace and timing data 379 * to the {@link android.os.DropBoxManager DropBox} on policy 380 * violation. Intended mostly for platform integrators doing 381 * beta user field data collection. 382 */ 383 public Builder penaltyDropBox() { 384 return enable(PENALTY_DROPBOX); 385 } 386 387 private Builder enable(int bit) { 388 mMask |= bit; 389 return this; 390 } 391 392 private Builder disable(int bit) { 393 mMask &= ~bit; 394 return this; 395 } 396 397 /** 398 * Construct the ThreadPolicy instance. 399 * 400 * <p>Note: if no penalties are enabled before calling 401 * <code>build</code>, {@link #penaltyLog} is implicitly 402 * set. 403 */ 404 public ThreadPolicy build() { 405 // If there are detection bits set but no violation bits 406 // set, enable simple logging. 407 if (mMask != 0 && 408 (mMask & (PENALTY_DEATH | PENALTY_LOG | 409 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) { 410 penaltyLog(); 411 } 412 return new ThreadPolicy(mMask); 413 } 414 } 415 } 416 417 /** 418 * {@link StrictMode} policy applied to all threads in the virtual machine's process. 419 * 420 * <p>The policy is enabled by {@link #setVmPolicy}. 421 */ 422 public static final class VmPolicy { 423 /** 424 * The default, lax policy which doesn't catch anything. 425 */ 426 public static final VmPolicy LAX = new VmPolicy(0); 427 428 final int mask; 429 430 private VmPolicy(int mask) { 431 this.mask = mask; 432 } 433 434 @Override 435 public String toString() { 436 return "[StrictMode.VmPolicy; mask=" + mask + "]"; 437 } 438 439 /** 440 * Creates {@link VmPolicy} instances. Methods whose names start 441 * with {@code detect} specify what problems we should look 442 * for. Methods whose names start with {@code penalty} specify what 443 * we should do when we detect a problem. 444 * 445 * <p>You can call as many {@code detect} and {@code penalty} 446 * methods as you like. Currently order is insignificant: all 447 * penalties apply to all detected problems. 448 * 449 * <p>For example, detect everything and log anything that's found: 450 * <pre> 451 * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder() 452 * .detectAll() 453 * .penaltyLog() 454 * .build(); 455 * StrictMode.setVmPolicy(policy); 456 * </pre> 457 */ 458 public static final class Builder { 459 private int mMask; 460 461 /** 462 * Detect everything that's potentially suspect. 463 * 464 * <p>In the Honeycomb release this includes leaks of 465 * SQLite cursors and other closable objects but will 466 * likely expand in future releases. 467 */ 468 public Builder detectAll() { 469 return enable(DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS); 470 } 471 472 /** 473 * Detect when an 474 * {@link android.database.sqlite.SQLiteCursor} or other 475 * SQLite object is finalized without having been closed. 476 * 477 * <p>You always want to explicitly close your SQLite 478 * cursors to avoid unnecessary database contention and 479 * temporary memory leaks. 480 */ 481 public Builder detectLeakedSqlLiteObjects() { 482 return enable(DETECT_VM_CURSOR_LEAKS); 483 } 484 485 /** 486 * Detect when an {@link java.io.Closeable} or other 487 * object with a explict termination method is finalized 488 * without having been closed. 489 * 490 * <p>You always want to explicitly close such objects to 491 * avoid unnecessary resources leaks. 492 */ 493 public Builder detectLeakedClosableObjects() { 494 return enable(DETECT_VM_CLOSABLE_LEAKS); 495 } 496 497 /** 498 * Crashes the whole process on violation. This penalty runs at 499 * the end of all enabled penalties so yo you'll still get 500 * your logging or other violations before the process dies. 501 */ 502 public Builder penaltyDeath() { 503 return enable(PENALTY_DEATH); 504 } 505 506 /** 507 * Log detected violations to the system log. 508 */ 509 public Builder penaltyLog() { 510 return enable(PENALTY_LOG); 511 } 512 513 /** 514 * Enable detected violations log a stacktrace and timing data 515 * to the {@link android.os.DropBoxManager DropBox} on policy 516 * violation. Intended mostly for platform integrators doing 517 * beta user field data collection. 518 */ 519 public Builder penaltyDropBox() { 520 return enable(PENALTY_DROPBOX); 521 } 522 523 private Builder enable(int bit) { 524 mMask |= bit; 525 return this; 526 } 527 528 /** 529 * Construct the VmPolicy instance. 530 * 531 * <p>Note: if no penalties are enabled before calling 532 * <code>build</code>, {@link #penaltyLog} is implicitly 533 * set. 534 */ 535 public VmPolicy build() { 536 // If there are detection bits set but no violation bits 537 // set, enable simple logging. 538 if (mMask != 0 && 539 (mMask & (PENALTY_DEATH | PENALTY_LOG | 540 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) { 541 penaltyLog(); 542 } 543 return new VmPolicy(mMask); 544 } 545 } 546 } 547 548 /** 549 * Log of strict mode violation stack traces that have occurred 550 * during a Binder call, to be serialized back later to the caller 551 * via Parcel.writeNoException() (amusingly) where the caller can 552 * choose how to react. 553 */ 554 private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations = 555 new ThreadLocal<ArrayList<ViolationInfo>>() { 556 @Override protected ArrayList<ViolationInfo> initialValue() { 557 // Starts null to avoid unnecessary allocations when 558 // checking whether there are any violations or not in 559 // hasGatheredViolations() below. 560 return null; 561 } 562 }; 563 564 /** 565 * Sets the policy for what actions on the current thread should 566 * be detected, as well as the penalty if such actions occur. 567 * 568 * <p>Internally this sets a thread-local variable which is 569 * propagated across cross-process IPC calls, meaning you can 570 * catch violations when a system service or another process 571 * accesses the disk or network on your behalf. 572 * 573 * @param policy the policy to put into place 574 */ 575 public static void setThreadPolicy(final ThreadPolicy policy) { 576 setThreadPolicyMask(policy.mask); 577 } 578 579 private static void setThreadPolicyMask(final int policyMask) { 580 // In addition to the Java-level thread-local in Dalvik's 581 // BlockGuard, we also need to keep a native thread-local in 582 // Binder in order to propagate the value across Binder calls, 583 // even across native-only processes. The two are kept in 584 // sync via the callback to onStrictModePolicyChange, below. 585 setBlockGuardPolicy(policyMask); 586 587 // And set the Android native version... 588 Binder.setThreadStrictModePolicy(policyMask); 589 } 590 591 // Sets the policy in Dalvik/libcore (BlockGuard) 592 private static void setBlockGuardPolicy(final int policyMask) { 593 if (policyMask == 0) { 594 BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY); 595 return; 596 } 597 BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); 598 if (!(policy instanceof AndroidBlockGuardPolicy)) { 599 BlockGuard.setThreadPolicy(new AndroidBlockGuardPolicy(policyMask)); 600 } else { 601 AndroidBlockGuardPolicy androidPolicy = (AndroidBlockGuardPolicy) policy; 602 androidPolicy.setPolicyMask(policyMask); 603 } 604 } 605 606 // Sets up CloseGuard in Dalvik/libcore 607 private static void setCloseGuardEnabled(boolean enabled) { 608 if (!(CloseGuard.getReporter() instanceof AndroidBlockGuardPolicy)) { 609 CloseGuard.setReporter(new AndroidCloseGuardReporter()); 610 } 611 CloseGuard.setEnabled(enabled); 612 } 613 614 private static class StrictModeNetworkViolation extends BlockGuard.BlockGuardPolicyException { 615 public StrictModeNetworkViolation(int policyMask) { 616 super(policyMask, DETECT_NETWORK); 617 } 618 } 619 620 private static class StrictModeDiskReadViolation extends BlockGuard.BlockGuardPolicyException { 621 public StrictModeDiskReadViolation(int policyMask) { 622 super(policyMask, DETECT_DISK_READ); 623 } 624 } 625 626 private static class StrictModeDiskWriteViolation extends BlockGuard.BlockGuardPolicyException { 627 public StrictModeDiskWriteViolation(int policyMask) { 628 super(policyMask, DETECT_DISK_WRITE); 629 } 630 } 631 632 /** 633 * Returns the bitmask of the current thread's policy. 634 * 635 * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled 636 * 637 * @hide 638 */ 639 public static int getThreadPolicyMask() { 640 return BlockGuard.getThreadPolicy().getPolicyMask(); 641 } 642 643 /** 644 * Returns the current thread's policy. 645 */ 646 public static ThreadPolicy getThreadPolicy() { 647 return new ThreadPolicy(getThreadPolicyMask()); 648 } 649 650 /** 651 * A convenience wrapper that takes the current 652 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it 653 * to permit both disk reads & writes, and sets the new policy 654 * with {@link #setThreadPolicy}, returning the old policy so you 655 * can restore it at the end of a block. 656 * 657 * @return the old policy, to be passed to {@link #setThreadPolicy} to 658 * restore the policy at the end of a block 659 */ 660 public static ThreadPolicy allowThreadDiskWrites() { 661 int oldPolicyMask = getThreadPolicyMask(); 662 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ); 663 if (newPolicyMask != oldPolicyMask) { 664 setThreadPolicyMask(newPolicyMask); 665 } 666 return new ThreadPolicy(oldPolicyMask); 667 } 668 669 /** 670 * A convenience wrapper that takes the current 671 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it 672 * to permit disk reads, and sets the new policy 673 * with {@link #setThreadPolicy}, returning the old policy so you 674 * can restore it at the end of a block. 675 * 676 * @return the old policy, to be passed to setThreadPolicy to 677 * restore the policy. 678 */ 679 public static ThreadPolicy allowThreadDiskReads() { 680 int oldPolicyMask = getThreadPolicyMask(); 681 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ); 682 if (newPolicyMask != oldPolicyMask) { 683 setThreadPolicyMask(newPolicyMask); 684 } 685 return new ThreadPolicy(oldPolicyMask); 686 } 687 688 /** 689 * Enable DropBox logging for debug phone builds. 690 * 691 * @hide 692 */ 693 public static boolean conditionallyEnableDebugLogging() { 694 // For debug builds, log event loop stalls to dropbox for analysis. 695 // Similar logic also appears in ActivityThread.java for system apps. 696 if ("user".equals(Build.TYPE)) { 697 return false; 698 } 699 StrictMode.setThreadPolicyMask( 700 StrictMode.DETECT_DISK_WRITE | 701 StrictMode.DETECT_DISK_READ | 702 StrictMode.DETECT_NETWORK | 703 StrictMode.PENALTY_DROPBOX); 704 sVmPolicyMask = StrictMode.DETECT_VM_CURSOR_LEAKS | 705 StrictMode.DETECT_VM_CLOSABLE_LEAKS | 706 StrictMode.PENALTY_DROPBOX | 707 StrictMode.PENALTY_LOG; 708 return true; 709 } 710 711 /** 712 * Used by the framework to make network usage on the main 713 * thread a fatal error. 714 * 715 * @hide 716 */ 717 public static void enableDeathOnNetwork() { 718 int oldPolicy = getThreadPolicyMask(); 719 int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK; 720 setThreadPolicyMask(newPolicy); 721 } 722 723 /** 724 * Parses the BlockGuard policy mask out from the Exception's 725 * getMessage() String value. Kinda gross, but least 726 * invasive. :/ 727 * 728 * Input is of form "policy=137 violation=64" 729 * 730 * Returns 0 on failure, which is a valid policy, but not a 731 * valid policy during a violation (else there must've been 732 * some policy in effect to violate). 733 */ 734 private static int parsePolicyFromMessage(String message) { 735 if (message == null || !message.startsWith("policy=")) { 736 return 0; 737 } 738 int spaceIndex = message.indexOf(' '); 739 if (spaceIndex == -1) { 740 return 0; 741 } 742 String policyString = message.substring(7, spaceIndex); 743 try { 744 return Integer.valueOf(policyString).intValue(); 745 } catch (NumberFormatException e) { 746 return 0; 747 } 748 } 749 750 /** 751 * Like parsePolicyFromMessage(), but returns the violation. 752 */ 753 private static int parseViolationFromMessage(String message) { 754 if (message == null) { 755 return 0; 756 } 757 int violationIndex = message.indexOf("violation="); 758 if (violationIndex == -1) { 759 return 0; 760 } 761 String violationString = message.substring(violationIndex + 10); 762 try { 763 return Integer.valueOf(violationString).intValue(); 764 } catch (NumberFormatException e) { 765 return 0; 766 } 767 } 768 769 private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed = 770 new ThreadLocal<ArrayList<ViolationInfo>>() { 771 @Override protected ArrayList<ViolationInfo> initialValue() { 772 return new ArrayList<ViolationInfo>(); 773 } 774 }; 775 776 private static boolean tooManyViolationsThisLoop() { 777 return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP; 778 } 779 780 private static class AndroidBlockGuardPolicy implements BlockGuard.Policy { 781 private int mPolicyMask; 782 783 // Map from violation stacktrace hashcode -> uptimeMillis of 784 // last violation. No locking needed, as this is only 785 // accessed by the same thread. 786 private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>(); 787 788 public AndroidBlockGuardPolicy(final int policyMask) { 789 mPolicyMask = policyMask; 790 } 791 792 @Override 793 public String toString() { 794 return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask; 795 } 796 797 // Part of BlockGuard.Policy interface: 798 public int getPolicyMask() { 799 return mPolicyMask; 800 } 801 802 // Part of BlockGuard.Policy interface: 803 public void onWriteToDisk() { 804 if ((mPolicyMask & DETECT_DISK_WRITE) == 0) { 805 return; 806 } 807 if (tooManyViolationsThisLoop()) { 808 return; 809 } 810 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask); 811 e.fillInStackTrace(); 812 startHandlingViolationException(e); 813 } 814 815 // Part of BlockGuard.Policy interface: 816 public void onReadFromDisk() { 817 if ((mPolicyMask & DETECT_DISK_READ) == 0) { 818 return; 819 } 820 if (tooManyViolationsThisLoop()) { 821 return; 822 } 823 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask); 824 e.fillInStackTrace(); 825 startHandlingViolationException(e); 826 } 827 828 // Part of BlockGuard.Policy interface: 829 public void onNetwork() { 830 if ((mPolicyMask & DETECT_NETWORK) == 0) { 831 return; 832 } 833 if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) { 834 throw new NetworkOnMainThreadException(); 835 } 836 if (tooManyViolationsThisLoop()) { 837 return; 838 } 839 BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask); 840 e.fillInStackTrace(); 841 startHandlingViolationException(e); 842 } 843 844 public void setPolicyMask(int policyMask) { 845 mPolicyMask = policyMask; 846 } 847 848 // Start handling a violation that just started and hasn't 849 // actually run yet (e.g. no disk write or network operation 850 // has yet occurred). This sees if we're in an event loop 851 // thread and, if so, uses it to roughly measure how long the 852 // violation took. 853 void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) { 854 final ViolationInfo info = new ViolationInfo(e, e.getPolicy()); 855 info.violationUptimeMillis = SystemClock.uptimeMillis(); 856 handleViolationWithTimingAttempt(info); 857 } 858 859 // Attempts to fill in the provided ViolationInfo's 860 // durationMillis field if this thread has a Looper we can use 861 // to measure with. We measure from the time of violation 862 // until the time the looper is idle again (right before 863 // the next epoll_wait) 864 void handleViolationWithTimingAttempt(final ViolationInfo info) { 865 Looper looper = Looper.myLooper(); 866 867 // Without a Looper, we're unable to time how long the 868 // violation takes place. This case should be rare, as 869 // most users will care about timing violations that 870 // happen on their main UI thread. Note that this case is 871 // also hit when a violation takes place in a Binder 872 // thread, in "gather" mode. In this case, the duration 873 // of the violation is computed by the ultimate caller and 874 // its Looper, if any. 875 // TODO: if in gather mode, ignore Looper.myLooper() and always 876 // go into this immediate mode? 877 if (looper == null) { 878 info.durationMillis = -1; // unknown (redundant, already set) 879 handleViolation(info); 880 return; 881 } 882 883 MessageQueue queue = Looper.myQueue(); 884 final ArrayList<ViolationInfo> records = violationsBeingTimed.get(); 885 if (records.size() >= MAX_OFFENSES_PER_LOOP) { 886 // Not worth measuring. Too many offenses in one loop. 887 return; 888 } 889 records.add(info); 890 if (records.size() > 1) { 891 // There's already been a violation this loop, so we've already 892 // registered an idle handler to process the list of violations 893 // at the end of this Looper's loop. 894 return; 895 } 896 897 queue.addIdleHandler(new MessageQueue.IdleHandler() { 898 public boolean queueIdle() { 899 long loopFinishTime = SystemClock.uptimeMillis(); 900 for (int n = 0; n < records.size(); ++n) { 901 ViolationInfo v = records.get(n); 902 v.violationNumThisLoop = n + 1; 903 v.durationMillis = 904 (int) (loopFinishTime - v.violationUptimeMillis); 905 handleViolation(v); 906 } 907 records.clear(); 908 return false; // remove this idle handler from the array 909 } 910 }); 911 } 912 913 // Note: It's possible (even quite likely) that the 914 // thread-local policy mask has changed from the time the 915 // violation fired and now (after the violating code ran) due 916 // to people who push/pop temporary policy in regions of code, 917 // hence the policy being passed around. 918 void handleViolation(final ViolationInfo info) { 919 if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) { 920 Log.wtf(TAG, "unexpected null stacktrace"); 921 return; 922 } 923 924 if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy); 925 926 if ((info.policy & PENALTY_GATHER) != 0) { 927 ArrayList<ViolationInfo> violations = gatheredViolations.get(); 928 if (violations == null) { 929 violations = new ArrayList<ViolationInfo>(1); 930 gatheredViolations.set(violations); 931 } else if (violations.size() >= 5) { 932 // Too many. In a loop or something? Don't gather them all. 933 return; 934 } 935 for (ViolationInfo previous : violations) { 936 if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) { 937 // Duplicate. Don't log. 938 return; 939 } 940 } 941 violations.add(info); 942 return; 943 } 944 945 // Not perfect, but fast and good enough for dup suppression. 946 Integer crashFingerprint = info.crashInfo.stackTrace.hashCode(); 947 long lastViolationTime = 0; 948 if (mLastViolationTime.containsKey(crashFingerprint)) { 949 lastViolationTime = mLastViolationTime.get(crashFingerprint); 950 } 951 long now = SystemClock.uptimeMillis(); 952 mLastViolationTime.put(crashFingerprint, now); 953 long timeSinceLastViolationMillis = lastViolationTime == 0 ? 954 Long.MAX_VALUE : (now - lastViolationTime); 955 956 if ((info.policy & PENALTY_LOG) != 0 && 957 timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) { 958 if (info.durationMillis != -1) { 959 Log.d(TAG, "StrictMode policy violation; ~duration=" + 960 info.durationMillis + " ms: " + info.crashInfo.stackTrace); 961 } else { 962 Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace); 963 } 964 } 965 966 // The violationMaskSubset, passed to ActivityManager, is a 967 // subset of the original StrictMode policy bitmask, with 968 // only the bit violated and penalty bits to be executed 969 // by the ActivityManagerService remaining set. 970 int violationMaskSubset = 0; 971 972 if ((info.policy & PENALTY_DIALOG) != 0 && 973 timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) { 974 violationMaskSubset |= PENALTY_DIALOG; 975 } 976 977 if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) { 978 violationMaskSubset |= PENALTY_DROPBOX; 979 } 980 981 if (violationMaskSubset != 0) { 982 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage); 983 violationMaskSubset |= violationBit; 984 final int violationMaskSubsetFinal = violationMaskSubset; 985 final int savedPolicyMask = getThreadPolicyMask(); 986 987 final boolean justDropBox = (info.policy & PENALTY_MASK) == PENALTY_DROPBOX; 988 if (justDropBox) { 989 // If all we're going to ask the activity manager 990 // to do is dropbox it (the common case during 991 // platform development), we can avoid doing this 992 // call synchronously which Binder data suggests 993 // isn't always super fast, despite the implementation 994 // in the ActivityManager trying to be mostly async. 995 new Thread("callActivityManagerForStrictModeDropbox") { 996 public void run() { 997 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 998 try { 999 ActivityManagerNative.getDefault(). 1000 handleApplicationStrictModeViolation( 1001 RuntimeInit.getApplicationObject(), 1002 violationMaskSubsetFinal, 1003 info); 1004 } catch (RemoteException e) { 1005 Log.e(TAG, "RemoteException handling StrictMode violation", e); 1006 } 1007 } 1008 }.start(); 1009 return; 1010 } 1011 1012 // Normal synchronous call to the ActivityManager. 1013 try { 1014 // First, remove any policy before we call into the Activity Manager, 1015 // otherwise we'll infinite recurse as we try to log policy violations 1016 // to disk, thus violating policy, thus requiring logging, etc... 1017 // We restore the current policy below, in the finally block. 1018 setThreadPolicyMask(0); 1019 1020 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( 1021 RuntimeInit.getApplicationObject(), 1022 violationMaskSubset, 1023 info); 1024 } catch (RemoteException e) { 1025 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); 1026 } finally { 1027 // Restore the policy. 1028 setThreadPolicyMask(savedPolicyMask); 1029 } 1030 } 1031 1032 if ((info.policy & PENALTY_DEATH) != 0) { 1033 System.err.println("StrictMode policy violation with POLICY_DEATH; shutting down."); 1034 Process.killProcess(Process.myPid()); 1035 System.exit(10); 1036 } 1037 } 1038 } 1039 1040 private static class AndroidCloseGuardReporter implements CloseGuard.Reporter { 1041 public void report (String message, Throwable allocationSite) { 1042 onVmPolicyViolation(message, allocationSite); 1043 } 1044 } 1045 1046 /** 1047 * Called from Parcel.writeNoException() 1048 */ 1049 /* package */ static boolean hasGatheredViolations() { 1050 return gatheredViolations.get() != null; 1051 } 1052 1053 /** 1054 * Called from Parcel.writeException(), so we drop this memory and 1055 * don't incorrectly attribute it to the wrong caller on the next 1056 * Binder call on this thread. 1057 */ 1058 /* package */ static void clearGatheredViolations() { 1059 gatheredViolations.set(null); 1060 } 1061 1062 /** 1063 * Sets the policy for what actions in the VM process (on any 1064 * thread) should be detected, as well as the penalty if such 1065 * actions occur. 1066 * 1067 * @param policy the policy to put into place 1068 */ 1069 public static void setVmPolicy(final VmPolicy policy) { 1070 sVmPolicyMask = policy.mask; 1071 setCloseGuardEnabled(vmClosableObjectLeaksEnabled()); 1072 } 1073 1074 /** 1075 * Gets the current VM policy. 1076 */ 1077 public static VmPolicy getVmPolicy() { 1078 return new VmPolicy(sVmPolicyMask); 1079 } 1080 1081 /** 1082 * Enable the recommended StrictMode defaults, with violations just being logged. 1083 * 1084 * <p>This catches disk and network access on the main thread, as 1085 * well as leaked SQLite cursors and unclosed resources. This is 1086 * simply a wrapper around {@link #setVmPolicy} and {@link 1087 * #setThreadPolicy}. 1088 */ 1089 public static void enableDefaults() { 1090 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() 1091 .detectAll() 1092 .penaltyLog() 1093 .build()); 1094 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() 1095 .detectLeakedSqlLiteObjects() 1096 .detectLeakedClosableObjects() 1097 .penaltyLog() 1098 .build()); 1099 } 1100 1101 /** 1102 * @hide 1103 */ 1104 public static boolean vmSqliteObjectLeaksEnabled() { 1105 return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0; 1106 } 1107 1108 /** 1109 * @hide 1110 */ 1111 public static boolean vmClosableObjectLeaksEnabled() { 1112 return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0; 1113 } 1114 1115 /** 1116 * @hide 1117 */ 1118 public static void onSqliteObjectLeaked(String message, Throwable originStack) { 1119 onVmPolicyViolation(message, originStack); 1120 } 1121 1122 /** 1123 * @hide 1124 */ 1125 public static void onVmPolicyViolation(String message, Throwable originStack) { 1126 if ((sVmPolicyMask & PENALTY_LOG) != 0) { 1127 Log.e(TAG, message, originStack); 1128 } 1129 1130 if ((sVmPolicyMask & PENALTY_DROPBOX) != 0) { 1131 final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask); 1132 1133 // The violationMask, passed to ActivityManager, is a 1134 // subset of the original StrictMode policy bitmask, with 1135 // only the bit violated and penalty bits to be executed 1136 // by the ActivityManagerService remaining set. 1137 int violationMaskSubset = PENALTY_DROPBOX | DETECT_VM_CURSOR_LEAKS; 1138 final int savedPolicyMask = getThreadPolicyMask(); 1139 try { 1140 // First, remove any policy before we call into the Activity Manager, 1141 // otherwise we'll infinite recurse as we try to log policy violations 1142 // to disk, thus violating policy, thus requiring logging, etc... 1143 // We restore the current policy below, in the finally block. 1144 setThreadPolicyMask(0); 1145 1146 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( 1147 RuntimeInit.getApplicationObject(), 1148 violationMaskSubset, 1149 info); 1150 } catch (RemoteException e) { 1151 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); 1152 } finally { 1153 // Restore the policy. 1154 setThreadPolicyMask(savedPolicyMask); 1155 } 1156 } 1157 1158 if ((sVmPolicyMask & PENALTY_DEATH) != 0) { 1159 System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down."); 1160 Process.killProcess(Process.myPid()); 1161 System.exit(10); 1162 } 1163 } 1164 1165 /** 1166 * Called from Parcel.writeNoException() 1167 */ 1168 /* package */ static void writeGatheredViolationsToParcel(Parcel p) { 1169 ArrayList<ViolationInfo> violations = gatheredViolations.get(); 1170 if (violations == null) { 1171 p.writeInt(0); 1172 } else { 1173 p.writeInt(violations.size()); 1174 for (int i = 0; i < violations.size(); ++i) { 1175 violations.get(i).writeToParcel(p, 0 /* unused flags? */); 1176 } 1177 if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size()); 1178 violations.clear(); // somewhat redundant, as we're about to null the threadlocal 1179 } 1180 gatheredViolations.set(null); 1181 } 1182 1183 private static class LogStackTrace extends Exception {} 1184 1185 /** 1186 * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, 1187 * we here read back all the encoded violations. 1188 */ 1189 /* package */ static void readAndHandleBinderCallViolations(Parcel p) { 1190 // Our own stack trace to append 1191 StringWriter sw = new StringWriter(); 1192 new LogStackTrace().printStackTrace(new PrintWriter(sw)); 1193 String ourStack = sw.toString(); 1194 1195 int policyMask = getThreadPolicyMask(); 1196 boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0; 1197 1198 int numViolations = p.readInt(); 1199 for (int i = 0; i < numViolations; ++i) { 1200 if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i); 1201 ViolationInfo info = new ViolationInfo(p, !currentlyGathering); 1202 info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack; 1203 BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); 1204 if (policy instanceof AndroidBlockGuardPolicy) { 1205 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info); 1206 } 1207 } 1208 } 1209 1210 /** 1211 * Called from android_util_Binder.cpp's 1212 * android_os_Parcel_enforceInterface when an incoming Binder call 1213 * requires changing the StrictMode policy mask. The role of this 1214 * function is to ask Binder for its current (native) thread-local 1215 * policy value and synchronize it to libcore's (Java) 1216 * thread-local policy value. 1217 */ 1218 private static void onBinderStrictModePolicyChange(int newPolicy) { 1219 setBlockGuardPolicy(newPolicy); 1220 } 1221 1222 /** 1223 * A tracked, critical time span. (e.g. during an animation.) 1224 * 1225 * The object itself is a linked list node, to avoid any allocations 1226 * during rapid span entries and exits. 1227 * 1228 * @hide 1229 */ 1230 public static class Span { 1231 private String mName; 1232 private long mCreateMillis; 1233 private Span mNext; 1234 private Span mPrev; // not used when in freeList, only active 1235 private final ThreadSpanState mContainerState; 1236 1237 Span(ThreadSpanState threadState) { 1238 mContainerState = threadState; 1239 } 1240 1241 /** 1242 * To be called when the critical span is complete (i.e. the 1243 * animation is done animating). This can be called on any 1244 * thread (even a different one from where the animation was 1245 * taking place), but that's only a defensive implementation 1246 * measure. It really makes no sense for you to call this on 1247 * thread other than that where you created it. 1248 * 1249 * @hide 1250 */ 1251 public void finish() { 1252 ThreadSpanState state = mContainerState; 1253 synchronized (state) { 1254 if (mName == null) { 1255 // Duplicate finish call. Ignore. 1256 return; 1257 } 1258 1259 // Remove ourselves from the active list. 1260 if (mPrev != null) { 1261 mPrev.mNext = mNext; 1262 } 1263 if (mNext != null) { 1264 mNext.mPrev = mPrev; 1265 } 1266 if (state.mActiveHead == this) { 1267 state.mActiveHead = mNext; 1268 } 1269 1270 this.mCreateMillis = -1; 1271 this.mName = null; 1272 this.mPrev = null; 1273 this.mNext = null; 1274 state.mActiveSize--; 1275 1276 // Add ourselves to the freeList, if it's not already 1277 // too big. 1278 if (state.mFreeListSize < 5) { 1279 this.mNext = state.mFreeListHead; 1280 state.mFreeListHead = this; 1281 state.mFreeListSize++; 1282 } 1283 } 1284 } 1285 } 1286 1287 /** 1288 * Linked lists of active spans and a freelist. 1289 * 1290 * Locking notes: there's one of these structures per thread and 1291 * all members of this structure (as well as the Span nodes under 1292 * it) are guarded by the ThreadSpanState object instance. While 1293 * in theory there'd be no locking required because it's all local 1294 * per-thread, the finish() method above is defensive against 1295 * people calling it on a different thread from where they created 1296 * the Span, hence the locking. 1297 */ 1298 private static class ThreadSpanState { 1299 public Span mActiveHead; // doubly-linked list. 1300 public int mActiveSize; 1301 public Span mFreeListHead; // singly-linked list. only changes at head. 1302 public int mFreeListSize; 1303 } 1304 1305 private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState = 1306 new ThreadLocal<ThreadSpanState>() { 1307 @Override protected ThreadSpanState initialValue() { 1308 return new ThreadSpanState(); 1309 } 1310 }; 1311 1312 /** 1313 * Enter a named critical span (e.g. an animation) 1314 * 1315 * <p>The name is an arbitary label (or tag) that will be applied 1316 * to any strictmode violation that happens while this span is 1317 * active. You must call finish() on the span when done. 1318 * 1319 * <p>This will never return null, but on devices without debugging 1320 * enabled, this may return a dummy object on which the finish() 1321 * method is a no-op. 1322 * 1323 * <p>TODO: add CloseGuard to this, verifying callers call finish. 1324 * 1325 * @hide 1326 */ 1327 public static Span enterCriticalSpan(String name) { 1328 if (name == null || name.isEmpty()) { 1329 throw new IllegalArgumentException("name must be non-null and non-empty"); 1330 } 1331 ThreadSpanState state = sThisThreadSpanState.get(); 1332 Span span = null; 1333 synchronized (state) { 1334 if (state.mFreeListHead != null) { 1335 span = state.mFreeListHead; 1336 state.mFreeListHead = span.mNext; 1337 state.mFreeListSize--; 1338 } else { 1339 // Shouldn't have to do this often. 1340 span = new Span(state); 1341 } 1342 span.mName = name; 1343 span.mCreateMillis = SystemClock.uptimeMillis(); 1344 span.mNext = state.mActiveHead; 1345 span.mPrev = null; 1346 state.mActiveHead = span; 1347 state.mActiveSize++; 1348 if (span.mNext != null) { 1349 span.mNext.mPrev = span; 1350 } 1351 } 1352 return span; 1353 } 1354 1355 1356 /** 1357 * Parcelable that gets sent in Binder call headers back to callers 1358 * to report violations that happened during a cross-process call. 1359 * 1360 * @hide 1361 */ 1362 public static class ViolationInfo { 1363 /** 1364 * Stack and other stuff info. 1365 */ 1366 public final ApplicationErrorReport.CrashInfo crashInfo; 1367 1368 /** 1369 * The strict mode policy mask at the time of violation. 1370 */ 1371 public final int policy; 1372 1373 /** 1374 * The wall time duration of the violation, when known. -1 when 1375 * not known. 1376 */ 1377 public int durationMillis = -1; 1378 1379 /** 1380 * The number of animations currently running. 1381 */ 1382 public int numAnimationsRunning = 0; 1383 1384 /** 1385 * List of tags from active Span instances during this 1386 * violation, or null for none. 1387 */ 1388 public String[] tags; 1389 1390 /** 1391 * Which violation number this was (1-based) since the last Looper loop, 1392 * from the perspective of the root caller (if it crossed any processes 1393 * via Binder calls). The value is 0 if the root caller wasn't on a Looper 1394 * thread. 1395 */ 1396 public int violationNumThisLoop; 1397 1398 /** 1399 * The time (in terms of SystemClock.uptimeMillis()) that the 1400 * violation occurred. 1401 */ 1402 public long violationUptimeMillis; 1403 1404 /** 1405 * The action of the Intent being broadcast to somebody's onReceive 1406 * on this thread right now, or null. 1407 */ 1408 public String broadcastIntentAction; 1409 1410 /** 1411 * Create an uninitialized instance of ViolationInfo 1412 */ 1413 public ViolationInfo() { 1414 crashInfo = null; 1415 policy = 0; 1416 } 1417 1418 /** 1419 * Create an instance of ViolationInfo initialized from an exception. 1420 */ 1421 public ViolationInfo(Throwable tr, int policy) { 1422 crashInfo = new ApplicationErrorReport.CrashInfo(tr); 1423 violationUptimeMillis = SystemClock.uptimeMillis(); 1424 this.policy = policy; 1425 this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount(); 1426 Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast(); 1427 if (broadcastIntent != null) { 1428 broadcastIntentAction = broadcastIntent.getAction(); 1429 } 1430 ThreadSpanState state = sThisThreadSpanState.get(); 1431 synchronized (state) { 1432 int spanActiveCount = state.mActiveSize; 1433 if (spanActiveCount > MAX_SPAN_TAGS) { 1434 spanActiveCount = MAX_SPAN_TAGS; 1435 } 1436 if (spanActiveCount != 0) { 1437 this.tags = new String[spanActiveCount]; 1438 Span iter = state.mActiveHead; 1439 int index = 0; 1440 while (iter != null && index < spanActiveCount) { 1441 this.tags[index] = iter.mName; 1442 index++; 1443 iter = iter.mNext; 1444 } 1445 } 1446 } 1447 } 1448 1449 /** 1450 * Create an instance of ViolationInfo initialized from a Parcel. 1451 */ 1452 public ViolationInfo(Parcel in) { 1453 this(in, false); 1454 } 1455 1456 /** 1457 * Create an instance of ViolationInfo initialized from a Parcel. 1458 * 1459 * @param unsetGatheringBit if true, the caller is the root caller 1460 * and the gathering penalty should be removed. 1461 */ 1462 public ViolationInfo(Parcel in, boolean unsetGatheringBit) { 1463 crashInfo = new ApplicationErrorReport.CrashInfo(in); 1464 int rawPolicy = in.readInt(); 1465 if (unsetGatheringBit) { 1466 policy = rawPolicy & ~PENALTY_GATHER; 1467 } else { 1468 policy = rawPolicy; 1469 } 1470 durationMillis = in.readInt(); 1471 violationNumThisLoop = in.readInt(); 1472 numAnimationsRunning = in.readInt(); 1473 violationUptimeMillis = in.readLong(); 1474 broadcastIntentAction = in.readString(); 1475 tags = in.readStringArray(); 1476 } 1477 1478 /** 1479 * Save a ViolationInfo instance to a parcel. 1480 */ 1481 public void writeToParcel(Parcel dest, int flags) { 1482 crashInfo.writeToParcel(dest, flags); 1483 dest.writeInt(policy); 1484 dest.writeInt(durationMillis); 1485 dest.writeInt(violationNumThisLoop); 1486 dest.writeInt(numAnimationsRunning); 1487 dest.writeLong(violationUptimeMillis); 1488 dest.writeString(broadcastIntentAction); 1489 dest.writeStringArray(tags); 1490 } 1491 1492 1493 /** 1494 * Dump a ViolationInfo instance to a Printer. 1495 */ 1496 public void dump(Printer pw, String prefix) { 1497 crashInfo.dump(pw, prefix); 1498 pw.println(prefix + "policy: " + policy); 1499 if (durationMillis != -1) { 1500 pw.println(prefix + "durationMillis: " + durationMillis); 1501 } 1502 if (violationNumThisLoop != 0) { 1503 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop); 1504 } 1505 if (numAnimationsRunning != 0) { 1506 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning); 1507 } 1508 pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis); 1509 if (broadcastIntentAction != null) { 1510 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction); 1511 } 1512 if (tags != null) { 1513 int index = 0; 1514 for (String tag : tags) { 1515 pw.println(prefix + "tag[" + (index++) + "]: " + tag); 1516 } 1517 } 1518 } 1519 1520 } 1521} 1522