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