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