StrictMode.java revision 1065685400335ef8c1220f34b4e896e7da603789
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.Intent;
24import android.util.Log;
25import android.util.Printer;
26import android.util.Singleton;
27import android.view.IWindowManager;
28
29import com.android.internal.os.RuntimeInit;
30
31import dalvik.system.BlockGuard;
32import dalvik.system.CloseGuard;
33
34import java.io.PrintWriter;
35import java.io.StringWriter;
36import java.util.ArrayList;
37import java.util.HashMap;
38import java.util.concurrent.atomic.AtomicInteger;
39
40/**
41 * <p>StrictMode is a developer tool which detects things you might be
42 * doing by accident and brings them to your attention so you can fix
43 * them.
44 *
45 * <p>StrictMode is most commonly used to catch accidental disk or
46 * network access on the application's main thread, where UI
47 * operations are received and animations take place.  Keeping disk
48 * and network operations off the main thread makes for much smoother,
49 * more responsive applications.  By keeping your application's main thread
50 * responsive, you also prevent
51 * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
52 * from being shown to users.
53 *
54 * <p class="note">Note that even though an Android device's disk is
55 * often on flash memory, many devices run a filesystem on top of that
56 * memory with very limited concurrency.  It's often the case that
57 * almost all disk accesses are fast, but may in individual cases be
58 * dramatically slower when certain I/O is happening in the background
59 * from other processes.  If possible, it's best to assume that such
60 * things are not fast.</p>
61 *
62 * <p>Example code to enable from early in your
63 * {@link android.app.Application}, {@link android.app.Activity}, or
64 * other application component's
65 * {@link android.app.Application#onCreate} method:
66 *
67 * <pre>
68 * public void onCreate() {
69 *     if (DEVELOPER_MODE) {
70 *         StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
71 *                 .detectDiskReads()
72 *                 .detectDiskWrites()
73 *                 .detectNetwork()   // or .detectAll() for all detectable problems
74 *                 .penaltyLog()
75 *                 .build());
76 *         StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
77 *                 .detectLeakedSqlLiteObjects()
78 *                 .detectLeakedClosableObjects()
79 *                 .penaltyLog()
80 *                 .penaltyDeath()
81 *                 .build());
82 *     }
83 *     super.onCreate();
84 * }
85 * </pre>
86 *
87 * <p>You can decide what should happen when a violation is detected.
88 * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can
89 * watch the output of <code>adb logcat</code> while you use your
90 * application to see the violations as they happen.
91 *
92 * <p>If you find violations that you feel are problematic, there are
93 * a variety of tools to help solve them: threads, {@link android.os.Handler},
94 * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
95 * But don't feel compelled to fix everything that StrictMode finds.  In particular,
96 * many cases of disk access are often necessary during the normal activity lifecycle.  Use
97 * StrictMode to find things you did by accident.  Network requests on the UI thread
98 * are almost always a problem, though.
99 *
100 * <p class="note">StrictMode is not a security mechanism and is not
101 * guaranteed to find all disk or network accesses.  While it does
102 * propagate its state across process boundaries when doing
103 * {@link android.os.Binder} calls, it's still ultimately a best
104 * effort mechanism.  Notably, disk or network access from JNI calls
105 * won't necessarily trigger it.  Future versions of Android may catch
106 * more (or fewer) operations, so you should never leave StrictMode
107 * enabled in shipping applications on the Android Market.
108 */
109public final class StrictMode {
110    private static final String TAG = "StrictMode";
111    private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
112
113    private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
114    private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE);
115
116    // Only log a duplicate stack trace to the logs every second.
117    private static final long MIN_LOG_INTERVAL_MS = 1000;
118
119    // Only show an annoying dialog at most every 30 seconds
120    private static final long MIN_DIALOG_INTERVAL_MS = 30000;
121
122    // How many Span tags (e.g. animations) to report.
123    private static final int MAX_SPAN_TAGS = 20;
124
125    // How many offending stacks to keep track of (and time) per loop
126    // of the Looper.
127    private static final int MAX_OFFENSES_PER_LOOP = 10;
128
129    // Thread-policy:
130
131    /**
132     * @hide
133     */
134    public static final int DETECT_DISK_WRITE = 0x01;  // for ThreadPolicy
135
136    /**
137      * @hide
138     */
139    public static final int DETECT_DISK_READ = 0x02;  // for ThreadPolicy
140
141    /**
142     * @hide
143     */
144    public static final int DETECT_NETWORK = 0x04;  // for ThreadPolicy
145
146    // Process-policy:
147
148    /**
149     * Note, a "VM_" bit, not thread.
150     * @hide
151     */
152    public static final int DETECT_VM_CURSOR_LEAKS = 0x200;  // for ProcessPolicy
153
154    /**
155     * Note, a "VM_" bit, not thread.
156     * @hide
157     */
158    public static final int DETECT_VM_CLOSABLE_LEAKS = 0x400;  // for ProcessPolicy
159
160    /**
161     * @hide
162     */
163    public static final int PENALTY_LOG = 0x10;  // normal android.util.Log
164
165    // Used for both process and thread policy:
166
167    /**
168     * @hide
169     */
170    public static final int PENALTY_DIALOG = 0x20;
171
172    /**
173     * Death on any detected violation.
174     *
175     * @hide
176     */
177    public static final int PENALTY_DEATH = 0x40;
178
179    /**
180     * Death just for detected network usage.
181     *
182     * @hide
183     */
184    public static final int PENALTY_DEATH_ON_NETWORK = 0x200;
185
186    /**
187     * Flash the screen during violations.
188     *
189     * @hide
190     */
191    public static final int PENALTY_FLASH = 0x800;
192
193    /**
194     * @hide
195     */
196    public static final int PENALTY_DROPBOX = 0x80;
197
198    /**
199     * Non-public penalty mode which overrides all the other penalty
200     * bits and signals that we're in a Binder call and we should
201     * ignore the other penalty bits and instead serialize back all
202     * our offending stack traces to the caller to ultimately handle
203     * in the originating process.
204     *
205     * This must be kept in sync with the constant in libs/binder/Parcel.cpp
206     *
207     * @hide
208     */
209    public static final int PENALTY_GATHER = 0x100;
210
211    /**
212     * Mask of all the penalty bits.
213     */
214    private static final int PENALTY_MASK =
215            PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
216            PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;
217
218    /**
219     * The current VmPolicy in effect.
220     */
221    private static volatile int sVmPolicyMask = 0;
222
223    /**
224     * The number of threads trying to do an async dropbox write.
225     * Just to limit ourselves out of paranoia.
226     */
227    private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
228
229    private StrictMode() {}
230
231    /**
232     * {@link StrictMode} policy applied to a certain thread.
233     *
234     * <p>The policy is enabled by {@link #setThreadPolicy}.  The current policy
235     * can be retrieved with {@link #getThreadPolicy}.
236     *
237     * <p>Note that multiple penalties may be provided and they're run
238     * in order from least to most severe (logging before process
239     * death, for example).  There's currently no mechanism to choose
240     * different penalties for different detected actions.
241     */
242    public static final class ThreadPolicy {
243        /**
244         * The default, lax policy which doesn't catch anything.
245         */
246        public static final ThreadPolicy LAX = new ThreadPolicy(0);
247
248        final int mask;
249
250        private ThreadPolicy(int mask) {
251            this.mask = mask;
252        }
253
254        @Override
255        public String toString() {
256            return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
257        }
258
259        /**
260         * Creates ThreadPolicy instances.  Methods whose names start
261         * with {@code detect} specify what problems we should look
262         * for.  Methods whose names start with {@code penalty} specify what
263         * we should do when we detect a problem.
264         *
265         * <p>You can call as many {@code detect} and {@code penalty}
266         * methods as you like. Currently order is insignificant: all
267         * penalties apply to all detected problems.
268         *
269         * <p>For example, detect everything and log anything that's found:
270         * <pre>
271         * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
272         *     .detectAll()
273         *     .penaltyLog()
274         *     .build();
275         * StrictMode.setVmPolicy(policy);
276         * </pre>
277         */
278        public static final class Builder {
279            private int mMask = 0;
280
281            /**
282             * Create a Builder that detects nothing and has no
283             * violations.  (but note that {@link #build} will default
284             * to enabling {@link #penaltyLog} if no other penalties
285             * are specified)
286             */
287            public Builder() {
288                mMask = 0;
289            }
290
291            /**
292             * Initialize a Builder from an existing ThreadPolicy.
293             */
294            public Builder(ThreadPolicy policy) {
295                mMask = policy.mask;
296            }
297
298            /**
299             * Detect everything that's potentially suspect.
300             *
301             * <p>As of the Gingerbread release this includes network and
302             * disk operations but will likely expand in future releases.
303             */
304            public Builder detectAll() {
305                return enable(DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK);
306            }
307
308            /**
309             * Disable the detection of everything.
310             */
311            public Builder permitAll() {
312                return disable(DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK);
313            }
314
315            /**
316             * Enable detection of network operations.
317             */
318            public Builder detectNetwork() {
319                return enable(DETECT_NETWORK);
320            }
321
322            /**
323             * Disable detection of network operations.
324             */
325            public Builder permitNetwork() {
326                return disable(DETECT_NETWORK);
327            }
328
329            /**
330             * Enable detection of disk reads.
331             */
332            public Builder detectDiskReads() {
333                return enable(DETECT_DISK_READ);
334            }
335
336            /**
337             * Disable detection of disk reads.
338             */
339            public Builder permitDiskReads() {
340                return disable(DETECT_DISK_READ);
341            }
342
343            /**
344             * Enable detection of disk writes.
345             */
346            public Builder detectDiskWrites() {
347                return enable(DETECT_DISK_WRITE);
348            }
349
350            /**
351             * Disable detection of disk writes.
352             */
353            public Builder permitDiskWrites() {
354                return disable(DETECT_DISK_WRITE);
355            }
356
357            /**
358             * Show an annoying dialog to the developer on detected
359             * violations, rate-limited to be only a little annoying.
360             */
361            public Builder penaltyDialog() {
362                return enable(PENALTY_DIALOG);
363            }
364
365            /**
366             * Crash the whole process on violation.  This penalty runs at
367             * the end of all enabled penalties so you'll still get
368             * see logging or other violations before the process dies.
369             *
370             * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies
371             * to disk reads, disk writes, and network usage if their
372             * corresponding detect flags are set.
373             */
374            public Builder penaltyDeath() {
375                return enable(PENALTY_DEATH);
376            }
377
378            /**
379             * Crash the whole process on any network usage.  Unlike
380             * {@link #penaltyDeath}, this penalty runs
381             * <em>before</em> anything else.  You must still have
382             * called {@link #detectNetwork} to enable this.
383             *
384             * <p>In the Honeycomb or later SDKs, this is on by default.
385             */
386            public Builder penaltyDeathOnNetwork() {
387                return enable(PENALTY_DEATH_ON_NETWORK);
388            }
389
390            /**
391             * Flash the screen during a violation.
392             */
393            public Builder penaltyFlashScreen() {
394                return enable(PENALTY_FLASH);
395            }
396
397            /**
398             * Log detected violations to the system log.
399             */
400            public Builder penaltyLog() {
401                return enable(PENALTY_LOG);
402            }
403
404            /**
405             * Enable detected violations log a stacktrace and timing data
406             * to the {@link android.os.DropBoxManager DropBox} on policy
407             * violation.  Intended mostly for platform integrators doing
408             * beta user field data collection.
409             */
410            public Builder penaltyDropBox() {
411                return enable(PENALTY_DROPBOX);
412            }
413
414            private Builder enable(int bit) {
415                mMask |= bit;
416                return this;
417            }
418
419            private Builder disable(int bit) {
420                mMask &= ~bit;
421                return this;
422            }
423
424            /**
425             * Construct the ThreadPolicy instance.
426             *
427             * <p>Note: if no penalties are enabled before calling
428             * <code>build</code>, {@link #penaltyLog} is implicitly
429             * set.
430             */
431            public ThreadPolicy build() {
432                // If there are detection bits set but no violation bits
433                // set, enable simple logging.
434                if (mMask != 0 &&
435                    (mMask & (PENALTY_DEATH | PENALTY_LOG |
436                              PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
437                    penaltyLog();
438                }
439                return new ThreadPolicy(mMask);
440            }
441        }
442    }
443
444    /**
445     * {@link StrictMode} policy applied to all threads in the virtual machine's process.
446     *
447     * <p>The policy is enabled by {@link #setVmPolicy}.
448     */
449    public static final class VmPolicy {
450        /**
451         * The default, lax policy which doesn't catch anything.
452         */
453        public static final VmPolicy LAX = new VmPolicy(0);
454
455        final int mask;
456
457        private VmPolicy(int mask) {
458            this.mask = mask;
459        }
460
461        @Override
462        public String toString() {
463            return "[StrictMode.VmPolicy; mask=" + mask + "]";
464        }
465
466        /**
467         * Creates {@link VmPolicy} instances.  Methods whose names start
468         * with {@code detect} specify what problems we should look
469         * for.  Methods whose names start with {@code penalty} specify what
470         * we should do when we detect a problem.
471         *
472         * <p>You can call as many {@code detect} and {@code penalty}
473         * methods as you like. Currently order is insignificant: all
474         * penalties apply to all detected problems.
475         *
476         * <p>For example, detect everything and log anything that's found:
477         * <pre>
478         * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
479         *     .detectAll()
480         *     .penaltyLog()
481         *     .build();
482         * StrictMode.setVmPolicy(policy);
483         * </pre>
484         */
485        public static final class Builder {
486            private int mMask;
487
488            /**
489             * Detect everything that's potentially suspect.
490             *
491             * <p>In the Honeycomb release this includes leaks of
492             * SQLite cursors and other closable objects but will
493             * likely expand in future releases.
494             */
495            public Builder detectAll() {
496                return enable(DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS);
497            }
498
499            /**
500             * Detect when an
501             * {@link android.database.sqlite.SQLiteCursor} or other
502             * SQLite object is finalized without having been closed.
503             *
504             * <p>You always want to explicitly close your SQLite
505             * cursors to avoid unnecessary database contention and
506             * temporary memory leaks.
507             */
508            public Builder detectLeakedSqlLiteObjects() {
509                return enable(DETECT_VM_CURSOR_LEAKS);
510            }
511
512            /**
513             * Detect when an {@link java.io.Closeable} or other
514             * object with a explict termination method is finalized
515             * without having been closed.
516             *
517             * <p>You always want to explicitly close such objects to
518             * avoid unnecessary resources leaks.
519             */
520            public Builder detectLeakedClosableObjects() {
521                return enable(DETECT_VM_CLOSABLE_LEAKS);
522            }
523
524            /**
525             * Crashes the whole process on violation.  This penalty runs at
526             * the end of all enabled penalties so yo you'll still get
527             * your logging or other violations before the process dies.
528             */
529            public Builder penaltyDeath() {
530                return enable(PENALTY_DEATH);
531            }
532
533            /**
534             * Log detected violations to the system log.
535             */
536            public Builder penaltyLog() {
537                return enable(PENALTY_LOG);
538            }
539
540            /**
541             * Enable detected violations log a stacktrace and timing data
542             * to the {@link android.os.DropBoxManager DropBox} on policy
543             * violation.  Intended mostly for platform integrators doing
544             * beta user field data collection.
545             */
546            public Builder penaltyDropBox() {
547                return enable(PENALTY_DROPBOX);
548            }
549
550            private Builder enable(int bit) {
551                mMask |= bit;
552                return this;
553            }
554
555            /**
556             * Construct the VmPolicy instance.
557             *
558             * <p>Note: if no penalties are enabled before calling
559             * <code>build</code>, {@link #penaltyLog} is implicitly
560             * set.
561             */
562            public VmPolicy build() {
563                // If there are detection bits set but no violation bits
564                // set, enable simple logging.
565                if (mMask != 0 &&
566                    (mMask & (PENALTY_DEATH | PENALTY_LOG |
567                              PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
568                    penaltyLog();
569                }
570                return new VmPolicy(mMask);
571            }
572        }
573    }
574
575    /**
576     * Log of strict mode violation stack traces that have occurred
577     * during a Binder call, to be serialized back later to the caller
578     * via Parcel.writeNoException() (amusingly) where the caller can
579     * choose how to react.
580     */
581    private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
582            new ThreadLocal<ArrayList<ViolationInfo>>() {
583        @Override protected ArrayList<ViolationInfo> initialValue() {
584            // Starts null to avoid unnecessary allocations when
585            // checking whether there are any violations or not in
586            // hasGatheredViolations() below.
587            return null;
588        }
589    };
590
591    /**
592     * Sets the policy for what actions on the current thread should
593     * be detected, as well as the penalty if such actions occur.
594     *
595     * <p>Internally this sets a thread-local variable which is
596     * propagated across cross-process IPC calls, meaning you can
597     * catch violations when a system service or another process
598     * accesses the disk or network on your behalf.
599     *
600     * @param policy the policy to put into place
601     */
602    public static void setThreadPolicy(final ThreadPolicy policy) {
603        setThreadPolicyMask(policy.mask);
604    }
605
606    private static void setThreadPolicyMask(final int policyMask) {
607        // In addition to the Java-level thread-local in Dalvik's
608        // BlockGuard, we also need to keep a native thread-local in
609        // Binder in order to propagate the value across Binder calls,
610        // even across native-only processes.  The two are kept in
611        // sync via the callback to onStrictModePolicyChange, below.
612        setBlockGuardPolicy(policyMask);
613
614        // And set the Android native version...
615        Binder.setThreadStrictModePolicy(policyMask);
616    }
617
618    // Sets the policy in Dalvik/libcore (BlockGuard)
619    private static void setBlockGuardPolicy(final int policyMask) {
620        if (policyMask == 0) {
621            BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
622            return;
623        }
624        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
625        if (!(policy instanceof AndroidBlockGuardPolicy)) {
626            BlockGuard.setThreadPolicy(new AndroidBlockGuardPolicy(policyMask));
627        } else {
628            AndroidBlockGuardPolicy androidPolicy = (AndroidBlockGuardPolicy) policy;
629            androidPolicy.setPolicyMask(policyMask);
630        }
631    }
632
633    // Sets up CloseGuard in Dalvik/libcore
634    private static void setCloseGuardEnabled(boolean enabled) {
635        if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
636            CloseGuard.setReporter(new AndroidCloseGuardReporter());
637        }
638        CloseGuard.setEnabled(enabled);
639    }
640
641    private static class StrictModeNetworkViolation extends BlockGuard.BlockGuardPolicyException {
642        public StrictModeNetworkViolation(int policyMask) {
643            super(policyMask, DETECT_NETWORK);
644        }
645    }
646
647    private static class StrictModeDiskReadViolation extends BlockGuard.BlockGuardPolicyException {
648        public StrictModeDiskReadViolation(int policyMask) {
649            super(policyMask, DETECT_DISK_READ);
650        }
651    }
652
653    private static class StrictModeDiskWriteViolation extends BlockGuard.BlockGuardPolicyException {
654        public StrictModeDiskWriteViolation(int policyMask) {
655            super(policyMask, DETECT_DISK_WRITE);
656        }
657    }
658
659    /**
660     * Returns the bitmask of the current thread's policy.
661     *
662     * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
663     *
664     * @hide
665     */
666    public static int getThreadPolicyMask() {
667        return BlockGuard.getThreadPolicy().getPolicyMask();
668    }
669
670    /**
671     * Returns the current thread's policy.
672     */
673    public static ThreadPolicy getThreadPolicy() {
674        return new ThreadPolicy(getThreadPolicyMask());
675    }
676
677    /**
678     * A convenience wrapper that takes the current
679     * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
680     * to permit both disk reads &amp; writes, and sets the new policy
681     * with {@link #setThreadPolicy}, returning the old policy so you
682     * can restore it at the end of a block.
683     *
684     * @return the old policy, to be passed to {@link #setThreadPolicy} to
685     *         restore the policy at the end of a block
686     */
687    public static ThreadPolicy allowThreadDiskWrites() {
688        int oldPolicyMask = getThreadPolicyMask();
689        int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
690        if (newPolicyMask != oldPolicyMask) {
691            setThreadPolicyMask(newPolicyMask);
692        }
693        return new ThreadPolicy(oldPolicyMask);
694    }
695
696    /**
697     * A convenience wrapper that takes the current
698     * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
699     * to permit disk reads, and sets the new policy
700     * with {@link #setThreadPolicy}, returning the old policy so you
701     * can restore it at the end of a block.
702     *
703     * @return the old policy, to be passed to setThreadPolicy to
704     *         restore the policy.
705     */
706    public static ThreadPolicy allowThreadDiskReads() {
707        int oldPolicyMask = getThreadPolicyMask();
708        int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
709        if (newPolicyMask != oldPolicyMask) {
710            setThreadPolicyMask(newPolicyMask);
711        }
712        return new ThreadPolicy(oldPolicyMask);
713    }
714
715    /**
716     * Enable DropBox logging for debug phone builds.
717     *
718     * @hide
719     */
720    public static boolean conditionallyEnableDebugLogging() {
721        // For debug builds, log event loop stalls to dropbox for analysis.
722        // Similar logic also appears in ActivityThread.java for system apps.
723        if (IS_USER_BUILD) {
724            setCloseGuardEnabled(false);
725            return false;
726        }
727        StrictMode.setThreadPolicyMask(
728            StrictMode.DETECT_DISK_WRITE |
729            StrictMode.DETECT_DISK_READ |
730            StrictMode.DETECT_NETWORK |
731            StrictMode.PENALTY_DROPBOX |
732            (IS_ENG_BUILD ? StrictMode.PENALTY_FLASH : 0)
733        );
734        sVmPolicyMask = StrictMode.DETECT_VM_CURSOR_LEAKS |
735                StrictMode.DETECT_VM_CLOSABLE_LEAKS |
736                StrictMode.PENALTY_DROPBOX;
737        setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
738        return true;
739    }
740
741    /**
742     * Used by the framework to make network usage on the main
743     * thread a fatal error.
744     *
745     * @hide
746     */
747    public static void enableDeathOnNetwork() {
748        int oldPolicy = getThreadPolicyMask();
749        int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
750        setThreadPolicyMask(newPolicy);
751    }
752
753    /**
754     * Parses the BlockGuard policy mask out from the Exception's
755     * getMessage() String value.  Kinda gross, but least
756     * invasive.  :/
757     *
758     * Input is of form "policy=137 violation=64"
759     *
760     * Returns 0 on failure, which is a valid policy, but not a
761     * valid policy during a violation (else there must've been
762     * some policy in effect to violate).
763     */
764    private static int parsePolicyFromMessage(String message) {
765        if (message == null || !message.startsWith("policy=")) {
766            return 0;
767        }
768        int spaceIndex = message.indexOf(' ');
769        if (spaceIndex == -1) {
770            return 0;
771        }
772        String policyString = message.substring(7, spaceIndex);
773        try {
774            return Integer.valueOf(policyString).intValue();
775        } catch (NumberFormatException e) {
776            return 0;
777        }
778    }
779
780    /**
781     * Like parsePolicyFromMessage(), but returns the violation.
782     */
783    private static int parseViolationFromMessage(String message) {
784        if (message == null) {
785            return 0;
786        }
787        int violationIndex = message.indexOf("violation=");
788        if (violationIndex == -1) {
789            return 0;
790        }
791        String violationString = message.substring(violationIndex + 10);
792        try {
793            return Integer.valueOf(violationString).intValue();
794        } catch (NumberFormatException e) {
795            return 0;
796        }
797    }
798
799    private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
800            new ThreadLocal<ArrayList<ViolationInfo>>() {
801        @Override protected ArrayList<ViolationInfo> initialValue() {
802            return new ArrayList<ViolationInfo>();
803        }
804    };
805
806    private static boolean tooManyViolationsThisLoop() {
807        return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
808    }
809
810    private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
811        private int mPolicyMask;
812
813        // Map from violation stacktrace hashcode -> uptimeMillis of
814        // last violation.  No locking needed, as this is only
815        // accessed by the same thread.
816        private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>();
817
818        public AndroidBlockGuardPolicy(final int policyMask) {
819            mPolicyMask = policyMask;
820        }
821
822        @Override
823        public String toString() {
824            return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
825        }
826
827        // Part of BlockGuard.Policy interface:
828        public int getPolicyMask() {
829            return mPolicyMask;
830        }
831
832        // Part of BlockGuard.Policy interface:
833        public void onWriteToDisk() {
834            if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
835                return;
836            }
837            if (tooManyViolationsThisLoop()) {
838                return;
839            }
840            BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
841            e.fillInStackTrace();
842            startHandlingViolationException(e);
843        }
844
845        // Part of BlockGuard.Policy interface:
846        public void onReadFromDisk() {
847            if ((mPolicyMask & DETECT_DISK_READ) == 0) {
848                return;
849            }
850            if (tooManyViolationsThisLoop()) {
851                return;
852            }
853            BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
854            e.fillInStackTrace();
855            startHandlingViolationException(e);
856        }
857
858        // Part of BlockGuard.Policy interface:
859        public void onNetwork() {
860            if ((mPolicyMask & DETECT_NETWORK) == 0) {
861                return;
862            }
863            if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
864                throw new NetworkOnMainThreadException();
865            }
866            if (tooManyViolationsThisLoop()) {
867                return;
868            }
869            BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
870            e.fillInStackTrace();
871            startHandlingViolationException(e);
872        }
873
874        public void setPolicyMask(int policyMask) {
875            mPolicyMask = policyMask;
876        }
877
878        // Start handling a violation that just started and hasn't
879        // actually run yet (e.g. no disk write or network operation
880        // has yet occurred).  This sees if we're in an event loop
881        // thread and, if so, uses it to roughly measure how long the
882        // violation took.
883        void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) {
884            final ViolationInfo info = new ViolationInfo(e, e.getPolicy());
885            info.violationUptimeMillis = SystemClock.uptimeMillis();
886            handleViolationWithTimingAttempt(info);
887        }
888
889        // Attempts to fill in the provided ViolationInfo's
890        // durationMillis field if this thread has a Looper we can use
891        // to measure with.  We measure from the time of violation
892        // until the time the looper is idle again (right before
893        // the next epoll_wait)
894        void handleViolationWithTimingAttempt(final ViolationInfo info) {
895            Looper looper = Looper.myLooper();
896
897            // Without a Looper, we're unable to time how long the
898            // violation takes place.  This case should be rare, as
899            // most users will care about timing violations that
900            // happen on their main UI thread.  Note that this case is
901            // also hit when a violation takes place in a Binder
902            // thread, in "gather" mode.  In this case, the duration
903            // of the violation is computed by the ultimate caller and
904            // its Looper, if any.
905            // TODO: if in gather mode, ignore Looper.myLooper() and always
906            //       go into this immediate mode?
907            if (looper == null) {
908                info.durationMillis = -1;  // unknown (redundant, already set)
909                handleViolation(info);
910                return;
911            }
912
913            MessageQueue queue = Looper.myQueue();
914            final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
915            if (records.size() >= MAX_OFFENSES_PER_LOOP) {
916                // Not worth measuring.  Too many offenses in one loop.
917                return;
918            }
919            records.add(info);
920            if (records.size() > 1) {
921                // There's already been a violation this loop, so we've already
922                // registered an idle handler to process the list of violations
923                // at the end of this Looper's loop.
924                return;
925            }
926
927            final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ?
928                    sWindowManager.get() : null;
929            if (windowManager != null) {
930                try {
931                    windowManager.showStrictModeViolation(true);
932                } catch (RemoteException unused) {
933                }
934            }
935
936            queue.addIdleHandler(new MessageQueue.IdleHandler() {
937                    public boolean queueIdle() {
938                        long loopFinishTime = SystemClock.uptimeMillis();
939                        for (int n = 0; n < records.size(); ++n) {
940                            ViolationInfo v = records.get(n);
941                            v.violationNumThisLoop = n + 1;
942                            v.durationMillis =
943                                    (int) (loopFinishTime - v.violationUptimeMillis);
944                            handleViolation(v);
945                        }
946                        records.clear();
947                        if (windowManager != null) {
948                            try {
949                                windowManager.showStrictModeViolation(false);
950                            } catch (RemoteException unused) {
951                            }
952                        }
953                        return false;  // remove this idle handler from the array
954                    }
955                });
956        }
957
958        // Note: It's possible (even quite likely) that the
959        // thread-local policy mask has changed from the time the
960        // violation fired and now (after the violating code ran) due
961        // to people who push/pop temporary policy in regions of code,
962        // hence the policy being passed around.
963        void handleViolation(final ViolationInfo info) {
964            if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) {
965                Log.wtf(TAG, "unexpected null stacktrace");
966                return;
967            }
968
969            if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy);
970
971            if ((info.policy & PENALTY_GATHER) != 0) {
972                ArrayList<ViolationInfo> violations = gatheredViolations.get();
973                if (violations == null) {
974                    violations = new ArrayList<ViolationInfo>(1);
975                    gatheredViolations.set(violations);
976                } else if (violations.size() >= 5) {
977                    // Too many.  In a loop or something?  Don't gather them all.
978                    return;
979                }
980                for (ViolationInfo previous : violations) {
981                    if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
982                        // Duplicate. Don't log.
983                        return;
984                    }
985                }
986                violations.add(info);
987                return;
988            }
989
990            // Not perfect, but fast and good enough for dup suppression.
991            Integer crashFingerprint = info.hashCode();
992            long lastViolationTime = 0;
993            if (mLastViolationTime.containsKey(crashFingerprint)) {
994                lastViolationTime = mLastViolationTime.get(crashFingerprint);
995            }
996            long now = SystemClock.uptimeMillis();
997            mLastViolationTime.put(crashFingerprint, now);
998            long timeSinceLastViolationMillis = lastViolationTime == 0 ?
999                    Long.MAX_VALUE : (now - lastViolationTime);
1000
1001            if ((info.policy & PENALTY_LOG) != 0 &&
1002                timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
1003                if (info.durationMillis != -1) {
1004                    Log.d(TAG, "StrictMode policy violation; ~duration=" +
1005                          info.durationMillis + " ms: " + info.crashInfo.stackTrace);
1006                } else {
1007                    Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
1008                }
1009            }
1010
1011            // The violationMaskSubset, passed to ActivityManager, is a
1012            // subset of the original StrictMode policy bitmask, with
1013            // only the bit violated and penalty bits to be executed
1014            // by the ActivityManagerService remaining set.
1015            int violationMaskSubset = 0;
1016
1017            if ((info.policy & PENALTY_DIALOG) != 0 &&
1018                timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
1019                violationMaskSubset |= PENALTY_DIALOG;
1020            }
1021
1022            if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
1023                violationMaskSubset |= PENALTY_DROPBOX;
1024            }
1025
1026            if (violationMaskSubset != 0) {
1027                int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1028                violationMaskSubset |= violationBit;
1029                final int savedPolicyMask = getThreadPolicyMask();
1030
1031                final boolean justDropBox = (info.policy & PENALTY_MASK) == PENALTY_DROPBOX;
1032                if (justDropBox) {
1033                    // If all we're going to ask the activity manager
1034                    // to do is dropbox it (the common case during
1035                    // platform development), we can avoid doing this
1036                    // call synchronously which Binder data suggests
1037                    // isn't always super fast, despite the implementation
1038                    // in the ActivityManager trying to be mostly async.
1039                    dropboxViolationAsync(violationMaskSubset, info);
1040                    return;
1041                }
1042
1043                // Normal synchronous call to the ActivityManager.
1044                try {
1045                    // First, remove any policy before we call into the Activity Manager,
1046                    // otherwise we'll infinite recurse as we try to log policy violations
1047                    // to disk, thus violating policy, thus requiring logging, etc...
1048                    // We restore the current policy below, in the finally block.
1049                    setThreadPolicyMask(0);
1050
1051                    ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1052                        RuntimeInit.getApplicationObject(),
1053                        violationMaskSubset,
1054                        info);
1055                } catch (RemoteException e) {
1056                    Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1057                } finally {
1058                    // Restore the policy.
1059                    setThreadPolicyMask(savedPolicyMask);
1060                }
1061            }
1062
1063            if ((info.policy & PENALTY_DEATH) != 0) {
1064                System.err.println("StrictMode policy violation with POLICY_DEATH; shutting down.");
1065                Process.killProcess(Process.myPid());
1066                System.exit(10);
1067            }
1068        }
1069    }
1070
1071    /**
1072     * In the common case, as set by conditionallyEnableDebugLogging,
1073     * we're just dropboxing any violations but not showing a dialog,
1074     * not loggging, and not killing the process.  In these cases we
1075     * don't need to do a synchronous call to the ActivityManager.
1076     * This is used by both per-thread and vm-wide violations when
1077     * applicable.
1078     */
1079    private static void dropboxViolationAsync(
1080            final int violationMaskSubset, final ViolationInfo info) {
1081        int outstanding = sDropboxCallsInFlight.incrementAndGet();
1082        if (outstanding > 20) {
1083            // What's going on?  Let's not make make the situation
1084            // worse and just not log.
1085            sDropboxCallsInFlight.decrementAndGet();
1086            return;
1087        }
1088
1089        if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1090
1091        new Thread("callActivityManagerForStrictModeDropbox") {
1092            public void run() {
1093                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1094                try {
1095                    IActivityManager am = ActivityManagerNative.getDefault();
1096                    if (am == null) {
1097                        Log.d(TAG, "No activity manager; failed to Dropbox violation.");
1098                    } else {
1099                        am.handleApplicationStrictModeViolation(
1100                            RuntimeInit.getApplicationObject(),
1101                            violationMaskSubset,
1102                            info);
1103                    }
1104                } catch (RemoteException e) {
1105                    Log.e(TAG, "RemoteException handling StrictMode violation", e);
1106                }
1107                int outstanding = sDropboxCallsInFlight.decrementAndGet();
1108                if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
1109            }
1110        }.start();
1111    }
1112
1113    private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
1114        public void report (String message, Throwable allocationSite) {
1115            onVmPolicyViolation(message, allocationSite);
1116        }
1117    }
1118
1119    /**
1120     * Called from Parcel.writeNoException()
1121     */
1122    /* package */ static boolean hasGatheredViolations() {
1123        return gatheredViolations.get() != null;
1124    }
1125
1126    /**
1127     * Called from Parcel.writeException(), so we drop this memory and
1128     * don't incorrectly attribute it to the wrong caller on the next
1129     * Binder call on this thread.
1130     */
1131    /* package */ static void clearGatheredViolations() {
1132        gatheredViolations.set(null);
1133    }
1134
1135    /**
1136     * Sets the policy for what actions in the VM process (on any
1137     * thread) should be detected, as well as the penalty if such
1138     * actions occur.
1139     *
1140     * @param policy the policy to put into place
1141     */
1142    public static void setVmPolicy(final VmPolicy policy) {
1143        sVmPolicyMask = policy.mask;
1144        setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
1145    }
1146
1147    /**
1148     * Gets the current VM policy.
1149     */
1150    public static VmPolicy getVmPolicy() {
1151        return new VmPolicy(sVmPolicyMask);
1152    }
1153
1154    /**
1155     * Enable the recommended StrictMode defaults, with violations just being logged.
1156     *
1157     * <p>This catches disk and network access on the main thread, as
1158     * well as leaked SQLite cursors and unclosed resources.  This is
1159     * simply a wrapper around {@link #setVmPolicy} and {@link
1160     * #setThreadPolicy}.
1161     */
1162    public static void enableDefaults() {
1163        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
1164                                   .detectAll()
1165                                   .penaltyLog()
1166                                   .build());
1167        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
1168                               .detectLeakedSqlLiteObjects()
1169                               .detectLeakedClosableObjects()
1170                               .penaltyLog()
1171                               .build());
1172    }
1173
1174    /**
1175     * @hide
1176     */
1177    public static boolean vmSqliteObjectLeaksEnabled() {
1178        return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
1179    }
1180
1181    /**
1182     * @hide
1183     */
1184    public static boolean vmClosableObjectLeaksEnabled() {
1185        return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
1186    }
1187
1188    /**
1189     * @hide
1190     */
1191    public static void onSqliteObjectLeaked(String message, Throwable originStack) {
1192        onVmPolicyViolation(message, originStack);
1193    }
1194
1195    /**
1196     * @hide
1197     */
1198    public static void onVmPolicyViolation(String message, Throwable originStack) {
1199        if ((sVmPolicyMask & PENALTY_LOG) != 0) {
1200            Log.e(TAG, message, originStack);
1201        }
1202
1203        boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
1204        boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0;
1205
1206        int violationMaskSubset = PENALTY_DROPBOX | DETECT_VM_CURSOR_LEAKS;
1207        ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
1208
1209        if (penaltyDropbox && !penaltyDeath) {
1210            // Common case for userdebug/eng builds.  If no death and
1211            // just dropboxing, we can do the ActivityManager call
1212            // asynchronously.
1213            dropboxViolationAsync(violationMaskSubset, info);
1214            return;
1215        }
1216
1217        if (penaltyDropbox) {
1218            // The violationMask, passed to ActivityManager, is a
1219            // subset of the original StrictMode policy bitmask, with
1220            // only the bit violated and penalty bits to be executed
1221            // by the ActivityManagerService remaining set.
1222            final int savedPolicyMask = getThreadPolicyMask();
1223            try {
1224                // First, remove any policy before we call into the Activity Manager,
1225                // otherwise we'll infinite recurse as we try to log policy violations
1226                // to disk, thus violating policy, thus requiring logging, etc...
1227                // We restore the current policy below, in the finally block.
1228                setThreadPolicyMask(0);
1229
1230                ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1231                    RuntimeInit.getApplicationObject(),
1232                    violationMaskSubset,
1233                    info);
1234            } catch (RemoteException e) {
1235                Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1236            } finally {
1237                // Restore the policy.
1238                setThreadPolicyMask(savedPolicyMask);
1239            }
1240        }
1241
1242        if (penaltyDeath) {
1243            System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
1244            Process.killProcess(Process.myPid());
1245            System.exit(10);
1246        }
1247    }
1248
1249    /**
1250     * Called from Parcel.writeNoException()
1251     */
1252    /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
1253        ArrayList<ViolationInfo> violations = gatheredViolations.get();
1254        if (violations == null) {
1255            p.writeInt(0);
1256        } else {
1257            p.writeInt(violations.size());
1258            for (int i = 0; i < violations.size(); ++i) {
1259                violations.get(i).writeToParcel(p, 0 /* unused flags? */);
1260            }
1261            if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
1262            violations.clear(); // somewhat redundant, as we're about to null the threadlocal
1263        }
1264        gatheredViolations.set(null);
1265    }
1266
1267    private static class LogStackTrace extends Exception {}
1268
1269    /**
1270     * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
1271     * we here read back all the encoded violations.
1272     */
1273    /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
1274        // Our own stack trace to append
1275        StringWriter sw = new StringWriter();
1276        new LogStackTrace().printStackTrace(new PrintWriter(sw));
1277        String ourStack = sw.toString();
1278
1279        int policyMask = getThreadPolicyMask();
1280        boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
1281
1282        int numViolations = p.readInt();
1283        for (int i = 0; i < numViolations; ++i) {
1284            if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call.  i=" + i);
1285            ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
1286            info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
1287            BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1288            if (policy instanceof AndroidBlockGuardPolicy) {
1289                ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
1290            }
1291        }
1292    }
1293
1294    /**
1295     * Called from android_util_Binder.cpp's
1296     * android_os_Parcel_enforceInterface when an incoming Binder call
1297     * requires changing the StrictMode policy mask.  The role of this
1298     * function is to ask Binder for its current (native) thread-local
1299     * policy value and synchronize it to libcore's (Java)
1300     * thread-local policy value.
1301     */
1302    private static void onBinderStrictModePolicyChange(int newPolicy) {
1303        setBlockGuardPolicy(newPolicy);
1304    }
1305
1306    /**
1307     * A tracked, critical time span.  (e.g. during an animation.)
1308     *
1309     * The object itself is a linked list node, to avoid any allocations
1310     * during rapid span entries and exits.
1311     *
1312     * @hide
1313     */
1314    public static class Span {
1315        private String mName;
1316        private long mCreateMillis;
1317        private Span mNext;
1318        private Span mPrev;  // not used when in freeList, only active
1319        private final ThreadSpanState mContainerState;
1320
1321        Span(ThreadSpanState threadState) {
1322            mContainerState = threadState;
1323        }
1324
1325        // Empty constructor for the NO_OP_SPAN
1326        protected Span() {
1327            mContainerState = null;
1328        }
1329
1330        /**
1331         * To be called when the critical span is complete (i.e. the
1332         * animation is done animating).  This can be called on any
1333         * thread (even a different one from where the animation was
1334         * taking place), but that's only a defensive implementation
1335         * measure.  It really makes no sense for you to call this on
1336         * thread other than that where you created it.
1337         *
1338         * @hide
1339         */
1340        public void finish() {
1341            ThreadSpanState state = mContainerState;
1342            synchronized (state) {
1343                if (mName == null) {
1344                    // Duplicate finish call.  Ignore.
1345                    return;
1346                }
1347
1348                // Remove ourselves from the active list.
1349                if (mPrev != null) {
1350                    mPrev.mNext = mNext;
1351                }
1352                if (mNext != null) {
1353                    mNext.mPrev = mPrev;
1354                }
1355                if (state.mActiveHead == this) {
1356                    state.mActiveHead = mNext;
1357                }
1358
1359                state.mActiveSize--;
1360
1361                if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
1362
1363                this.mCreateMillis = -1;
1364                this.mName = null;
1365                this.mPrev = null;
1366                this.mNext = null;
1367
1368                // Add ourselves to the freeList, if it's not already
1369                // too big.
1370                if (state.mFreeListSize < 5) {
1371                    this.mNext = state.mFreeListHead;
1372                    state.mFreeListHead = this;
1373                    state.mFreeListSize++;
1374                }
1375            }
1376        }
1377    }
1378
1379    // The no-op span that's used in user builds.
1380    private static final Span NO_OP_SPAN = new Span() {
1381            public void finish() {
1382                // Do nothing.
1383            }
1384        };
1385
1386    /**
1387     * Linked lists of active spans and a freelist.
1388     *
1389     * Locking notes: there's one of these structures per thread and
1390     * all members of this structure (as well as the Span nodes under
1391     * it) are guarded by the ThreadSpanState object instance.  While
1392     * in theory there'd be no locking required because it's all local
1393     * per-thread, the finish() method above is defensive against
1394     * people calling it on a different thread from where they created
1395     * the Span, hence the locking.
1396     */
1397    private static class ThreadSpanState {
1398        public Span mActiveHead;    // doubly-linked list.
1399        public int mActiveSize;
1400        public Span mFreeListHead;  // singly-linked list.  only changes at head.
1401        public int mFreeListSize;
1402    }
1403
1404    private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
1405            new ThreadLocal<ThreadSpanState>() {
1406        @Override protected ThreadSpanState initialValue() {
1407            return new ThreadSpanState();
1408        }
1409    };
1410
1411    private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
1412        protected IWindowManager create() {
1413            return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
1414        }
1415    };
1416
1417    /**
1418     * Enter a named critical span (e.g. an animation)
1419     *
1420     * <p>The name is an arbitary label (or tag) that will be applied
1421     * to any strictmode violation that happens while this span is
1422     * active.  You must call finish() on the span when done.
1423     *
1424     * <p>This will never return null, but on devices without debugging
1425     * enabled, this may return a dummy object on which the finish()
1426     * method is a no-op.
1427     *
1428     * <p>TODO: add CloseGuard to this, verifying callers call finish.
1429     *
1430     * @hide
1431     */
1432    public static Span enterCriticalSpan(String name) {
1433        if (IS_USER_BUILD) {
1434            return NO_OP_SPAN;
1435        }
1436        if (name == null || name.isEmpty()) {
1437            throw new IllegalArgumentException("name must be non-null and non-empty");
1438        }
1439        ThreadSpanState state = sThisThreadSpanState.get();
1440        Span span = null;
1441        synchronized (state) {
1442            if (state.mFreeListHead != null) {
1443                span = state.mFreeListHead;
1444                state.mFreeListHead = span.mNext;
1445                state.mFreeListSize--;
1446            } else {
1447                // Shouldn't have to do this often.
1448                span = new Span(state);
1449            }
1450            span.mName = name;
1451            span.mCreateMillis = SystemClock.uptimeMillis();
1452            span.mNext = state.mActiveHead;
1453            span.mPrev = null;
1454            state.mActiveHead = span;
1455            state.mActiveSize++;
1456            if (span.mNext != null) {
1457                span.mNext.mPrev = span;
1458            }
1459            if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
1460        }
1461        return span;
1462    }
1463
1464
1465    /**
1466     * Parcelable that gets sent in Binder call headers back to callers
1467     * to report violations that happened during a cross-process call.
1468     *
1469     * @hide
1470     */
1471    public static class ViolationInfo {
1472        /**
1473         * Stack and other stuff info.
1474         */
1475        public final ApplicationErrorReport.CrashInfo crashInfo;
1476
1477        /**
1478         * The strict mode policy mask at the time of violation.
1479         */
1480        public final int policy;
1481
1482        /**
1483         * The wall time duration of the violation, when known.  -1 when
1484         * not known.
1485         */
1486        public int durationMillis = -1;
1487
1488        /**
1489         * The number of animations currently running.
1490         */
1491        public int numAnimationsRunning = 0;
1492
1493        /**
1494         * List of tags from active Span instances during this
1495         * violation, or null for none.
1496         */
1497        public String[] tags;
1498
1499        /**
1500         * Which violation number this was (1-based) since the last Looper loop,
1501         * from the perspective of the root caller (if it crossed any processes
1502         * via Binder calls).  The value is 0 if the root caller wasn't on a Looper
1503         * thread.
1504         */
1505        public int violationNumThisLoop;
1506
1507        /**
1508         * The time (in terms of SystemClock.uptimeMillis()) that the
1509         * violation occurred.
1510         */
1511        public long violationUptimeMillis;
1512
1513        /**
1514         * The action of the Intent being broadcast to somebody's onReceive
1515         * on this thread right now, or null.
1516         */
1517        public String broadcastIntentAction;
1518
1519        /**
1520         * Create an uninitialized instance of ViolationInfo
1521         */
1522        public ViolationInfo() {
1523            crashInfo = null;
1524            policy = 0;
1525        }
1526
1527        /**
1528         * Create an instance of ViolationInfo initialized from an exception.
1529         */
1530        public ViolationInfo(Throwable tr, int policy) {
1531            crashInfo = new ApplicationErrorReport.CrashInfo(tr);
1532            violationUptimeMillis = SystemClock.uptimeMillis();
1533            this.policy = policy;
1534            this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
1535            Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
1536            if (broadcastIntent != null) {
1537                broadcastIntentAction = broadcastIntent.getAction();
1538            }
1539            ThreadSpanState state = sThisThreadSpanState.get();
1540            synchronized (state) {
1541                int spanActiveCount = state.mActiveSize;
1542                if (spanActiveCount > MAX_SPAN_TAGS) {
1543                    spanActiveCount = MAX_SPAN_TAGS;
1544                }
1545                if (spanActiveCount != 0) {
1546                    this.tags = new String[spanActiveCount];
1547                    Span iter = state.mActiveHead;
1548                    int index = 0;
1549                    while (iter != null && index < spanActiveCount) {
1550                        this.tags[index] = iter.mName;
1551                        index++;
1552                        iter = iter.mNext;
1553                    }
1554                }
1555            }
1556        }
1557
1558        @Override
1559        public int hashCode() {
1560            int result = 17;
1561            result = 37 * result + crashInfo.stackTrace.hashCode();
1562            if (numAnimationsRunning != 0) {
1563                result *= 37;
1564            }
1565            if (broadcastIntentAction != null) {
1566                result = 37 * result + broadcastIntentAction.hashCode();
1567            }
1568            if (tags != null) {
1569                for (String tag : tags) {
1570                    result = 37 * result + tag.hashCode();
1571                }
1572            }
1573            return result;
1574        }
1575
1576        /**
1577         * Create an instance of ViolationInfo initialized from a Parcel.
1578         */
1579        public ViolationInfo(Parcel in) {
1580            this(in, false);
1581        }
1582
1583        /**
1584         * Create an instance of ViolationInfo initialized from a Parcel.
1585         *
1586         * @param unsetGatheringBit if true, the caller is the root caller
1587         *   and the gathering penalty should be removed.
1588         */
1589        public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
1590            crashInfo = new ApplicationErrorReport.CrashInfo(in);
1591            int rawPolicy = in.readInt();
1592            if (unsetGatheringBit) {
1593                policy = rawPolicy & ~PENALTY_GATHER;
1594            } else {
1595                policy = rawPolicy;
1596            }
1597            durationMillis = in.readInt();
1598            violationNumThisLoop = in.readInt();
1599            numAnimationsRunning = in.readInt();
1600            violationUptimeMillis = in.readLong();
1601            broadcastIntentAction = in.readString();
1602            tags = in.readStringArray();
1603        }
1604
1605        /**
1606         * Save a ViolationInfo instance to a parcel.
1607         */
1608        public void writeToParcel(Parcel dest, int flags) {
1609            crashInfo.writeToParcel(dest, flags);
1610            dest.writeInt(policy);
1611            dest.writeInt(durationMillis);
1612            dest.writeInt(violationNumThisLoop);
1613            dest.writeInt(numAnimationsRunning);
1614            dest.writeLong(violationUptimeMillis);
1615            dest.writeString(broadcastIntentAction);
1616            dest.writeStringArray(tags);
1617        }
1618
1619
1620        /**
1621         * Dump a ViolationInfo instance to a Printer.
1622         */
1623        public void dump(Printer pw, String prefix) {
1624            crashInfo.dump(pw, prefix);
1625            pw.println(prefix + "policy: " + policy);
1626            if (durationMillis != -1) {
1627                pw.println(prefix + "durationMillis: " + durationMillis);
1628            }
1629            if (violationNumThisLoop != 0) {
1630                pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
1631            }
1632            if (numAnimationsRunning != 0) {
1633                pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
1634            }
1635            pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
1636            if (broadcastIntentAction != null) {
1637                pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
1638            }
1639            if (tags != null) {
1640                int index = 0;
1641                for (String tag : tags) {
1642                    pw.println(prefix + "tag[" + (index++) + "]: " + tag);
1643                }
1644            }
1645        }
1646
1647    }
1648}
1649