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