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