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