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