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