79 | *
This catches disk and network access on the main thread, as 80 | * well as leaked SQLite cursors and unclosed resources. This is 81 | * simply a wrapper around {@link #setVmPolicy} and {@link 82 | * #setThreadPolicy}. 83 | */ 84 | public static void enableDefaults() { 85 | StrictMode.enableDefaults(); 86 | } 87 | 88 | /** 89 | * Returns the current thread's policy. 90 | * 91 | * @see StrictMode#getThreadPolicy() 92 | */ 93 | @NonNull 94 | public static StrictMode.ThreadPolicy getThreadPolicy() { 95 | return StrictMode.getThreadPolicy(); 96 | } 97 | 98 | /** 99 | * Gets the current VM policy. 100 | */ 101 | @NonNull 102 | public static StrictMode.VmPolicy getVmPolicy() { 103 | return StrictMode.getVmPolicy(); 104 | } 105 | 106 | /** 107 | * For code to note that it's slow. This is a no-op unless the 108 | * current thread's {@link android.os.StrictMode.ThreadPolicy} has 109 | * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls} 110 | * enabled. 111 | * 112 | * @param name Short string for the exception stack trace that's 113 | * built if when this fires. 114 | * @see StrictModeCompat#noteSlowCall(String, Object...) 115 | * @see StrictModeCompat#noteSlowCall(Locale, String, Object...) 116 | */ 117 | public static void noteSlowCall(@NonNull String name) { 118 | StrictMode.noteSlowCall(name); 119 | } 120 | 121 | /** 122 | * For code to note that it's slow. This is a no-op unless the 123 | * current thread's {@link android.os.StrictMode.ThreadPolicy} has 124 | * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls} 125 | * enabled. 126 | * 127 | * @param message Short formatting string for the exception stack trace that's 128 | * built if when this fires. 129 | * @param args Arguments referenced by the format specifiers in the format string 130 | * @see StrictModeCompat#noteSlowCall(String) 131 | * @see StrictModeCompat#noteSlowCall(Locale, String, Object...) 132 | */ 133 | public static void noteSlowCall(@NonNull String message, @NonNull Object... args) { 134 | StrictMode.noteSlowCall(String.format(message, args)); 135 | } 136 | 137 | /** 138 | * For code to note that it's slow. This is a no-op unless the 139 | * current thread's {@link android.os.StrictMode.ThreadPolicy} has 140 | * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls} 141 | * enabled. 142 | * 143 | * @param locale The locale to apply during formatting 144 | * @param message Short formatting string for the exception stack trace that's 145 | * built if when this fires. 146 | * @param args Arguments referenced by the format specifiers in the format string 147 | * @see StrictModeCompat#noteSlowCall(String) 148 | * @see StrictModeCompat#noteSlowCall(String, Object...) 149 | */ 150 | public static void noteSlowCall(@Nullable Locale locale, @NonNull String message, @NonNull Object... args) { 151 | if (locale == null) { 152 | StrictMode.noteSlowCall(String.format(message, args)); 153 | } else { 154 | StrictMode.noteSlowCall(String.format(locale, message, args)); 155 | } 156 | } 157 | 158 | /** 159 | * Sets the policy for what actions on the current thread should 160 | * be detected, as well as the penalty if such actions occur. 161 | *
162 | *
Internally this sets a thread-local variable which is 163 | * propagated across cross-process IPC calls, meaning you can 164 | * catch violations when a system service or another process 165 | * accesses the disk or network on your behalf. 166 | * 167 | * @param policy the policy to put into place 168 | */ 169 | public static void setThreadPolicy(@NonNull StrictMode.ThreadPolicy policy) { 170 | StrictMode.setThreadPolicy(policy); 171 | } 172 | 173 | /** 174 | * Sets the policy for what actions in the VM process (on any 175 | * thread) should be detected, as well as the penalty if such 176 | * actions occur. 177 | * 178 | * @param policy the policy to put into place 179 | */ 180 | public static void setVmPolicy(@NonNull StrictMode.VmPolicy policy) { 181 | StrictMode.setVmPolicy(policy); 182 | } 183 | 184 | /** 185 | * Set Thread and VM policies in one method. 186 | * 187 | * @param threadPolicy the thread policy to put into place 188 | * @param vmPolicy the vm policy to put into place 189 | */ 190 | public static void setPolicies( 191 | @NonNull StrictMode.ThreadPolicy threadPolicy, 192 | @NonNull StrictMode.VmPolicy vmPolicy 193 | ) { 194 | setThreadPolicy(threadPolicy); 195 | setVmPolicy(vmPolicy); 196 | } 197 | 198 | /** 199 | * When {@link StrictMode.VmPolicy.Builder#penaltyListener(Executor, StrictMode.OnVmViolationListener)} is enabled, 200 | * the listener is called on the provided executor when a VM violation occurs. 201 | */ 202 | public interface OnVmViolationListener { 203 | 204 | /** 205 | * Called on a VM policy violation. 206 | */ 207 | @TargetApi(Build.VERSION_CODES.O) 208 | void onVmViolation(@NonNull Violation violation); 209 | } 210 | 211 | /** 212 | * When {@link StrictMode.ThreadPolicy.Builder#penaltyListener(Executor, StrictMode.OnThreadViolationListener)} is enabled, 213 | * the listener is called on the provided executor when a Thread violation occurs. 214 | */ 215 | public interface OnThreadViolationListener { 216 | 217 | /** 218 | * Called on a thread policy violation. 219 | */ 220 | @TargetApi(Build.VERSION_CODES.O) 221 | void onThreadViolation(@NonNull Violation violation); 222 | } 223 | 224 | public static final class ThreadPolicy { 225 | 226 | private ThreadPolicy() { 227 | } 228 | 229 | public static final class Builder { 230 | 231 | @NonNull 232 | private final BuilderImpl mBuilder; 233 | 234 | public Builder() { 235 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 236 | mBuilder = new V28BuilderImpl(); 237 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 238 | mBuilder = new V26BuilderImpl(); 239 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 240 | mBuilder = new V23BuilderImpl(); 241 | } else { 242 | mBuilder = new V14BuilderImpl(); 243 | } 244 | } 245 | 246 | public Builder(@NonNull StrictMode.ThreadPolicy policy) { 247 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 248 | mBuilder = new V28BuilderImpl(policy); 249 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 250 | mBuilder = new V26BuilderImpl(policy); 251 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 252 | mBuilder = new V23BuilderImpl(policy); 253 | } else { 254 | mBuilder = new V14BuilderImpl(policy); 255 | } 256 | } 257 | 258 | /** 259 | * Construct the ThreadPolicy instance. 260 | *
261 | *
Note: if no penalties are enabled before calling
262 | * build, {@link #penaltyLog} is implicitly
263 | * set.
264 | */
265 | public StrictMode.ThreadPolicy build() {
266 | return mBuilder.build();
267 | }
268 |
269 | /**
270 | * Detect everything that's potentially suspect.
271 | */
272 | public Builder detectAll() {
273 | mBuilder.detectAll();
274 | return this;
275 | }
276 |
277 | /**
278 | * Enable detection of slow calls.
279 | */
280 | public Builder detectCustomSlowCalls() {
281 | mBuilder.detectCustomSlowCalls();
282 | return this;
283 | }
284 |
285 | /**
286 | * Enable detection of disk reads.
287 | */
288 | public Builder detectDiskReads() {
289 | mBuilder.detectDiskReads();
290 | return this;
291 | }
292 |
293 | /**
294 | * Enable detection of disk writes.
295 | */
296 | public Builder detectDiskWrites() {
297 | mBuilder.detectDiskWrites();
298 | return this;
299 | }
300 |
301 | /**
302 | * Enable detection of network operations.
303 | */
304 | public Builder detectNetwork() {
305 | mBuilder.detectNetwork();
306 | return this;
307 | }
308 |
309 | /**
310 | * Enables detection of mismatches between defined resource types
311 | * and getter calls.
312 | *
313 | * This helps detect accidental type mismatches and potentially 314 | * expensive type conversions when obtaining typed resources. 315 | *
316 | * For example, a strict mode violation would be thrown when 317 | * calling {@link TypedArray#getInt(int, int)} 318 | * on an index that contains a String-type resource. If the string 319 | * value can be parsed as an integer, this method call will return 320 | * a value without crashing; however, the developer should format 321 | * the resource as an integer to avoid unnecessary type conversion. 322 | */ 323 | public Builder detectResourceMismatches() { 324 | mBuilder.detectResourceMismatches(); 325 | return this; 326 | } 327 | 328 | /** 329 | * Crash the whole process on violation. This penalty runs at 330 | * the end of all enabled penalties so you'll still get 331 | * see logging or other violations before the process dies. 332 | *
333 | *
Unlike {@link #penaltyDeathOnNetwork}, this applies 334 | * to disk reads, disk writes, and network usage if their 335 | * corresponding detect flags are set. 336 | */ 337 | public Builder penaltyDeath() { 338 | mBuilder.penaltyDeath(); 339 | return this; 340 | } 341 | 342 | /** 343 | * Crash the whole process on any network usage. Unlike 344 | * {@link #penaltyDeath}, this penalty runs 345 | * before anything else. You must still have 346 | * called {@link #detectNetwork} to enable this. 347 | *
348 | *
In the Honeycomb or later SDKs, this is on by default. 349 | */ 350 | public Builder penaltyDeathOnNetwork() { 351 | mBuilder.penaltyDeathOnNetwork(); 352 | return this; 353 | } 354 | 355 | /** 356 | * Show an annoying dialog to the developer on detected 357 | * violations, rate-limited to be only a little annoying. 358 | */ 359 | public Builder penaltyDialog() { 360 | mBuilder.penaltyDialog(); 361 | return this; 362 | } 363 | 364 | /** 365 | * Enable detected violations log a stacktrace and timing data 366 | * to the {@link DropBoxManager DropBox} on policy 367 | * violation. Intended mostly for platform integrators doing 368 | * beta user field data collection. 369 | */ 370 | public Builder penaltyDropBox() { 371 | mBuilder.penaltyDropBox(); 372 | return this; 373 | } 374 | 375 | /** 376 | * Flash the screen during a violation. 377 | */ 378 | public Builder penaltyFlashScreen() { 379 | mBuilder.penaltyFlashScreen(); 380 | return this; 381 | } 382 | 383 | /** 384 | * Log detected violations to the system log. 385 | */ 386 | public Builder penaltyLog() { 387 | mBuilder.penaltyLog(); 388 | return this; 389 | } 390 | 391 | /** 392 | * Disable the detection of everything. 393 | */ 394 | public Builder permitAll() { 395 | mBuilder.permitAll(); 396 | return this; 397 | } 398 | 399 | /** 400 | * Disable detection of slow calls. 401 | */ 402 | public Builder permitCustomSlowCalls() { 403 | mBuilder.permitCustomSlowCalls(); 404 | return this; 405 | } 406 | 407 | /** 408 | * Disable detection of disk reads. 409 | */ 410 | public Builder permitDiskReads() { 411 | mBuilder.permitDiskReads(); 412 | return this; 413 | } 414 | 415 | /** 416 | * Disable detection of disk writes. 417 | */ 418 | public Builder permitDiskWrites() { 419 | mBuilder.permitDiskWrites(); 420 | return this; 421 | } 422 | 423 | /** 424 | * Disable detection of network operations. 425 | */ 426 | public Builder permitNetwork() { 427 | mBuilder.permitNetwork(); 428 | return this; 429 | } 430 | 431 | /** 432 | * Disable detection of mismatches between defined resource types 433 | * and getter calls. 434 | */ 435 | public Builder permitResourceMismatches() { 436 | mBuilder.permitResourceMismatches(); 437 | return this; 438 | } 439 | 440 | /** 441 | * Detect unbuffered input/output operations. 442 | *
443 | * Work on {@link Build.VERSION_CODES#O} and newer. 444 | */ 445 | public Builder detectUnbufferedIo() { 446 | mBuilder.detectUnbufferedIo(); 447 | return this; 448 | } 449 | 450 | /** 451 | * Disable detection of unbuffered input/output operations. 452 | *
453 | * Work on {@link Build.VERSION_CODES#O} and newer. 454 | */ 455 | public Builder permitUnbufferedIo() { 456 | mBuilder.permitUnbufferedIo(); 457 | return this; 458 | } 459 | 460 | /** 461 | * Call {@link StrictMode.OnThreadViolationListener#onThreadViolation(Violation)} 462 | * on specified executor every violation. 463 | *
464 | * Work on {@link Build.VERSION_CODES#P} and newer. 465 | * 466 | * @param executor This value must never be null. 467 | * @param listener This value must never be null. 468 | */ 469 | public Builder penaltyListener( 470 | @NonNull Executor executor, 471 | @NonNull OnThreadViolationListener listener 472 | ) { 473 | mBuilder.penaltyListener(executor, listener); 474 | return this; 475 | } 476 | } 477 | 478 | private interface BuilderImpl { 479 | 480 | String CATEGORY = "ThreadPolicy"; 481 | 482 | StrictMode.ThreadPolicy build(); 483 | 484 | void detectAll(); 485 | 486 | void detectCustomSlowCalls(); 487 | 488 | void detectDiskReads(); 489 | 490 | void detectDiskWrites(); 491 | 492 | void detectNetwork(); 493 | 494 | void penaltyDeath(); 495 | 496 | void penaltyDeathOnNetwork(); 497 | 498 | void penaltyDialog(); 499 | 500 | void penaltyDropBox(); 501 | 502 | void penaltyFlashScreen(); 503 | 504 | void penaltyLog(); 505 | 506 | void permitAll(); 507 | 508 | void permitCustomSlowCalls(); 509 | 510 | void permitDiskReads(); 511 | 512 | void permitDiskWrites(); 513 | 514 | void permitNetwork(); 515 | 516 | // Min sdk 23 517 | void detectResourceMismatches(); 518 | 519 | // Min sdk 23 520 | void permitResourceMismatches(); 521 | 522 | // Min sdk 26 523 | void detectUnbufferedIo(); 524 | 525 | // Min sdk 26 526 | void permitUnbufferedIo(); 527 | 528 | // Min sdk 28 529 | void penaltyListener(@NonNull Executor executor, @NonNull OnThreadViolationListener listener); 530 | } 531 | 532 | private static class V14BuilderImpl implements BuilderImpl { 533 | 534 | @NonNull 535 | final StrictMode.ThreadPolicy.Builder builder; 536 | 537 | V14BuilderImpl() { 538 | this.builder = new StrictMode.ThreadPolicy.Builder(); 539 | } 540 | 541 | V14BuilderImpl(@NonNull StrictMode.ThreadPolicy policy) { 542 | this.builder = new StrictMode.ThreadPolicy.Builder(policy); 543 | } 544 | 545 | @Override 546 | public void detectCustomSlowCalls() { 547 | builder.detectCustomSlowCalls(); 548 | } 549 | 550 | @Override 551 | public void penaltyDeathOnNetwork() { 552 | builder.penaltyDeathOnNetwork(); 553 | } 554 | 555 | @Override 556 | public void penaltyFlashScreen() { 557 | builder.penaltyFlashScreen(); 558 | } 559 | 560 | @Override 561 | public void permitCustomSlowCalls() { 562 | builder.permitCustomSlowCalls(); 563 | } 564 | 565 | @Override 566 | public StrictMode.ThreadPolicy build() { 567 | return builder.build(); 568 | } 569 | 570 | @Override 571 | public void detectAll() { 572 | builder.detectAll(); 573 | } 574 | 575 | @Override 576 | public void detectDiskReads() { 577 | builder.detectDiskReads(); 578 | } 579 | 580 | @Override 581 | public void detectDiskWrites() { 582 | builder.detectDiskWrites(); 583 | } 584 | 585 | @Override 586 | public void detectNetwork() { 587 | builder.detectNetwork(); 588 | } 589 | 590 | @Override 591 | public void penaltyDeath() { 592 | builder.penaltyDeath(); 593 | } 594 | 595 | @Override 596 | public void penaltyDialog() { 597 | builder.penaltyDialog(); 598 | } 599 | 600 | @Override 601 | public void penaltyDropBox() { 602 | builder.penaltyDropBox(); 603 | } 604 | 605 | @Override 606 | public void penaltyLog() { 607 | builder.penaltyLog(); 608 | } 609 | 610 | @Override 611 | public void permitAll() { 612 | builder.permitAll(); 613 | } 614 | 615 | @Override 616 | public void permitDiskReads() { 617 | builder.permitDiskReads(); 618 | } 619 | 620 | @Override 621 | public void permitDiskWrites() { 622 | builder.permitDiskWrites(); 623 | } 624 | 625 | @Override 626 | public void permitNetwork() { 627 | builder.permitNetwork(); 628 | } 629 | 630 | // Min sdk 23 631 | @Override 632 | public void detectResourceMismatches() { 633 | Utils.logUnsupportedFeature(CATEGORY, "Resource mismatches"); 634 | } 635 | 636 | // Min sdk 23 637 | @Override 638 | public void permitResourceMismatches() { 639 | Utils.logUnsupportedFeature(CATEGORY, "Resource mismatches"); 640 | } 641 | 642 | // Min sdk 26 643 | @Override 644 | public void detectUnbufferedIo() { 645 | Utils.logUnsupportedFeature(CATEGORY, "Unbuffered IO"); 646 | } 647 | 648 | // Min sdk 26 649 | @Override 650 | public void permitUnbufferedIo() { 651 | Utils.logUnsupportedFeature(CATEGORY, "Unbuffered IO"); 652 | } 653 | 654 | // Min sdk 28 655 | @Override 656 | public void penaltyListener(@NonNull Executor executor, @NonNull OnThreadViolationListener listener) { 657 | Utils.logUnsupportedFeature(CATEGORY, "Penalty listener"); 658 | } 659 | } 660 | 661 | @TargetApi(Build.VERSION_CODES.M) 662 | private static class V23BuilderImpl extends V14BuilderImpl { 663 | 664 | V23BuilderImpl() { 665 | } 666 | 667 | V23BuilderImpl(@NonNull StrictMode.ThreadPolicy policy) { 668 | super(policy); 669 | } 670 | 671 | @Override 672 | public void detectResourceMismatches() { 673 | builder.detectResourceMismatches(); 674 | } 675 | 676 | @Override 677 | public void permitResourceMismatches() { 678 | builder.permitResourceMismatches(); 679 | } 680 | } 681 | 682 | @TargetApi(Build.VERSION_CODES.O) 683 | private static class V26BuilderImpl extends V23BuilderImpl { 684 | 685 | V26BuilderImpl() { 686 | } 687 | 688 | V26BuilderImpl(@NonNull StrictMode.ThreadPolicy policy) { 689 | super(policy); 690 | } 691 | 692 | @Override 693 | public void detectUnbufferedIo() { 694 | builder.detectUnbufferedIo(); 695 | } 696 | 697 | @Override 698 | public void permitUnbufferedIo() { 699 | builder.permitUnbufferedIo(); 700 | } 701 | } 702 | 703 | @TargetApi(Build.VERSION_CODES.P) 704 | private static class V28BuilderImpl extends V26BuilderImpl { 705 | 706 | V28BuilderImpl() { 707 | } 708 | 709 | V28BuilderImpl(@NonNull StrictMode.ThreadPolicy policy) { 710 | super(policy); 711 | } 712 | 713 | @Override 714 | public void penaltyListener( 715 | @NonNull Executor executor, 716 | @NonNull final OnThreadViolationListener listener 717 | ) { 718 | builder.penaltyListener( 719 | executor, 720 | new StrictMode.OnThreadViolationListener() { 721 | 722 | @Override 723 | public void onThreadViolation(Violation violation) { 724 | listener.onThreadViolation(violation); 725 | } 726 | } 727 | ); 728 | } 729 | } 730 | } 731 | 732 | public static final class VmPolicy { 733 | 734 | private VmPolicy() { 735 | } 736 | 737 | public static final class Builder { 738 | 739 | @NonNull 740 | private final BuilderImpl mBuilder; 741 | 742 | public Builder() { 743 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 744 | mBuilder = new V29BuilderImpl(); 745 | 746 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 747 | mBuilder = new V28BuilderImpl(); 748 | 749 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 750 | mBuilder = new V26BuilderImpl(); 751 | 752 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 753 | mBuilder = new V24BuilderImpl(); 754 | 755 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 756 | mBuilder = new V23BuilderImpl(); 757 | 758 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 759 | mBuilder = new V18BuilderImpl(); 760 | 761 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 762 | mBuilder = new V16BuilderImpl(); 763 | 764 | } else { 765 | mBuilder = new V14BuilderImpl(); 766 | } 767 | } 768 | 769 | public Builder(@NonNull StrictMode.VmPolicy policy) { 770 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 771 | mBuilder = new V29BuilderImpl(policy); 772 | 773 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 774 | mBuilder = new V28BuilderImpl(policy); 775 | 776 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 777 | mBuilder = new V26BuilderImpl(policy); 778 | 779 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 780 | mBuilder = new V24BuilderImpl(policy); 781 | 782 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 783 | mBuilder = new V23BuilderImpl(policy); 784 | 785 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 786 | mBuilder = new V18BuilderImpl(policy); 787 | 788 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 789 | mBuilder = new V16BuilderImpl(policy); 790 | 791 | } else { 792 | mBuilder = new V14BuilderImpl(policy); 793 | } 794 | } 795 | 796 | public StrictMode.VmPolicy build() { 797 | return mBuilder.build(); 798 | } 799 | 800 | /** 801 | * Detect leaks of {@link Activity} subclasses. 802 | */ 803 | public Builder detectActivityLeaks() { 804 | mBuilder.detectActivityLeaks(); 805 | return this; 806 | } 807 | 808 | /** 809 | * Detect everything that's potentially suspect. 810 | *
811 | *
In the Honeycomb release this includes leaks of 812 | * SQLite cursors, Activities, and other closable objects 813 | * but will likely expand in future releases. 814 | */ 815 | public Builder detectAll() { 816 | mBuilder.detectAll(); 817 | return this; 818 | } 819 | 820 | /** 821 | * Detect any network traffic from the calling app which is not 822 | * wrapped in SSL/TLS. This can help you detect places that your app 823 | * is inadvertently sending cleartext data across the network. 824 | *
825 | * Using {@link #penaltyDeath()} or 826 | * {@link #penaltyDeathOnCleartextNetwork()} will block further 827 | * traffic on that socket to prevent accidental data leakage, in 828 | * addition to crashing your process. 829 | *
830 | * Using {@link #penaltyDropBox()} will log the raw contents of the 831 | * packet that triggered the violation. 832 | *
833 | * This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it 834 | * may be subject to false positives, such as when STARTTLS 835 | * protocols or HTTP proxies are used. 836 | */ 837 | public Builder detectCleartextNetwork() { 838 | mBuilder.detectCleartextNetwork(); 839 | return this; 840 | } 841 | 842 | /** 843 | * Detect when this application exposes a {@code file://} 844 | * {@link Uri} to another app. 845 | *
846 | * This exposure is discouraged since the receiving app may not have 847 | * access to the shared path. For example, the receiving app may not 848 | * have requested the 849 | * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime 850 | * permission, or the platform may be sharing the 851 | * {@link Uri} across user profile boundaries. 852 | *
853 | * Instead, apps should use {@code content://} Uris so the platform 854 | * can extend temporary permission for the receiving app to access 855 | * the resource. 856 | * 857 | * @see Intent#FLAG_GRANT_READ_URI_PERMISSION 858 | */ 859 | @SuppressWarnings("JavadocReference") 860 | public Builder detectFileUriExposure() { 861 | mBuilder.detectFileUriExposure(); 862 | return this; 863 | } 864 | 865 | /** 866 | * Detect when an {@link Closeable} or other 867 | * object with a explict termination method is finalized 868 | * without having been closed. 869 | *
870 | *
You always want to explicitly close such objects to 871 | * avoid unnecessary resources leaks. 872 | */ 873 | public Builder detectLeakedClosableObjects() { 874 | mBuilder.detectLeakedClosableObjects(); 875 | return this; 876 | } 877 | 878 | /** 879 | * Detect when a {@link BroadcastReceiver} or 880 | * {@link ServiceConnection} is leaked during {@link Context} 881 | * teardown. 882 | */ 883 | public Builder detectLeakedRegistrationObjects() { 884 | mBuilder.detectLeakedRegistrationObjects(); 885 | return this; 886 | } 887 | 888 | /** 889 | * Detect when an 890 | * {@link SQLiteCursor} or other 891 | * SQLite object is finalized without having been closed. 892 | *
893 | *
You always want to explicitly close your SQLite 894 | * cursors to avoid unnecessary database contention and 895 | * temporary memory leaks. 896 | */ 897 | public Builder detectLeakedSqlLiteObjects() { 898 | mBuilder.detectLeakedSqlLiteObjects(); 899 | return this; 900 | } 901 | 902 | /** 903 | * Crashes the whole process on violation. This penalty runs at the 904 | * end of all enabled penalties so you'll still get your logging or 905 | * other violations before the process dies. 906 | */ 907 | public Builder penaltyDeath() { 908 | mBuilder.penaltyDeath(); 909 | return this; 910 | } 911 | 912 | /** 913 | * Crashes the whole process when cleartext network traffic is 914 | * detected. 915 | * 916 | * @see #detectCleartextNetwork() 917 | */ 918 | public Builder penaltyDeathOnCleartextNetwork() { 919 | mBuilder.penaltyDeathOnCleartextNetwork(); 920 | return this; 921 | } 922 | 923 | /** 924 | * Crashes the whole process when a {@code file://} 925 | * {@link Uri} is exposed beyond this app. 926 | * 927 | * @see #detectFileUriExposure() 928 | */ 929 | public Builder penaltyDeathOnFileUriExposure() { 930 | mBuilder.penaltyDeathOnFileUriExposure(); 931 | return this; 932 | } 933 | 934 | /** 935 | * Enable detected violations log a stacktrace and timing data 936 | * to the {@link DropBoxManager DropBox} on policy 937 | * violation. Intended mostly for platform integrators doing 938 | * beta user field data collection. 939 | */ 940 | public Builder penaltyDropBox() { 941 | mBuilder.penaltyDropBox(); 942 | return this; 943 | } 944 | 945 | /** 946 | * Log detected violations to the system log. 947 | */ 948 | public Builder penaltyLog() { 949 | mBuilder.penaltyLog(); 950 | return this; 951 | } 952 | 953 | /** 954 | * Set an upper bound on how many instances of a class can be in memory 955 | * at once. Helps to prevent object leaks. 956 | * 957 | * @param klass Class for what apply instances limit 958 | * @param instanceLimit Max instances count 959 | */ 960 | public Builder setClassInstanceLimit(@NonNull Class> klass, 961 | @IntRange(from = 0) int instanceLimit) { 962 | mBuilder.setClassInstanceLimit(klass, instanceLimit); 963 | return this; 964 | } 965 | 966 | /** 967 | * Detect when the calling application sends a content:// Uri to another app 968 | * without setting {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} or 969 | * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
970 | * Forgetting to include one or more of these flags 971 | * when sending an intent is typically an app bug. 972 | */ 973 | public Builder detectContentUriWithoutPermission() { 974 | mBuilder.detectContentUriWithoutPermission(); 975 | return this; 976 | } 977 | 978 | /** 979 | * Detect any sockets in the calling app which have not been tagged 980 | * using {@link android.net.TrafficStats}. 981 | * Tagging sockets can help you investigate network usage inside your app, 982 | * such as a narrowing down heavy usage to a specific library or component. 983 | *
This currently does not detect sockets created in native code. 984 | */ 985 | public Builder detectUntaggedSockets() { 986 | mBuilder.detectUntaggedSockets(); 987 | return this; 988 | } 989 | 990 | /** 991 | * Detect reflective usage of APIs that are not part of the public Android SDK. 992 | *
993 | * Note that any non-SDK APIs that this processes accesses before this detection is enabled may not be detected. 994 | * To ensure that all such API accesses are detected, you should apply this policy as early as possible after process creation. 995 | */ 996 | public Builder detectNonSdkApiUsage() { 997 | mBuilder.detectNonSdkApiUsage(); 998 | return this; 999 | } 1000 | 1001 | /** 1002 | * Call {@link StrictMode.OnVmViolationListener#onVmViolation(Violation)} on every violation. 1003 | * 1004 | * @param executor This value must never be null. 1005 | * @param listener This value must never be null. 1006 | */ 1007 | public Builder penaltyListener(@NonNull Executor executor, 1008 | @NonNull OnVmViolationListener listener) { 1009 | mBuilder.penaltyListener(executor, listener); 1010 | return this; 1011 | } 1012 | 1013 | /** 1014 | * Permit reflective usage of APIs that are not part of the public Android SDK. 1015 | *
1016 | * Note that this only affects StrictMode, the underlying runtime may continue 1017 | * to restrict or warn on access to methods that are not part of the public SDK. 1018 | */ 1019 | public Builder permitNonSdkApiUsage() { 1020 | mBuilder.permitNonSdkApiUsage(); 1021 | return this; 1022 | } 1023 | 1024 | /** 1025 | * Detect any implicit reliance on Direct Boot automatic filtering of 1026 | * {@link android.content.pm.PackageManager} values. Violations are only triggered 1027 | * when implicit calls are made while the user is locked. 1028 | *
1029 | * Apps becoming Direct Boot aware need to carefully inspect each query site 1030 | * and explicitly decide which combination of flags they want to use: 1031 | * 1032 | *
1047 | * When a user is locked, credential protected storage is unavailable, 1048 | * and files stored in these locations appear to not exist, which can result 1049 | * in subtle app bugs if they assume default behaviors or empty states. 1050 | * Instead, apps should store data needed while a user is locked 1051 | * under device protected storage areas. 1052 | */ 1053 | public Builder detectCredentialProtectedWhileLocked() { 1054 | mBuilder.detectCredentialProtectedWhileLocked(); 1055 | return this; 1056 | } 1057 | } 1058 | 1059 | private interface BuilderImpl { 1060 | 1061 | String CATEGORY = "VmPolicy"; 1062 | 1063 | StrictMode.VmPolicy build(); 1064 | 1065 | void detectActivityLeaks(); 1066 | 1067 | void detectAll(); 1068 | 1069 | // Min SDK 23 1070 | void detectCleartextNetwork(); 1071 | 1072 | // Min SDK 18 1073 | void detectFileUriExposure(); 1074 | 1075 | void detectLeakedClosableObjects(); 1076 | 1077 | // Min SDK 16 1078 | void detectLeakedRegistrationObjects(); 1079 | 1080 | void detectLeakedSqlLiteObjects(); 1081 | 1082 | void penaltyDeath(); 1083 | 1084 | // Min SDK 23 1085 | void penaltyDeathOnCleartextNetwork(); 1086 | 1087 | // Min SDK 24 1088 | void penaltyDeathOnFileUriExposure(); 1089 | 1090 | void penaltyDropBox(); 1091 | 1092 | void penaltyLog(); 1093 | 1094 | void setClassInstanceLimit(@NonNull Class> klass, @IntRange(from = 0) int instanceLimit); 1095 | 1096 | // Min SDK 26 1097 | void detectContentUriWithoutPermission(); 1098 | 1099 | // Min SDK 26 1100 | void detectUntaggedSockets(); 1101 | 1102 | // Min SDK 28 1103 | void detectNonSdkApiUsage(); 1104 | 1105 | // Min SDK 28 1106 | void penaltyListener(@NonNull Executor executor, @NonNull OnVmViolationListener listener); 1107 | 1108 | // Min SDK 28 1109 | void permitNonSdkApiUsage(); 1110 | 1111 | // Min SDK 29 1112 | void detectImplicitDirectBoot(); 1113 | 1114 | // Min SDK 29 1115 | void detectCredentialProtectedWhileLocked(); 1116 | } 1117 | 1118 | private static class V14BuilderImpl implements BuilderImpl { 1119 | 1120 | @NonNull 1121 | final StrictMode.VmPolicy.Builder mBuilder; 1122 | 1123 | V14BuilderImpl() { 1124 | mBuilder = new StrictMode.VmPolicy.Builder(); 1125 | } 1126 | 1127 | V14BuilderImpl(@NonNull StrictMode.VmPolicy policy) { 1128 | mBuilder = new StrictMode.VmPolicy.Builder(policy); 1129 | } 1130 | 1131 | @Override 1132 | public StrictMode.VmPolicy build() { 1133 | return mBuilder.build(); 1134 | } 1135 | 1136 | @Override 1137 | public void detectAll() { 1138 | mBuilder.detectAll(); 1139 | } 1140 | 1141 | @Override 1142 | public void detectCleartextNetwork() { 1143 | Utils.logUnsupportedFeature(CATEGORY, "Cleartext network"); 1144 | } 1145 | 1146 | @Override 1147 | public void detectFileUriExposure() { 1148 | Utils.logUnsupportedFeature(CATEGORY, "File uri exposure"); 1149 | } 1150 | 1151 | @Override 1152 | public void detectLeakedSqlLiteObjects() { 1153 | mBuilder.detectLeakedSqlLiteObjects(); 1154 | } 1155 | 1156 | @Override 1157 | public void detectLeakedRegistrationObjects() { 1158 | Utils.logUnsupportedFeature(CATEGORY, "Leaked registration objects"); 1159 | } 1160 | 1161 | @Override 1162 | public void penaltyDeath() { 1163 | mBuilder.penaltyDeath(); 1164 | } 1165 | 1166 | @Override 1167 | public void penaltyDeathOnCleartextNetwork() { 1168 | Utils.logUnsupportedFeature(CATEGORY, "Cleartext network"); 1169 | } 1170 | 1171 | @Override 1172 | public void penaltyDeathOnFileUriExposure() { 1173 | Utils.logUnsupportedFeature(CATEGORY, "Penalty death on file uri exposure"); 1174 | } 1175 | 1176 | @Override 1177 | public void penaltyDropBox() { 1178 | mBuilder.penaltyDropBox(); 1179 | } 1180 | 1181 | @Override 1182 | public void penaltyLog() { 1183 | mBuilder.penaltyLog(); 1184 | } 1185 | 1186 | @Override 1187 | public void detectActivityLeaks() { 1188 | mBuilder.detectActivityLeaks(); 1189 | } 1190 | 1191 | @Override 1192 | public void detectLeakedClosableObjects() { 1193 | mBuilder.detectLeakedClosableObjects(); 1194 | } 1195 | 1196 | @Override 1197 | public void setClassInstanceLimit(@NonNull Class> klass, @IntRange(from = 0) int instanceLimit) { 1198 | mBuilder.setClassInstanceLimit(klass, instanceLimit); 1199 | } 1200 | 1201 | @Override 1202 | public void detectContentUriWithoutPermission() { 1203 | Utils.logUnsupportedFeature(CATEGORY, "Content uri without permission"); 1204 | } 1205 | 1206 | @Override 1207 | public void detectUntaggedSockets() { 1208 | Utils.logUnsupportedFeature(CATEGORY, "Untagged sockets"); 1209 | } 1210 | 1211 | @Override 1212 | public void detectNonSdkApiUsage() { 1213 | Utils.logUnsupportedFeature(CATEGORY, "Non SDK api usage"); 1214 | } 1215 | 1216 | @Override 1217 | public void penaltyListener(@NonNull Executor executor, 1218 | @NonNull OnVmViolationListener listener) { 1219 | Utils.logUnsupportedFeature(CATEGORY, "Penalty listener"); 1220 | } 1221 | 1222 | @Override 1223 | public void permitNonSdkApiUsage() { 1224 | Utils.logUnsupportedFeature(CATEGORY, "Non SDK api usage"); 1225 | } 1226 | 1227 | @Override 1228 | public void detectImplicitDirectBoot() { 1229 | Utils.logUnsupportedFeature(CATEGORY, "Implicit Direct Boot"); 1230 | } 1231 | 1232 | @Override 1233 | public void detectCredentialProtectedWhileLocked() { 1234 | Utils.logUnsupportedFeature(CATEGORY, "Credential Protected While Locked"); 1235 | } 1236 | } 1237 | 1238 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 1239 | private static class V16BuilderImpl extends V14BuilderImpl { 1240 | 1241 | V16BuilderImpl() { 1242 | } 1243 | 1244 | V16BuilderImpl(@NonNull StrictMode.VmPolicy policy) { 1245 | super(policy); 1246 | } 1247 | 1248 | @Override 1249 | public void detectLeakedRegistrationObjects() { 1250 | mBuilder.detectLeakedRegistrationObjects(); 1251 | } 1252 | } 1253 | 1254 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 1255 | private static class V18BuilderImpl extends V16BuilderImpl { 1256 | 1257 | V18BuilderImpl() { 1258 | } 1259 | 1260 | V18BuilderImpl(@NonNull StrictMode.VmPolicy policy) { 1261 | super(policy); 1262 | } 1263 | 1264 | @Override 1265 | public void detectFileUriExposure() { 1266 | mBuilder.detectFileUriExposure(); 1267 | } 1268 | } 1269 | 1270 | @TargetApi(Build.VERSION_CODES.M) 1271 | private static class V23BuilderImpl extends V18BuilderImpl { 1272 | 1273 | V23BuilderImpl() { 1274 | } 1275 | 1276 | V23BuilderImpl(@NonNull StrictMode.VmPolicy policy) { 1277 | super(policy); 1278 | } 1279 | 1280 | @Override 1281 | public void detectCleartextNetwork() { 1282 | mBuilder.detectCleartextNetwork(); 1283 | } 1284 | 1285 | @Override 1286 | public void penaltyDeathOnCleartextNetwork() { 1287 | mBuilder.penaltyDeathOnCleartextNetwork(); 1288 | } 1289 | } 1290 | 1291 | @TargetApi(Build.VERSION_CODES.N) 1292 | private static class V24BuilderImpl extends V23BuilderImpl { 1293 | 1294 | V24BuilderImpl() { 1295 | } 1296 | 1297 | V24BuilderImpl(@NonNull StrictMode.VmPolicy policy) { 1298 | super(policy); 1299 | } 1300 | 1301 | @Override 1302 | public void penaltyDeathOnFileUriExposure() { 1303 | mBuilder.penaltyDeathOnFileUriExposure(); 1304 | } 1305 | } 1306 | 1307 | @TargetApi(Build.VERSION_CODES.O) 1308 | private static class V26BuilderImpl extends V24BuilderImpl { 1309 | 1310 | V26BuilderImpl() { 1311 | } 1312 | 1313 | V26BuilderImpl(@NonNull StrictMode.VmPolicy policy) { 1314 | super(policy); 1315 | } 1316 | 1317 | @Override 1318 | public void detectUntaggedSockets() { 1319 | mBuilder.detectUntaggedSockets(); 1320 | } 1321 | 1322 | @Override 1323 | public void detectContentUriWithoutPermission() { 1324 | mBuilder.detectContentUriWithoutPermission(); 1325 | } 1326 | } 1327 | 1328 | @TargetApi(Build.VERSION_CODES.P) 1329 | private static class V28BuilderImpl extends V26BuilderImpl { 1330 | 1331 | V28BuilderImpl() { 1332 | } 1333 | 1334 | V28BuilderImpl(@NonNull StrictMode.VmPolicy policy) { 1335 | super(policy); 1336 | } 1337 | 1338 | @Override 1339 | public void detectNonSdkApiUsage() { 1340 | mBuilder.detectNonSdkApiUsage(); 1341 | } 1342 | 1343 | @Override 1344 | public void permitNonSdkApiUsage() { 1345 | mBuilder.permitNonSdkApiUsage(); 1346 | } 1347 | 1348 | @Override 1349 | public void penaltyListener( 1350 | @NonNull Executor executor, 1351 | @NonNull final OnVmViolationListener listener 1352 | ) { 1353 | mBuilder.penaltyListener( 1354 | executor, 1355 | new StrictMode.OnVmViolationListener() { 1356 | 1357 | @Override 1358 | public void onVmViolation(Violation violation) { 1359 | listener.onVmViolation(violation); 1360 | } 1361 | } 1362 | ); 1363 | } 1364 | } 1365 | 1366 | @TargetApi(Build.VERSION_CODES.Q) 1367 | private static class V29BuilderImpl extends V26BuilderImpl { 1368 | 1369 | V29BuilderImpl() { 1370 | } 1371 | 1372 | V29BuilderImpl(@NonNull StrictMode.VmPolicy policy) { 1373 | super(policy); 1374 | } 1375 | 1376 | @Override 1377 | public void detectImplicitDirectBoot() { 1378 | mBuilder.detectImplicitDirectBoot(); 1379 | } 1380 | 1381 | @Override 1382 | public void detectCredentialProtectedWhileLocked() { 1383 | mBuilder.detectCredentialProtectedWhileLocked(); 1384 | } 1385 | } 1386 | } 1387 | } 1388 | --------------------------------------------------------------------------------