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