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