StrictMode.java revision d82a743002cacd9eb073b09929dab4930213e97d
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.os;
17
18import android.animation.ValueAnimator;
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.annotation.TestApi;
22import android.app.ActivityManager;
23import android.app.ActivityThread;
24import android.app.IActivityManager;
25import android.content.BroadcastReceiver;
26import android.content.Context;
27import android.content.Intent;
28import android.content.ServiceConnection;
29import android.content.pm.ApplicationInfo;
30import android.net.TrafficStats;
31import android.net.Uri;
32import android.os.strictmode.CleartextNetworkViolation;
33import android.os.strictmode.ContentUriWithoutPermissionViolation;
34import android.os.strictmode.CustomViolation;
35import android.os.strictmode.DiskReadViolation;
36import android.os.strictmode.DiskWriteViolation;
37import android.os.strictmode.FileUriExposedViolation;
38import android.os.strictmode.InstanceCountViolation;
39import android.os.strictmode.IntentReceiverLeakedViolation;
40import android.os.strictmode.LeakedClosableViolation;
41import android.os.strictmode.NetworkViolation;
42import android.os.strictmode.NonSdkApiUsedViolation;
43import android.os.strictmode.ResourceMismatchViolation;
44import android.os.strictmode.ServiceConnectionLeakedViolation;
45import android.os.strictmode.SqliteObjectLeakedViolation;
46import android.os.strictmode.UnbufferedIoViolation;
47import android.os.strictmode.UntaggedSocketViolation;
48import android.os.strictmode.Violation;
49import android.os.strictmode.WebViewMethodCalledOnWrongThreadViolation;
50import android.util.ArrayMap;
51import android.util.Log;
52import android.util.Printer;
53import android.util.Singleton;
54import android.util.Slog;
55import android.view.IWindowManager;
56
57import com.android.internal.annotations.GuardedBy;
58import com.android.internal.os.BackgroundThread;
59import com.android.internal.os.RuntimeInit;
60import com.android.internal.util.FastPrintWriter;
61import com.android.internal.util.HexDump;
62
63import dalvik.system.BlockGuard;
64import dalvik.system.CloseGuard;
65import dalvik.system.VMDebug;
66import dalvik.system.VMRuntime;
67
68import java.io.PrintWriter;
69import java.io.StringWriter;
70import java.net.InetAddress;
71import java.net.UnknownHostException;
72import java.util.ArrayDeque;
73import java.util.ArrayList;
74import java.util.Arrays;
75import java.util.Deque;
76import java.util.HashMap;
77import java.util.concurrent.Executor;
78import java.util.concurrent.RejectedExecutionException;
79import java.util.concurrent.atomic.AtomicInteger;
80import java.util.function.Consumer;
81
82/**
83 * StrictMode is a developer tool which detects things you might be doing by accident and brings
84 * them to your attention so you can fix them.
85 *
86 * <p>StrictMode is most commonly used to catch accidental disk or network access on the
87 * application's main thread, where UI operations are received and animations take place. Keeping
88 * disk and network operations off the main thread makes for much smoother, more responsive
89 * applications. By keeping your application's main thread responsive, you also prevent <a
90 * href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a> from being shown to
91 * users.
92 *
93 * <p class="note">Note that even though an Android device's disk is often on flash memory, many
94 * devices run a filesystem on top of that memory with very limited concurrency. It's often the case
95 * that almost all disk accesses are fast, but may in individual cases be dramatically slower when
96 * certain I/O is happening in the background from other processes. If possible, it's best to assume
97 * that such things are not fast.
98 *
99 * <p>Example code to enable from early in your {@link android.app.Application}, {@link
100 * android.app.Activity}, or other application component's {@link android.app.Application#onCreate}
101 * method:
102 *
103 * <pre>
104 * public void onCreate() {
105 *     if (DEVELOPER_MODE) {
106 *         StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
107 *                 .detectDiskReads()
108 *                 .detectDiskWrites()
109 *                 .detectNetwork()   // or .detectAll() for all detectable problems
110 *                 .penaltyLog()
111 *                 .build());
112 *         StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
113 *                 .detectLeakedSqlLiteObjects()
114 *                 .detectLeakedClosableObjects()
115 *                 .penaltyLog()
116 *                 .penaltyDeath()
117 *                 .build());
118 *     }
119 *     super.onCreate();
120 * }
121 * </pre>
122 *
123 * <p>You can decide what should happen when a violation is detected. For example, using {@link
124 * ThreadPolicy.Builder#penaltyLog} you can watch the output of <code>adb logcat</code> while you
125 * use your application to see the violations as they happen.
126 *
127 * <p>If you find violations that you feel are problematic, there are a variety of tools to help
128 * solve them: threads, {@link android.os.Handler}, {@link android.os.AsyncTask}, {@link
129 * android.app.IntentService}, etc. But don't feel compelled to fix everything that StrictMode
130 * finds. In particular, many cases of disk access are often necessary during the normal activity
131 * lifecycle. Use StrictMode to find things you did by accident. Network requests on the UI thread
132 * are almost always a problem, though.
133 *
134 * <p class="note">StrictMode is not a security mechanism and is not guaranteed to find all disk or
135 * network accesses. While it does propagate its state across process boundaries when doing {@link
136 * android.os.Binder} calls, it's still ultimately a best effort mechanism. Notably, disk or network
137 * access from JNI calls won't necessarily trigger it. Future versions of Android may catch more (or
138 * fewer) operations, so you should never leave StrictMode enabled in applications distributed on
139 * Google Play.
140 */
141public final class StrictMode {
142    private static final String TAG = "StrictMode";
143    private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
144
145    /**
146     * Boolean system property to disable strict mode checks outright. Set this to 'true' to force
147     * disable; 'false' has no effect on other enable/disable policy.
148     *
149     * @hide
150     */
151    public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
152
153    /**
154     * The boolean system property to control screen flashes on violations.
155     *
156     * @hide
157     */
158    public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
159
160    /**
161     * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK} in {@link
162     * VmPolicy.Builder#detectAll()}. Apps can still always opt-into detection using {@link
163     * VmPolicy.Builder#detectCleartextNetwork()}.
164     */
165    private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.clear";
166
167    /**
168     * Quick feature-flag that can be used to disable the defaults provided by {@link
169     * #initThreadDefaults(ApplicationInfo)} and {@link #initVmDefaults(ApplicationInfo)}.
170     */
171    private static final boolean DISABLE = false;
172
173    // Only apply VM penalties for the same violation at this interval.
174    private static final long MIN_VM_INTERVAL_MS = 1000;
175
176    // Only log a duplicate stack trace to the logs every second.
177    private static final long MIN_LOG_INTERVAL_MS = 1000;
178
179    // Only show an annoying dialog at most every 30 seconds
180    private static final long MIN_DIALOG_INTERVAL_MS = 30000;
181
182    // How many Span tags (e.g. animations) to report.
183    private static final int MAX_SPAN_TAGS = 20;
184
185    // How many offending stacks to keep track of (and time) per loop
186    // of the Looper.
187    private static final int MAX_OFFENSES_PER_LOOP = 10;
188
189    // Byte 1: Thread-policy
190
191    /** @hide */
192    @TestApi public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy
193
194    /** @hide */
195    @TestApi public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy
196
197    /** @hide */
198    @TestApi public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy
199
200    /**
201     * For StrictMode.noteSlowCall()
202     *
203     * @hide
204     */
205    @TestApi public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy
206
207    /**
208     * For StrictMode.noteResourceMismatch()
209     *
210     * @hide
211     */
212    @TestApi public static final int DETECT_RESOURCE_MISMATCH = 0x10; // for ThreadPolicy
213
214    /** @hide */
215    @TestApi public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy
216
217    private static final int ALL_THREAD_DETECT_BITS =
218            DETECT_DISK_WRITE
219                    | DETECT_DISK_READ
220                    | DETECT_NETWORK
221                    | DETECT_CUSTOM
222                    | DETECT_RESOURCE_MISMATCH
223                    | DETECT_UNBUFFERED_IO;
224
225    // Byte 2: Process-policy
226
227    /**
228     * Note, a "VM_" bit, not thread.
229     *
230     * @hide
231     */
232    @TestApi public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8; // for VmPolicy
233
234    /**
235     * Note, a "VM_" bit, not thread.
236     *
237     * @hide
238     */
239    @TestApi public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8; // for VmPolicy
240
241    /**
242     * Note, a "VM_" bit, not thread.
243     *
244     * @hide
245     */
246    @TestApi public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8; // for VmPolicy
247
248    /** @hide */
249    @TestApi public static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8; // for VmPolicy
250
251    /** @hide */
252    @TestApi public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8; // for VmPolicy
253
254    /** @hide */
255    @TestApi public static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8; // for VmPolicy
256
257    /** @hide */
258    @TestApi public static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8; // for VmPolicy
259
260    /** @hide */
261    @TestApi
262    public static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy
263
264    /** @hide */
265    @TestApi public static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy
266
267    /** @hide */
268    @TestApi public static final int DETECT_VM_NON_SDK_API_USAGE = 0x40 << 24; // for VmPolicy
269
270    private static final int ALL_VM_DETECT_BITS =
271            DETECT_VM_CURSOR_LEAKS
272                    | DETECT_VM_CLOSABLE_LEAKS
273                    | DETECT_VM_ACTIVITY_LEAKS
274                    | DETECT_VM_INSTANCE_LEAKS
275                    | DETECT_VM_REGISTRATION_LEAKS
276                    | DETECT_VM_FILE_URI_EXPOSURE
277                    | DETECT_VM_CLEARTEXT_NETWORK
278                    | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION
279                    | DETECT_VM_UNTAGGED_SOCKET
280                    | DETECT_VM_NON_SDK_API_USAGE;
281
282
283    // Byte 3: Penalty
284
285    /** {@hide} */
286    public static final int PENALTY_LOG = 0x01 << 16; // normal android.util.Log
287    /** {@hide} */
288    public static final int PENALTY_DIALOG = 0x02 << 16;
289    /** {@hide} */
290    public static final int PENALTY_DEATH = 0x04 << 16;
291    /** {@hide} */
292    public static final int PENALTY_FLASH = 0x10 << 16;
293    /** {@hide} */
294    public static final int PENALTY_DROPBOX = 0x20 << 16;
295
296    /**
297     * Non-public penalty mode which overrides all the other penalty bits and signals that we're in
298     * a Binder call and we should ignore the other penalty bits and instead serialize back all our
299     * offending stack traces to the caller to ultimately handle in the originating process.
300     *
301     * <p>This must be kept in sync with the constant in libs/binder/Parcel.cpp
302     *
303     * @hide
304     */
305    public static final int PENALTY_GATHER = 0x40 << 16;
306
307    // Byte 4: Special cases
308
309    /**
310     * Death when network traffic is detected on main thread.
311     *
312     * @hide
313     */
314    public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
315
316    /**
317     * Death when cleartext network traffic is detected.
318     *
319     * @hide
320     */
321    public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
322
323    /**
324     * Death when file exposure is detected.
325     *
326     * @hide
327     */
328    public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
329
330    // CAUTION: we started stealing the top bits of Byte 4 for VM above
331
332    /** Mask of all the penalty bits valid for thread policies. */
333    private static final int THREAD_PENALTY_MASK =
334            PENALTY_LOG
335                    | PENALTY_DIALOG
336                    | PENALTY_DEATH
337                    | PENALTY_DROPBOX
338                    | PENALTY_GATHER
339                    | PENALTY_DEATH_ON_NETWORK
340                    | PENALTY_FLASH;
341
342    /** Mask of all the penalty bits valid for VM policies. */
343    private static final int VM_PENALTY_MASK =
344            PENALTY_LOG
345                    | PENALTY_DEATH
346                    | PENALTY_DROPBOX
347                    | PENALTY_DEATH_ON_CLEARTEXT_NETWORK
348                    | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
349
350    /** {@hide} */
351    public static final int NETWORK_POLICY_ACCEPT = 0;
352    /** {@hide} */
353    public static final int NETWORK_POLICY_LOG = 1;
354    /** {@hide} */
355    public static final int NETWORK_POLICY_REJECT = 2;
356
357    // TODO: wrap in some ImmutableHashMap thing.
358    // Note: must be before static initialization of sVmPolicy.
359    private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP =
360            new HashMap<Class, Integer>();
361
362    /** The current VmPolicy in effect. */
363    private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
364
365    /** {@hide} */
366    @TestApi
367    public interface ViolationLogger {
368
369        /** Called when penaltyLog is enabled and a violation needs logging. */
370        void log(ViolationInfo info);
371    }
372
373    private static final ViolationLogger LOGCAT_LOGGER =
374            info -> {
375                String msg;
376                if (info.durationMillis != -1) {
377                    msg = "StrictMode policy violation; ~duration=" + info.durationMillis + " ms:";
378                } else {
379                    msg = "StrictMode policy violation:";
380                }
381                Log.d(TAG, msg + " " + info.getStackTrace());
382            };
383
384    private static volatile ViolationLogger sLogger = LOGCAT_LOGGER;
385
386    private static final ThreadLocal<OnThreadViolationListener> sThreadViolationListener =
387            new ThreadLocal<>();
388    private static final ThreadLocal<Executor> sThreadViolationExecutor = new ThreadLocal<>();
389
390    /**
391     * When #{@link ThreadPolicy.Builder#penaltyListener} is enabled, the listener is called on the
392     * provided executor when a Thread violation occurs.
393     */
394    public interface OnThreadViolationListener {
395        /** Called on a thread policy violation. */
396        void onThreadViolation(Violation v);
397    }
398
399    /**
400     * When #{@link VmPolicy.Builder#penaltyListener} is enabled, the listener is called on the
401     * provided executor when a VM violation occurs.
402     */
403    public interface OnVmViolationListener {
404        /** Called on a VM policy violation. */
405        void onVmViolation(Violation v);
406    }
407
408    /** {@hide} */
409    @TestApi
410    public static void setViolationLogger(ViolationLogger listener) {
411        if (listener == null) {
412            listener = LOGCAT_LOGGER;
413        }
414        sLogger = listener;
415    }
416
417    /**
418     * The number of threads trying to do an async dropbox write. Just to limit ourselves out of
419     * paranoia.
420     */
421    private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
422
423    /**
424     * Callback supplied to dalvik / libcore to get informed of usages of java API that are not
425     * a part of the public SDK.
426     */
427    private static final Consumer<String> sNonSdkApiUsageConsumer =
428            message -> onVmPolicyViolation(new NonSdkApiUsedViolation(message));
429
430    private StrictMode() {}
431
432    /**
433     * {@link StrictMode} policy applied to a certain thread.
434     *
435     * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy can be retrieved
436     * with {@link #getThreadPolicy}.
437     *
438     * <p>Note that multiple penalties may be provided and they're run in order from least to most
439     * severe (logging before process death, for example). There's currently no mechanism to choose
440     * different penalties for different detected actions.
441     */
442    public static final class ThreadPolicy {
443        /** The default, lax policy which doesn't catch anything. */
444        public static final ThreadPolicy LAX = new ThreadPolicy(0, null, null);
445
446        final int mask;
447        final OnThreadViolationListener mListener;
448        final Executor mCallbackExecutor;
449
450        private ThreadPolicy(int mask, OnThreadViolationListener listener, Executor executor) {
451            this.mask = mask;
452            mListener = listener;
453            mCallbackExecutor = executor;
454        }
455
456        @Override
457        public String toString() {
458            return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
459        }
460
461        /**
462         * Creates {@link ThreadPolicy} instances. Methods whose names start with {@code detect}
463         * specify what problems we should look for. Methods whose names start with {@code penalty}
464         * specify what we should do when we detect a problem.
465         *
466         * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently
467         * order is insignificant: all penalties apply to all detected problems.
468         *
469         * <p>For example, detect everything and log anything that's found:
470         *
471         * <pre>
472         * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
473         *     .detectAll()
474         *     .penaltyLog()
475         *     .build();
476         * StrictMode.setThreadPolicy(policy);
477         * </pre>
478         */
479        public static final class Builder {
480            private int mMask = 0;
481            private OnThreadViolationListener mListener;
482            private Executor mExecutor;
483
484            /**
485             * Create a Builder that detects nothing and has no violations. (but note that {@link
486             * #build} will default to enabling {@link #penaltyLog} if no other penalties are
487             * specified)
488             */
489            public Builder() {
490                mMask = 0;
491            }
492
493            /** Initialize a Builder from an existing ThreadPolicy. */
494            public Builder(ThreadPolicy policy) {
495                mMask = policy.mask;
496                mListener = policy.mListener;
497                mExecutor = policy.mCallbackExecutor;
498            }
499
500            /**
501             * Detect everything that's potentially suspect.
502             *
503             * <p>As of the Gingerbread release this includes network and disk operations but will
504             * likely expand in future releases.
505             */
506            public Builder detectAll() {
507                detectDiskReads();
508                detectDiskWrites();
509                detectNetwork();
510
511                final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
512                if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
513                    detectCustomSlowCalls();
514                }
515                if (targetSdk >= Build.VERSION_CODES.M) {
516                    detectResourceMismatches();
517                }
518                if (targetSdk >= Build.VERSION_CODES.O) {
519                    detectUnbufferedIo();
520                }
521                return this;
522            }
523
524            /** Disable the detection of everything. */
525            public Builder permitAll() {
526                return disable(ALL_THREAD_DETECT_BITS);
527            }
528
529            /** Enable detection of network operations. */
530            public Builder detectNetwork() {
531                return enable(DETECT_NETWORK);
532            }
533
534            /** Disable detection of network operations. */
535            public Builder permitNetwork() {
536                return disable(DETECT_NETWORK);
537            }
538
539            /** Enable detection of disk reads. */
540            public Builder detectDiskReads() {
541                return enable(DETECT_DISK_READ);
542            }
543
544            /** Disable detection of disk reads. */
545            public Builder permitDiskReads() {
546                return disable(DETECT_DISK_READ);
547            }
548
549            /** Enable detection of slow calls. */
550            public Builder detectCustomSlowCalls() {
551                return enable(DETECT_CUSTOM);
552            }
553
554            /** Disable detection of slow calls. */
555            public Builder permitCustomSlowCalls() {
556                return disable(DETECT_CUSTOM);
557            }
558
559            /** Disable detection of mismatches between defined resource types and getter calls. */
560            public Builder permitResourceMismatches() {
561                return disable(DETECT_RESOURCE_MISMATCH);
562            }
563
564            /** Detect unbuffered input/output operations. */
565            public Builder detectUnbufferedIo() {
566                return enable(DETECT_UNBUFFERED_IO);
567            }
568
569            /** Disable detection of unbuffered input/output operations. */
570            public Builder permitUnbufferedIo() {
571                return disable(DETECT_UNBUFFERED_IO);
572            }
573
574            /**
575             * Enables detection of mismatches between defined resource types and getter calls.
576             *
577             * <p>This helps detect accidental type mismatches and potentially expensive type
578             * conversions when obtaining typed resources.
579             *
580             * <p>For example, a strict mode violation would be thrown when calling {@link
581             * android.content.res.TypedArray#getInt(int, int)} on an index that contains a
582             * String-type resource. If the string value can be parsed as an integer, this method
583             * call will return a value without crashing; however, the developer should format the
584             * resource as an integer to avoid unnecessary type conversion.
585             */
586            public Builder detectResourceMismatches() {
587                return enable(DETECT_RESOURCE_MISMATCH);
588            }
589
590            /** Enable detection of disk writes. */
591            public Builder detectDiskWrites() {
592                return enable(DETECT_DISK_WRITE);
593            }
594
595            /** Disable detection of disk writes. */
596            public Builder permitDiskWrites() {
597                return disable(DETECT_DISK_WRITE);
598            }
599
600            /**
601             * Show an annoying dialog to the developer on detected violations, rate-limited to be
602             * only a little annoying.
603             */
604            public Builder penaltyDialog() {
605                return enable(PENALTY_DIALOG);
606            }
607
608            /**
609             * Crash the whole process on violation. This penalty runs at the end of all enabled
610             * penalties so you'll still get see logging or other violations before the process
611             * dies.
612             *
613             * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies to disk reads, disk writes,
614             * and network usage if their corresponding detect flags are set.
615             */
616            public Builder penaltyDeath() {
617                return enable(PENALTY_DEATH);
618            }
619
620            /**
621             * Crash the whole process on any network usage. Unlike {@link #penaltyDeath}, this
622             * penalty runs <em>before</em> anything else. You must still have called {@link
623             * #detectNetwork} to enable this.
624             *
625             * <p>In the Honeycomb or later SDKs, this is on by default.
626             */
627            public Builder penaltyDeathOnNetwork() {
628                return enable(PENALTY_DEATH_ON_NETWORK);
629            }
630
631            /** Flash the screen during a violation. */
632            public Builder penaltyFlashScreen() {
633                return enable(PENALTY_FLASH);
634            }
635
636            /** Log detected violations to the system log. */
637            public Builder penaltyLog() {
638                return enable(PENALTY_LOG);
639            }
640
641            /**
642             * Enable detected violations log a stacktrace and timing data to the {@link
643             * android.os.DropBoxManager DropBox} on policy violation. Intended mostly for platform
644             * integrators doing beta user field data collection.
645             */
646            public Builder penaltyDropBox() {
647                return enable(PENALTY_DROPBOX);
648            }
649
650            /**
651             * Call #{@link OnThreadViolationListener#onThreadViolation(Violation)} on specified
652             * executor every violation.
653             */
654            public Builder penaltyListener(
655                    @NonNull Executor executor, @NonNull OnThreadViolationListener listener) {
656                if (executor == null) {
657                    throw new NullPointerException("executor must not be null");
658                }
659                mListener = listener;
660                mExecutor = executor;
661                return this;
662            }
663
664            /** @removed */
665            public Builder penaltyListener(
666                    @NonNull OnThreadViolationListener listener, @NonNull Executor executor) {
667                return penaltyListener(executor, listener);
668            }
669
670            private Builder enable(int bit) {
671                mMask |= bit;
672                return this;
673            }
674
675            private Builder disable(int bit) {
676                mMask &= ~bit;
677                return this;
678            }
679
680            /**
681             * Construct the ThreadPolicy instance.
682             *
683             * <p>Note: if no penalties are enabled before calling <code>build</code>, {@link
684             * #penaltyLog} is implicitly set.
685             */
686            public ThreadPolicy build() {
687                // If there are detection bits set but no violation bits
688                // set, enable simple logging.
689                if (mListener == null
690                        && mMask != 0
691                        && (mMask
692                                        & (PENALTY_DEATH
693                                                | PENALTY_LOG
694                                                | PENALTY_DROPBOX
695                                                | PENALTY_DIALOG))
696                                == 0) {
697                    penaltyLog();
698                }
699                return new ThreadPolicy(mMask, mListener, mExecutor);
700            }
701        }
702    }
703
704    /**
705     * {@link StrictMode} policy applied to all threads in the virtual machine's process.
706     *
707     * <p>The policy is enabled by {@link #setVmPolicy}.
708     */
709    public static final class VmPolicy {
710        /** The default, lax policy which doesn't catch anything. */
711        public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP, null, null);
712
713        final int mask;
714        final OnVmViolationListener mListener;
715        final Executor mCallbackExecutor;
716
717        // Map from class to max number of allowed instances in memory.
718        final HashMap<Class, Integer> classInstanceLimit;
719
720        private VmPolicy(
721                int mask,
722                HashMap<Class, Integer> classInstanceLimit,
723                OnVmViolationListener listener,
724                Executor executor) {
725            if (classInstanceLimit == null) {
726                throw new NullPointerException("classInstanceLimit == null");
727            }
728            this.mask = mask;
729            this.classInstanceLimit = classInstanceLimit;
730            mListener = listener;
731            mCallbackExecutor = executor;
732        }
733
734        @Override
735        public String toString() {
736            return "[StrictMode.VmPolicy; mask=" + mask + "]";
737        }
738
739        /**
740         * Creates {@link VmPolicy} instances. Methods whose names start with {@code detect} specify
741         * what problems we should look for. Methods whose names start with {@code penalty} specify
742         * what we should do when we detect a problem.
743         *
744         * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently
745         * order is insignificant: all penalties apply to all detected problems.
746         *
747         * <p>For example, detect everything and log anything that's found:
748         *
749         * <pre>
750         * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
751         *     .detectAll()
752         *     .penaltyLog()
753         *     .build();
754         * StrictMode.setVmPolicy(policy);
755         * </pre>
756         */
757        public static final class Builder {
758            private int mMask;
759            private OnVmViolationListener mListener;
760            private Executor mExecutor;
761
762            private HashMap<Class, Integer> mClassInstanceLimit; // null until needed
763            private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write
764
765            public Builder() {
766                mMask = 0;
767            }
768
769            /** Build upon an existing VmPolicy. */
770            public Builder(VmPolicy base) {
771                mMask = base.mask;
772                mClassInstanceLimitNeedCow = true;
773                mClassInstanceLimit = base.classInstanceLimit;
774                mListener = base.mListener;
775                mExecutor = base.mCallbackExecutor;
776            }
777
778            /**
779             * Set an upper bound on how many instances of a class can be in memory at once. Helps
780             * to prevent object leaks.
781             */
782            public Builder setClassInstanceLimit(Class klass, int instanceLimit) {
783                if (klass == null) {
784                    throw new NullPointerException("klass == null");
785                }
786                if (mClassInstanceLimitNeedCow) {
787                    if (mClassInstanceLimit.containsKey(klass)
788                            && mClassInstanceLimit.get(klass) == instanceLimit) {
789                        // no-op; don't break COW
790                        return this;
791                    }
792                    mClassInstanceLimitNeedCow = false;
793                    mClassInstanceLimit = (HashMap<Class, Integer>) mClassInstanceLimit.clone();
794                } else if (mClassInstanceLimit == null) {
795                    mClassInstanceLimit = new HashMap<Class, Integer>();
796                }
797                mMask |= DETECT_VM_INSTANCE_LEAKS;
798                mClassInstanceLimit.put(klass, instanceLimit);
799                return this;
800            }
801
802            /** Detect leaks of {@link android.app.Activity} subclasses. */
803            public Builder detectActivityLeaks() {
804                return enable(DETECT_VM_ACTIVITY_LEAKS);
805            }
806
807            /** @hide */
808            public Builder permitActivityLeaks() {
809                return disable(DETECT_VM_ACTIVITY_LEAKS);
810            }
811
812            /**
813             * Detect reflective usage of APIs that are not part of the public Android SDK.
814             *
815             * <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             */
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             */
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             */
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             */
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             */
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             */
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             */
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             */
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             */
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             */
964            public Builder detectUntaggedSockets() {
965                return enable(DETECT_VM_UNTAGGED_SOCKET);
966            }
967
968            /** @hide */
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             */
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             */
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             */
997            public Builder penaltyDeathOnFileUriExposure() {
998                return enable(PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
999            }
1000
1001            /** Log detected violations to the system log. */
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             */
1011            public Builder penaltyDropBox() {
1012                return enable(PENALTY_DROPBOX);
1013            }
1014
1015            /**
1016             * Call #{@link OnVmViolationListener#onVmViolation(Violation)} on every violation.
1017             */
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 */
1029            public Builder penaltyListener(
1030                    @NonNull OnVmViolationListener listener, @NonNull Executor executor) {
1031                return penaltyListener(executor, listener);
1032            }
1033
1034            private Builder enable(int bit) {
1035                mMask |= bit;
1036                return this;
1037            }
1038
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             */
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     */
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 */
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)
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
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     */
1148    public static int getThreadPolicyMask() {
1149        return BlockGuard.getThreadPolicy().getPolicyMask();
1150    }
1151
1152    /** Returns the current thread's policy. */
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     */
1173    public static ThreadPolicy allowThreadDiskWrites() {
1174        return new ThreadPolicy(
1175                allowThreadDiskWritesMask(),
1176                sThreadViolationListener.get(),
1177                sThreadViolationExecutor.get());
1178    }
1179
1180    /** @hide */
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     */
1197    public static ThreadPolicy allowThreadDiskReads() {
1198        return new ThreadPolicy(
1199                allowThreadDiskReadsMask(),
1200                sThreadViolationListener.get(),
1201                sThreadViolationExecutor.get());
1202    }
1203
1204    /** @hide */
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
1214    private static ThreadPolicy allowThreadViolations() {
1215        ThreadPolicy oldPolicy = getThreadPolicy();
1216        setThreadPolicyMask(0);
1217        return oldPolicy;
1218    }
1219
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     */
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     */
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     */
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     */
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     */
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     */
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
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
1438        public AndroidBlockGuardPolicy(final int policyMask) {
1439            mPolicyMask = policyMask;
1440        }
1441
1442        @Override
1443        public String toString() {
1444            return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
1445        }
1446
1447        // Part of BlockGuard.Policy interface:
1448        public int getPolicyMask() {
1449            return mPolicyMask;
1450        }
1451
1452        // Part of BlockGuard.Policy interface:
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:
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:
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:
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:
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:
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
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.
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)
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.
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     */
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
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 {
1785        public void report(String message, Throwable allocationSite) {
1786            onVmPolicyViolation(new LeakedClosableViolation(message, allocationSite));
1787        }
1788    }
1789
1790    /** Called from Parcel.writeNoException() */
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     */
1799    /* package */ static void clearGatheredViolations() {
1800        gatheredViolations.set(null);
1801    }
1802
1803    /** @hide */
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     */
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. */
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     */
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 */
1920    public static boolean vmSqliteObjectLeaksEnabled() {
1921        return (sVmPolicy.mask & DETECT_VM_CURSOR_LEAKS) != 0;
1922    }
1923
1924    /** @hide */
1925    public static boolean vmClosableObjectLeaksEnabled() {
1926        return (sVmPolicy.mask & DETECT_VM_CLOSABLE_LEAKS) != 0;
1927    }
1928
1929    /** @hide */
1930    public static boolean vmRegistrationLeaksEnabled() {
1931        return (sVmPolicy.mask & DETECT_VM_REGISTRATION_LEAKS) != 0;
1932    }
1933
1934    /** @hide */
1935    public static boolean vmFileUriExposureEnabled() {
1936        return (sVmPolicy.mask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
1937    }
1938
1939    /** @hide */
1940    public static boolean vmCleartextNetworkEnabled() {
1941        return (sVmPolicy.mask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
1942    }
1943
1944    /** @hide */
1945    public static boolean vmContentUriWithoutPermissionEnabled() {
1946        return (sVmPolicy.mask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
1947    }
1948
1949    /** @hide */
1950    public static boolean vmUntaggedSocketEnabled() {
1951        return (sVmPolicy.mask & DETECT_VM_UNTAGGED_SOCKET) != 0;
1952    }
1953
1954    /** @hide */
1955    public static void onSqliteObjectLeaked(String message, Throwable originStack) {
1956        onVmPolicyViolation(new SqliteObjectLeakedViolation(message, originStack));
1957    }
1958
1959    /** @hide */
1960    public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
1961        onVmPolicyViolation(new WebViewMethodCalledOnWrongThreadViolation(originStack));
1962    }
1963
1964    /** @hide */
1965    public static void onIntentReceiverLeaked(Throwable originStack) {
1966        onVmPolicyViolation(new IntentReceiverLeakedViolation(originStack));
1967    }
1968
1969    /** @hide */
1970    public static void onServiceConnectionLeaked(Throwable originStack) {
1971        onVmPolicyViolation(new ServiceConnectionLeakedViolation(originStack));
1972    }
1973
1974    /** @hide */
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 */
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 */
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 */
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 */
2030    public static void onVmPolicyViolation(Violation originStack) {
2031        onVmPolicyViolation(originStack, false);
2032    }
2033
2034    /** @hide */
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() */
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     */
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     */
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
2171        Span(ThreadSpanState threadState) {
2172            mContainerState = threadState;
2173        }
2174
2175        // Empty constructor for the NO_OP_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         */
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     */
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     */
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     */
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 */
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 */
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 */
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     */
2383    public static Object trackActivity(Object instance) {
2384        return new InstanceTracker(instance);
2385    }
2386
2387    /** @hide */
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 */
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. */
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}. */
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
2560        public String getViolationDetails() {
2561            return mViolation.getMessage();
2562        }
2563
2564        /**
2565         * Policy mask at time of violation.
2566         *
2567         * @hide
2568         */
2569        @TestApi
2570        public int getPolicyMask() {
2571            return mPolicy;
2572        }
2573
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         */
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
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
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. */
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         */
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
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. */
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
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
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
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
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