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