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