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