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