StrictMode.java revision c847aae2cfb524002f9ae3a8e329d38d6fd84e53
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.ActivityManagerNative;
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             * Disable detection of 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                }
1478                for (ViolationInfo previous : violations) {
1479                    if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
1480                        // Duplicate. Don't log.
1481                        return;
1482                    }
1483                }
1484                violations.add(info);
1485                return;
1486            }
1487
1488            // Not perfect, but fast and good enough for dup suppression.
1489            Integer crashFingerprint = info.hashCode();
1490            long lastViolationTime = 0;
1491            if (mLastViolationTime != null) {
1492                Long vtime = mLastViolationTime.get(crashFingerprint);
1493                if (vtime != null) {
1494                    lastViolationTime = vtime;
1495                }
1496            } else {
1497                mLastViolationTime = new ArrayMap<Integer, Long>(1);
1498            }
1499            long now = SystemClock.uptimeMillis();
1500            mLastViolationTime.put(crashFingerprint, now);
1501            long timeSinceLastViolationMillis = lastViolationTime == 0 ?
1502                    Long.MAX_VALUE : (now - lastViolationTime);
1503
1504            if ((info.policy & PENALTY_LOG) != 0 &&
1505                timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
1506                if (info.durationMillis != -1) {
1507                    Log.d(TAG, "StrictMode policy violation; ~duration=" +
1508                          info.durationMillis + " ms: " + info.crashInfo.stackTrace);
1509                } else {
1510                    Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
1511                }
1512            }
1513
1514            // The violationMaskSubset, passed to ActivityManager, is a
1515            // subset of the original StrictMode policy bitmask, with
1516            // only the bit violated and penalty bits to be executed
1517            // by the ActivityManagerService remaining set.
1518            int violationMaskSubset = 0;
1519
1520            if ((info.policy & PENALTY_DIALOG) != 0 &&
1521                timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
1522                violationMaskSubset |= PENALTY_DIALOG;
1523            }
1524
1525            if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
1526                violationMaskSubset |= PENALTY_DROPBOX;
1527            }
1528
1529            if (violationMaskSubset != 0) {
1530                int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1531                violationMaskSubset |= violationBit;
1532                final int savedPolicyMask = getThreadPolicyMask();
1533
1534                final boolean justDropBox = (info.policy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
1535                if (justDropBox) {
1536                    // If all we're going to ask the activity manager
1537                    // to do is dropbox it (the common case during
1538                    // platform development), we can avoid doing this
1539                    // call synchronously which Binder data suggests
1540                    // isn't always super fast, despite the implementation
1541                    // in the ActivityManager trying to be mostly async.
1542                    dropboxViolationAsync(violationMaskSubset, info);
1543                    return;
1544                }
1545
1546                // Normal synchronous call to the ActivityManager.
1547                try {
1548                    // First, remove any policy before we call into the Activity Manager,
1549                    // otherwise we'll infinite recurse as we try to log policy violations
1550                    // to disk, thus violating policy, thus requiring logging, etc...
1551                    // We restore the current policy below, in the finally block.
1552                    setThreadPolicyMask(0);
1553
1554                    ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1555                        RuntimeInit.getApplicationObject(),
1556                        violationMaskSubset,
1557                        info);
1558                } catch (RemoteException e) {
1559                    if (e instanceof DeadObjectException) {
1560                        // System process is dead; ignore
1561                    } else {
1562                        Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1563                    }
1564                } finally {
1565                    // Restore the policy.
1566                    setThreadPolicyMask(savedPolicyMask);
1567                }
1568            }
1569
1570            if ((info.policy & PENALTY_DEATH) != 0) {
1571                executeDeathPenalty(info);
1572            }
1573        }
1574    }
1575
1576    private static void executeDeathPenalty(ViolationInfo info) {
1577        int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1578        throw new StrictModeViolation(info.policy, violationBit, null);
1579    }
1580
1581    /**
1582     * In the common case, as set by conditionallyEnableDebugLogging,
1583     * we're just dropboxing any violations but not showing a dialog,
1584     * not loggging, and not killing the process.  In these cases we
1585     * don't need to do a synchronous call to the ActivityManager.
1586     * This is used by both per-thread and vm-wide violations when
1587     * applicable.
1588     */
1589    private static void dropboxViolationAsync(
1590            final int violationMaskSubset, final ViolationInfo info) {
1591        int outstanding = sDropboxCallsInFlight.incrementAndGet();
1592        if (outstanding > 20) {
1593            // What's going on?  Let's not make make the situation
1594            // worse and just not log.
1595            sDropboxCallsInFlight.decrementAndGet();
1596            return;
1597        }
1598
1599        if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1600
1601        new Thread("callActivityManagerForStrictModeDropbox") {
1602            public void run() {
1603                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1604                try {
1605                    IActivityManager am = ActivityManagerNative.getDefault();
1606                    if (am == null) {
1607                        Log.d(TAG, "No activity manager; failed to Dropbox violation.");
1608                    } else {
1609                        am.handleApplicationStrictModeViolation(
1610                            RuntimeInit.getApplicationObject(),
1611                            violationMaskSubset,
1612                            info);
1613                    }
1614                } catch (RemoteException e) {
1615                    if (e instanceof DeadObjectException) {
1616                        // System process is dead; ignore
1617                    } else {
1618                        Log.e(TAG, "RemoteException handling StrictMode violation", e);
1619                    }
1620                }
1621                int outstanding = sDropboxCallsInFlight.decrementAndGet();
1622                if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
1623            }
1624        }.start();
1625    }
1626
1627    private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
1628        public void report(String message, Throwable allocationSite) {
1629            onVmPolicyViolation(message, allocationSite);
1630        }
1631    }
1632
1633    /**
1634     * Called from Parcel.writeNoException()
1635     */
1636    /* package */ static boolean hasGatheredViolations() {
1637        return gatheredViolations.get() != null;
1638    }
1639
1640    /**
1641     * Called from Parcel.writeException(), so we drop this memory and
1642     * don't incorrectly attribute it to the wrong caller on the next
1643     * Binder call on this thread.
1644     */
1645    /* package */ static void clearGatheredViolations() {
1646        gatheredViolations.set(null);
1647    }
1648
1649    /**
1650     * @hide
1651     */
1652    public static void conditionallyCheckInstanceCounts() {
1653        VmPolicy policy = getVmPolicy();
1654        int policySize = policy.classInstanceLimit.size();
1655        if (policySize == 0) {
1656            return;
1657        }
1658
1659        System.gc();
1660        System.runFinalization();
1661        System.gc();
1662
1663        // Note: classInstanceLimit is immutable, so this is lock-free
1664        // Create the classes array.
1665        Class[] classes = policy.classInstanceLimit.keySet().toArray(new Class[policySize]);
1666        long[] instanceCounts = VMDebug.countInstancesOfClasses(classes, false);
1667        for (int i = 0; i < classes.length; ++i) {
1668            Class klass = classes[i];
1669            int limit = policy.classInstanceLimit.get(klass);
1670            long instances = instanceCounts[i];
1671            if (instances > limit) {
1672                Throwable tr = new InstanceCountViolation(klass, instances, limit);
1673                onVmPolicyViolation(tr.getMessage(), tr);
1674            }
1675        }
1676    }
1677
1678    private static long sLastInstanceCountCheckMillis = 0;
1679    private static boolean sIsIdlerRegistered = false;  // guarded by StrictMode.class
1680    private static final MessageQueue.IdleHandler sProcessIdleHandler =
1681            new MessageQueue.IdleHandler() {
1682                public boolean queueIdle() {
1683                    long now = SystemClock.uptimeMillis();
1684                    if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1685                        sLastInstanceCountCheckMillis = now;
1686                        conditionallyCheckInstanceCounts();
1687                    }
1688                    return true;
1689                }
1690            };
1691
1692    /**
1693     * Sets the policy for what actions in the VM process (on any
1694     * thread) should be detected, as well as the penalty if such
1695     * actions occur.
1696     *
1697     * @param policy the policy to put into place
1698     */
1699    public static void setVmPolicy(final VmPolicy policy) {
1700        synchronized (StrictMode.class) {
1701            sVmPolicy = policy;
1702            sVmPolicyMask = policy.mask;
1703            setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
1704
1705            Looper looper = Looper.getMainLooper();
1706            if (looper != null) {
1707                MessageQueue mq = looper.mQueue;
1708                if (policy.classInstanceLimit.size() == 0 ||
1709                    (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
1710                    mq.removeIdleHandler(sProcessIdleHandler);
1711                    sIsIdlerRegistered = false;
1712                } else if (!sIsIdlerRegistered) {
1713                    mq.addIdleHandler(sProcessIdleHandler);
1714                    sIsIdlerRegistered = true;
1715                }
1716            }
1717
1718            int networkPolicy = NETWORK_POLICY_ACCEPT;
1719            if ((sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
1720                if ((sVmPolicyMask & PENALTY_DEATH) != 0
1721                        || (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
1722                    networkPolicy = NETWORK_POLICY_REJECT;
1723                } else {
1724                    networkPolicy = NETWORK_POLICY_LOG;
1725                }
1726            }
1727
1728            final INetworkManagementService netd = INetworkManagementService.Stub.asInterface(
1729                    ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
1730            if (netd != null) {
1731                try {
1732                    netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
1733                } catch (RemoteException ignored) {
1734                }
1735            } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
1736                Log.w(TAG, "Dropping requested network policy due to missing service!");
1737            }
1738        }
1739    }
1740
1741    /**
1742     * Gets the current VM policy.
1743     */
1744    public static VmPolicy getVmPolicy() {
1745        synchronized (StrictMode.class) {
1746            return sVmPolicy;
1747        }
1748    }
1749
1750    /**
1751     * Enable the recommended StrictMode defaults, with violations just being logged.
1752     *
1753     * <p>This catches disk and network access on the main thread, as
1754     * well as leaked SQLite cursors and unclosed resources.  This is
1755     * simply a wrapper around {@link #setVmPolicy} and {@link
1756     * #setThreadPolicy}.
1757     */
1758    public static void enableDefaults() {
1759        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
1760                                   .detectAll()
1761                                   .penaltyLog()
1762                                   .build());
1763        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
1764                               .detectAll()
1765                               .penaltyLog()
1766                               .build());
1767    }
1768
1769    /**
1770     * @hide
1771     */
1772    public static boolean vmSqliteObjectLeaksEnabled() {
1773        return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
1774    }
1775
1776    /**
1777     * @hide
1778     */
1779    public static boolean vmClosableObjectLeaksEnabled() {
1780        return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
1781    }
1782
1783    /**
1784     * @hide
1785     */
1786    public static boolean vmRegistrationLeaksEnabled() {
1787        return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
1788    }
1789
1790    /**
1791     * @hide
1792     */
1793    public static boolean vmFileUriExposureEnabled() {
1794        return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
1795    }
1796
1797    /**
1798     * @hide
1799     */
1800    public static boolean vmCleartextNetworkEnabled() {
1801        return (sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
1802    }
1803
1804    /**
1805     * @hide
1806     */
1807    public static void onSqliteObjectLeaked(String message, Throwable originStack) {
1808        onVmPolicyViolation(message, originStack);
1809    }
1810
1811    /**
1812     * @hide
1813     */
1814    public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
1815        onVmPolicyViolation(null, originStack);
1816    }
1817
1818    /**
1819     * @hide
1820     */
1821    public static void onIntentReceiverLeaked(Throwable originStack) {
1822        onVmPolicyViolation(null, originStack);
1823    }
1824
1825    /**
1826     * @hide
1827     */
1828    public static void onServiceConnectionLeaked(Throwable originStack) {
1829        onVmPolicyViolation(null, originStack);
1830    }
1831
1832    /**
1833     * @hide
1834     */
1835    public static void onFileUriExposed(Uri uri, String location) {
1836        final String message = uri + " exposed beyond app through " + location;
1837        if ((sVmPolicyMask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
1838            throw new FileUriExposedException(message);
1839        } else {
1840            onVmPolicyViolation(null, new Throwable(message));
1841        }
1842    }
1843
1844    /**
1845     * @hide
1846     */
1847    public static void onCleartextNetworkDetected(byte[] firstPacket) {
1848        byte[] rawAddr = null;
1849        if (firstPacket != null) {
1850            if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
1851                // IPv4
1852                rawAddr = new byte[4];
1853                System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
1854            } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
1855                // IPv6
1856                rawAddr = new byte[16];
1857                System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
1858            }
1859        }
1860
1861        final int uid = android.os.Process.myUid();
1862        String msg = "Detected cleartext network traffic from UID " + uid;
1863        if (rawAddr != null) {
1864            try {
1865                msg = "Detected cleartext network traffic from UID " + uid + " to "
1866                        + InetAddress.getByAddress(rawAddr);
1867            } catch (UnknownHostException ignored) {
1868            }
1869        }
1870
1871        final boolean forceDeath = (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
1872        onVmPolicyViolation(HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg),
1873                forceDeath);
1874    }
1875
1876    // Map from VM violation fingerprint to uptime millis.
1877    private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
1878
1879    /**
1880     * @hide
1881     */
1882    public static void onVmPolicyViolation(String message, Throwable originStack) {
1883        onVmPolicyViolation(message, originStack, false);
1884    }
1885
1886    /**
1887     * @hide
1888     */
1889    public static void onVmPolicyViolation(String message, Throwable originStack,
1890            boolean forceDeath) {
1891        final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
1892        final boolean penaltyDeath = ((sVmPolicyMask & PENALTY_DEATH) != 0) || forceDeath;
1893        final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
1894        final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicyMask);
1895
1896        // Erase stuff not relevant for process-wide violations
1897        info.numAnimationsRunning = 0;
1898        info.tags = null;
1899        info.broadcastIntentAction = null;
1900
1901        final Integer fingerprint = info.hashCode();
1902        final long now = SystemClock.uptimeMillis();
1903        long lastViolationTime = 0;
1904        long timeSinceLastViolationMillis = Long.MAX_VALUE;
1905        synchronized (sLastVmViolationTime) {
1906            if (sLastVmViolationTime.containsKey(fingerprint)) {
1907                lastViolationTime = sLastVmViolationTime.get(fingerprint);
1908                timeSinceLastViolationMillis = now - lastViolationTime;
1909            }
1910            if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
1911                sLastVmViolationTime.put(fingerprint, now);
1912            }
1913        }
1914
1915        if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
1916            Log.e(TAG, message, originStack);
1917        }
1918
1919        int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
1920
1921        if (penaltyDropbox && !penaltyDeath) {
1922            // Common case for userdebug/eng builds.  If no death and
1923            // just dropboxing, we can do the ActivityManager call
1924            // asynchronously.
1925            dropboxViolationAsync(violationMaskSubset, info);
1926            return;
1927        }
1928
1929        if (penaltyDropbox && lastViolationTime == 0) {
1930            // The violationMask, passed to ActivityManager, is a
1931            // subset of the original StrictMode policy bitmask, with
1932            // only the bit violated and penalty bits to be executed
1933            // by the ActivityManagerService remaining set.
1934            final int savedPolicyMask = getThreadPolicyMask();
1935            try {
1936                // First, remove any policy before we call into the Activity Manager,
1937                // otherwise we'll infinite recurse as we try to log policy violations
1938                // to disk, thus violating policy, thus requiring logging, etc...
1939                // We restore the current policy below, in the finally block.
1940                setThreadPolicyMask(0);
1941
1942                ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1943                    RuntimeInit.getApplicationObject(),
1944                    violationMaskSubset,
1945                    info);
1946            } catch (RemoteException e) {
1947                if (e instanceof DeadObjectException) {
1948                    // System process is dead; ignore
1949                } else {
1950                    Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1951                }
1952            } finally {
1953                // Restore the policy.
1954                setThreadPolicyMask(savedPolicyMask);
1955            }
1956        }
1957
1958        if (penaltyDeath) {
1959            System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
1960            Process.killProcess(Process.myPid());
1961            System.exit(10);
1962        }
1963    }
1964
1965    /**
1966     * Called from Parcel.writeNoException()
1967     */
1968    /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
1969        ArrayList<ViolationInfo> violations = gatheredViolations.get();
1970        if (violations == null) {
1971            p.writeInt(0);
1972        } else {
1973            // To avoid taking up too much transaction space, only include
1974            // details for the first 3 violations. Deep inside, CrashInfo
1975            // will truncate each stack trace to ~20kB.
1976            final int size = Math.min(violations.size(), 3);
1977            p.writeInt(size);
1978            for (int i = 0; i < size; i++) {
1979                violations.get(i).writeToParcel(p, 0);
1980            }
1981        }
1982        gatheredViolations.set(null);
1983    }
1984
1985    private static class LogStackTrace extends Exception {}
1986
1987    /**
1988     * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
1989     * we here read back all the encoded violations.
1990     */
1991    /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
1992        // Our own stack trace to append
1993        StringWriter sw = new StringWriter();
1994        sw.append("# via Binder call with stack:\n");
1995        PrintWriter pw = new FastPrintWriter(sw, false, 256);
1996        new LogStackTrace().printStackTrace(pw);
1997        pw.flush();
1998        String ourStack = sw.toString();
1999
2000        final int policyMask = getThreadPolicyMask();
2001        final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
2002
2003        final int size = p.readInt();
2004        for (int i = 0; i < size; i++) {
2005            final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
2006            info.crashInfo.appendStackTrace(ourStack);
2007            BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2008            if (policy instanceof AndroidBlockGuardPolicy) {
2009                ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
2010            }
2011        }
2012    }
2013
2014    /**
2015     * Called from android_util_Binder.cpp's
2016     * android_os_Parcel_enforceInterface when an incoming Binder call
2017     * requires changing the StrictMode policy mask.  The role of this
2018     * function is to ask Binder for its current (native) thread-local
2019     * policy value and synchronize it to libcore's (Java)
2020     * thread-local policy value.
2021     */
2022    private static void onBinderStrictModePolicyChange(int newPolicy) {
2023        setBlockGuardPolicy(newPolicy);
2024    }
2025
2026    /**
2027     * A tracked, critical time span.  (e.g. during an animation.)
2028     *
2029     * The object itself is a linked list node, to avoid any allocations
2030     * during rapid span entries and exits.
2031     *
2032     * @hide
2033     */
2034    public static class Span {
2035        private String mName;
2036        private long mCreateMillis;
2037        private Span mNext;
2038        private Span mPrev;  // not used when in freeList, only active
2039        private final ThreadSpanState mContainerState;
2040
2041        Span(ThreadSpanState threadState) {
2042            mContainerState = threadState;
2043        }
2044
2045        // Empty constructor for the NO_OP_SPAN
2046        protected Span() {
2047            mContainerState = null;
2048        }
2049
2050        /**
2051         * To be called when the critical span is complete (i.e. the
2052         * animation is done animating).  This can be called on any
2053         * thread (even a different one from where the animation was
2054         * taking place), but that's only a defensive implementation
2055         * measure.  It really makes no sense for you to call this on
2056         * thread other than that where you created it.
2057         *
2058         * @hide
2059         */
2060        public void finish() {
2061            ThreadSpanState state = mContainerState;
2062            synchronized (state) {
2063                if (mName == null) {
2064                    // Duplicate finish call.  Ignore.
2065                    return;
2066                }
2067
2068                // Remove ourselves from the active list.
2069                if (mPrev != null) {
2070                    mPrev.mNext = mNext;
2071                }
2072                if (mNext != null) {
2073                    mNext.mPrev = mPrev;
2074                }
2075                if (state.mActiveHead == this) {
2076                    state.mActiveHead = mNext;
2077                }
2078
2079                state.mActiveSize--;
2080
2081                if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
2082
2083                this.mCreateMillis = -1;
2084                this.mName = null;
2085                this.mPrev = null;
2086                this.mNext = null;
2087
2088                // Add ourselves to the freeList, if it's not already
2089                // too big.
2090                if (state.mFreeListSize < 5) {
2091                    this.mNext = state.mFreeListHead;
2092                    state.mFreeListHead = this;
2093                    state.mFreeListSize++;
2094                }
2095            }
2096        }
2097    }
2098
2099    // The no-op span that's used in user builds.
2100    private static final Span NO_OP_SPAN = new Span() {
2101            public void finish() {
2102                // Do nothing.
2103            }
2104        };
2105
2106    /**
2107     * Linked lists of active spans and a freelist.
2108     *
2109     * Locking notes: there's one of these structures per thread and
2110     * all members of this structure (as well as the Span nodes under
2111     * it) are guarded by the ThreadSpanState object instance.  While
2112     * in theory there'd be no locking required because it's all local
2113     * per-thread, the finish() method above is defensive against
2114     * people calling it on a different thread from where they created
2115     * the Span, hence the locking.
2116     */
2117    private static class ThreadSpanState {
2118        public Span mActiveHead;    // doubly-linked list.
2119        public int mActiveSize;
2120        public Span mFreeListHead;  // singly-linked list.  only changes at head.
2121        public int mFreeListSize;
2122    }
2123
2124    private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
2125            new ThreadLocal<ThreadSpanState>() {
2126        @Override protected ThreadSpanState initialValue() {
2127            return new ThreadSpanState();
2128        }
2129    };
2130
2131    private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
2132        protected IWindowManager create() {
2133            return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
2134        }
2135    };
2136
2137    /**
2138     * Enter a named critical span (e.g. an animation)
2139     *
2140     * <p>The name is an arbitary label (or tag) that will be applied
2141     * to any strictmode violation that happens while this span is
2142     * active.  You must call finish() on the span when done.
2143     *
2144     * <p>This will never return null, but on devices without debugging
2145     * enabled, this may return a dummy object on which the finish()
2146     * method is a no-op.
2147     *
2148     * <p>TODO: add CloseGuard to this, verifying callers call finish.
2149     *
2150     * @hide
2151     */
2152    public static Span enterCriticalSpan(String name) {
2153        if (IS_USER_BUILD) {
2154            return NO_OP_SPAN;
2155        }
2156        if (name == null || name.isEmpty()) {
2157            throw new IllegalArgumentException("name must be non-null and non-empty");
2158        }
2159        ThreadSpanState state = sThisThreadSpanState.get();
2160        Span span = null;
2161        synchronized (state) {
2162            if (state.mFreeListHead != null) {
2163                span = state.mFreeListHead;
2164                state.mFreeListHead = span.mNext;
2165                state.mFreeListSize--;
2166            } else {
2167                // Shouldn't have to do this often.
2168                span = new Span(state);
2169            }
2170            span.mName = name;
2171            span.mCreateMillis = SystemClock.uptimeMillis();
2172            span.mNext = state.mActiveHead;
2173            span.mPrev = null;
2174            state.mActiveHead = span;
2175            state.mActiveSize++;
2176            if (span.mNext != null) {
2177                span.mNext.mPrev = span;
2178            }
2179            if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
2180        }
2181        return span;
2182    }
2183
2184    /**
2185     * For code to note that it's slow.  This is a no-op unless the
2186     * current thread's {@link android.os.StrictMode.ThreadPolicy} has
2187     * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls}
2188     * enabled.
2189     *
2190     * @param name a short string for the exception stack trace that's
2191     *             built if when this fires.
2192     */
2193    public static void noteSlowCall(String name) {
2194        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2195        if (!(policy instanceof AndroidBlockGuardPolicy)) {
2196            // StrictMode not enabled.
2197            return;
2198        }
2199        ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
2200    }
2201
2202    /**
2203     * For code to note that a resource was obtained using a type other than
2204     * its defined type. This is a no-op unless the current thread's
2205     * {@link android.os.StrictMode.ThreadPolicy} has
2206     * {@link android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()}
2207     * enabled.
2208     *
2209     * @param tag an object for the exception stack trace that's
2210     *            built if when this fires.
2211     * @hide
2212     */
2213    public static void noteResourceMismatch(Object tag) {
2214        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2215        if (!(policy instanceof AndroidBlockGuardPolicy)) {
2216            // StrictMode not enabled.
2217            return;
2218        }
2219        ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag);
2220    }
2221
2222    /**
2223     * @hide
2224     */
2225    public static void noteUnbufferedIO() {
2226        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2227        if (!(policy instanceof AndroidBlockGuardPolicy)) {
2228            // StrictMode not enabled.
2229            return;
2230        }
2231        ((AndroidBlockGuardPolicy) policy).onUnbufferedIO();
2232    }
2233
2234    /**
2235     * @hide
2236     */
2237    public static void noteDiskRead() {
2238        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2239        if (!(policy instanceof AndroidBlockGuardPolicy)) {
2240            // StrictMode not enabled.
2241            return;
2242        }
2243        ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
2244    }
2245
2246    /**
2247     * @hide
2248     */
2249    public static void noteDiskWrite() {
2250        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2251        if (!(policy instanceof AndroidBlockGuardPolicy)) {
2252            // StrictMode not enabled.
2253            return;
2254        }
2255        ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
2256    }
2257
2258    // Guarded by StrictMode.class
2259    private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
2260            new HashMap<Class, Integer>();
2261
2262    /**
2263     * Returns an object that is used to track instances of activites.
2264     * The activity should store a reference to the tracker object in one of its fields.
2265     * @hide
2266     */
2267    public static Object trackActivity(Object instance) {
2268        return new InstanceTracker(instance);
2269    }
2270
2271    /**
2272     * @hide
2273     */
2274    public static void incrementExpectedActivityCount(Class klass) {
2275        if (klass == null) {
2276            return;
2277        }
2278
2279        synchronized (StrictMode.class) {
2280            if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2281                return;
2282            }
2283
2284            Integer expected = sExpectedActivityInstanceCount.get(klass);
2285            Integer newExpected = expected == null ? 1 : expected + 1;
2286            sExpectedActivityInstanceCount.put(klass, newExpected);
2287        }
2288    }
2289
2290    /**
2291     * @hide
2292     */
2293    public static void decrementExpectedActivityCount(Class klass) {
2294        if (klass == null) {
2295            return;
2296        }
2297
2298        final int limit;
2299        synchronized (StrictMode.class) {
2300            if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2301                return;
2302            }
2303
2304            Integer expected = sExpectedActivityInstanceCount.get(klass);
2305            int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
2306            if (newExpected == 0) {
2307                sExpectedActivityInstanceCount.remove(klass);
2308            } else {
2309                sExpectedActivityInstanceCount.put(klass, newExpected);
2310            }
2311
2312            // Note: adding 1 here to give some breathing room during
2313            // orientation changes.  (shouldn't be necessary, though?)
2314            limit = newExpected + 1;
2315        }
2316
2317        // Quick check.
2318        int actual = InstanceTracker.getInstanceCount(klass);
2319        if (actual <= limit) {
2320            return;
2321        }
2322
2323        // Do a GC and explicit count to double-check.
2324        // This is the work that we are trying to avoid by tracking the object instances
2325        // explicity.  Running an explicit GC can be expensive (80ms) and so can walking
2326        // the heap to count instance (30ms).  This extra work can make the system feel
2327        // noticeably less responsive during orientation changes when activities are
2328        // being restarted.  Granted, it is only a problem when StrictMode is enabled
2329        // but it is annoying.
2330
2331        System.gc();
2332        System.runFinalization();
2333        System.gc();
2334
2335        long instances = VMDebug.countInstancesOfClass(klass, false);
2336        if (instances > limit) {
2337            Throwable tr = new InstanceCountViolation(klass, instances, limit);
2338            onVmPolicyViolation(tr.getMessage(), tr);
2339        }
2340    }
2341
2342    /**
2343     * Parcelable that gets sent in Binder call headers back to callers
2344     * to report violations that happened during a cross-process call.
2345     *
2346     * @hide
2347     */
2348    public static class ViolationInfo {
2349        public final String message;
2350
2351        /**
2352         * Stack and other stuff info.
2353         */
2354        public final ApplicationErrorReport.CrashInfo crashInfo;
2355
2356        /**
2357         * The strict mode policy mask at the time of violation.
2358         */
2359        public final int policy;
2360
2361        /**
2362         * The wall time duration of the violation, when known.  -1 when
2363         * not known.
2364         */
2365        public int durationMillis = -1;
2366
2367        /**
2368         * The number of animations currently running.
2369         */
2370        public int numAnimationsRunning = 0;
2371
2372        /**
2373         * List of tags from active Span instances during this
2374         * violation, or null for none.
2375         */
2376        public String[] tags;
2377
2378        /**
2379         * Which violation number this was (1-based) since the last Looper loop,
2380         * from the perspective of the root caller (if it crossed any processes
2381         * via Binder calls).  The value is 0 if the root caller wasn't on a Looper
2382         * thread.
2383         */
2384        public int violationNumThisLoop;
2385
2386        /**
2387         * The time (in terms of SystemClock.uptimeMillis()) that the
2388         * violation occurred.
2389         */
2390        public long violationUptimeMillis;
2391
2392        /**
2393         * The action of the Intent being broadcast to somebody's onReceive
2394         * on this thread right now, or null.
2395         */
2396        public String broadcastIntentAction;
2397
2398        /**
2399         * If this is a instance count violation, the number of instances in memory,
2400         * else -1.
2401         */
2402        public long numInstances = -1;
2403
2404        /**
2405         * Create an uninitialized instance of ViolationInfo
2406         */
2407        public ViolationInfo() {
2408            message = null;
2409            crashInfo = null;
2410            policy = 0;
2411        }
2412
2413        public ViolationInfo(Throwable tr, int policy) {
2414            this(null, tr, policy);
2415        }
2416
2417        /**
2418         * Create an instance of ViolationInfo initialized from an exception.
2419         */
2420        public ViolationInfo(String message, Throwable tr, int policy) {
2421            this.message = message;
2422            crashInfo = new ApplicationErrorReport.CrashInfo(tr);
2423            violationUptimeMillis = SystemClock.uptimeMillis();
2424            this.policy = policy;
2425            this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
2426            Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2427            if (broadcastIntent != null) {
2428                broadcastIntentAction = broadcastIntent.getAction();
2429            }
2430            ThreadSpanState state = sThisThreadSpanState.get();
2431            if (tr instanceof InstanceCountViolation) {
2432                this.numInstances = ((InstanceCountViolation) tr).mInstances;
2433            }
2434            synchronized (state) {
2435                int spanActiveCount = state.mActiveSize;
2436                if (spanActiveCount > MAX_SPAN_TAGS) {
2437                    spanActiveCount = MAX_SPAN_TAGS;
2438                }
2439                if (spanActiveCount != 0) {
2440                    this.tags = new String[spanActiveCount];
2441                    Span iter = state.mActiveHead;
2442                    int index = 0;
2443                    while (iter != null && index < spanActiveCount) {
2444                        this.tags[index] = iter.mName;
2445                        index++;
2446                        iter = iter.mNext;
2447                    }
2448                }
2449            }
2450        }
2451
2452        @Override
2453        public int hashCode() {
2454            int result = 17;
2455            if (crashInfo != null) {
2456                result = 37 * result + crashInfo.stackTrace.hashCode();
2457            }
2458            if (numAnimationsRunning != 0) {
2459                result *= 37;
2460            }
2461            if (broadcastIntentAction != null) {
2462                result = 37 * result + broadcastIntentAction.hashCode();
2463            }
2464            if (tags != null) {
2465                for (String tag : tags) {
2466                    result = 37 * result + tag.hashCode();
2467                }
2468            }
2469            return result;
2470        }
2471
2472        /**
2473         * Create an instance of ViolationInfo initialized from a Parcel.
2474         */
2475        public ViolationInfo(Parcel in) {
2476            this(in, false);
2477        }
2478
2479        /**
2480         * Create an instance of ViolationInfo initialized from a Parcel.
2481         *
2482         * @param unsetGatheringBit if true, the caller is the root caller
2483         *   and the gathering penalty should be removed.
2484         */
2485        public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
2486            message = in.readString();
2487            if (in.readInt() != 0) {
2488                crashInfo = new ApplicationErrorReport.CrashInfo(in);
2489            } else {
2490                crashInfo = null;
2491            }
2492            int rawPolicy = in.readInt();
2493            if (unsetGatheringBit) {
2494                policy = rawPolicy & ~PENALTY_GATHER;
2495            } else {
2496                policy = rawPolicy;
2497            }
2498            durationMillis = in.readInt();
2499            violationNumThisLoop = in.readInt();
2500            numAnimationsRunning = in.readInt();
2501            violationUptimeMillis = in.readLong();
2502            numInstances = in.readLong();
2503            broadcastIntentAction = in.readString();
2504            tags = in.readStringArray();
2505        }
2506
2507        /**
2508         * Save a ViolationInfo instance to a parcel.
2509         */
2510        public void writeToParcel(Parcel dest, int flags) {
2511            dest.writeString(message);
2512            if (crashInfo != null) {
2513                dest.writeInt(1);
2514                crashInfo.writeToParcel(dest, flags);
2515            } else {
2516                dest.writeInt(0);
2517            }
2518            int start = dest.dataPosition();
2519            dest.writeInt(policy);
2520            dest.writeInt(durationMillis);
2521            dest.writeInt(violationNumThisLoop);
2522            dest.writeInt(numAnimationsRunning);
2523            dest.writeLong(violationUptimeMillis);
2524            dest.writeLong(numInstances);
2525            dest.writeString(broadcastIntentAction);
2526            dest.writeStringArray(tags);
2527            int total = dest.dataPosition()-start;
2528            if (total > 10*1024) {
2529                Slog.d(TAG, "VIO: policy=" + policy + " dur=" + durationMillis
2530                        + " numLoop=" + violationNumThisLoop
2531                        + " anim=" + numAnimationsRunning
2532                        + " uptime=" + violationUptimeMillis
2533                        + " numInst=" + numInstances);
2534                Slog.d(TAG, "VIO: action=" + broadcastIntentAction);
2535                Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags));
2536                Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition()-start));
2537            }
2538        }
2539
2540
2541        /**
2542         * Dump a ViolationInfo instance to a Printer.
2543         */
2544        public void dump(Printer pw, String prefix) {
2545            if (crashInfo != null) {
2546                crashInfo.dump(pw, prefix);
2547            }
2548            pw.println(prefix + "policy: " + policy);
2549            if (durationMillis != -1) {
2550                pw.println(prefix + "durationMillis: " + durationMillis);
2551            }
2552            if (numInstances != -1) {
2553                pw.println(prefix + "numInstances: " + numInstances);
2554            }
2555            if (violationNumThisLoop != 0) {
2556                pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2557            }
2558            if (numAnimationsRunning != 0) {
2559                pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2560            }
2561            pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
2562            if (broadcastIntentAction != null) {
2563                pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2564            }
2565            if (tags != null) {
2566                int index = 0;
2567                for (String tag : tags) {
2568                    pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2569                }
2570            }
2571        }
2572
2573    }
2574
2575    // Dummy throwable, for now, since we don't know when or where the
2576    // leaked instances came from.  We might in the future, but for
2577    // now we suppress the stack trace because it's useless and/or
2578    // misleading.
2579    private static class InstanceCountViolation extends Throwable {
2580        final Class mClass;
2581        final long mInstances;
2582        final int mLimit;
2583
2584        private static final StackTraceElement[] FAKE_STACK = {
2585            new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
2586                                  "StrictMode.java", 1)
2587        };
2588
2589        public InstanceCountViolation(Class klass, long instances, int limit) {
2590            super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
2591            setStackTrace(FAKE_STACK);
2592            mClass = klass;
2593            mInstances = instances;
2594            mLimit = limit;
2595        }
2596    }
2597
2598    private static final class InstanceTracker {
2599        private static final HashMap<Class<?>, Integer> sInstanceCounts =
2600                new HashMap<Class<?>, Integer>();
2601
2602        private final Class<?> mKlass;
2603
2604        public InstanceTracker(Object instance) {
2605            mKlass = instance.getClass();
2606
2607            synchronized (sInstanceCounts) {
2608                final Integer value = sInstanceCounts.get(mKlass);
2609                final int newValue = value != null ? value + 1 : 1;
2610                sInstanceCounts.put(mKlass, newValue);
2611            }
2612        }
2613
2614        @Override
2615        protected void finalize() throws Throwable {
2616            try {
2617                synchronized (sInstanceCounts) {
2618                    final Integer value = sInstanceCounts.get(mKlass);
2619                    if (value != null) {
2620                        final int newValue = value - 1;
2621                        if (newValue > 0) {
2622                            sInstanceCounts.put(mKlass, newValue);
2623                        } else {
2624                            sInstanceCounts.remove(mKlass);
2625                        }
2626                    }
2627                }
2628            } finally {
2629                super.finalize();
2630            }
2631        }
2632
2633        public static int getInstanceCount(Class<?> klass) {
2634            synchronized (sInstanceCounts) {
2635                final Integer value = sInstanceCounts.get(klass);
2636                return value != null ? value : 0;
2637            }
2638        }
2639    }
2640}
2641