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