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