• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.annotation.TestApi;
20 import android.app.ActivityManager;
21 import android.app.ActivityThread;
22 import android.app.ApplicationErrorReport;
23 import android.app.IActivityManager;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.ServiceConnection;
28 import android.net.TrafficStats;
29 import android.net.Uri;
30 import android.util.ArrayMap;
31 import android.util.Log;
32 import android.util.Printer;
33 import android.util.Singleton;
34 import android.util.Slog;
35 import android.view.IWindowManager;
36 
37 import com.android.internal.os.RuntimeInit;
38 import com.android.internal.util.FastPrintWriter;
39 import com.android.internal.util.HexDump;
40 
41 import dalvik.system.BlockGuard;
42 import dalvik.system.CloseGuard;
43 import dalvik.system.VMDebug;
44 import dalvik.system.VMRuntime;
45 
46 import java.io.PrintWriter;
47 import java.io.StringWriter;
48 import java.net.InetAddress;
49 import java.net.UnknownHostException;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.HashMap;
53 import java.util.concurrent.atomic.AtomicInteger;
54 
55 /**
56  * <p>StrictMode is a developer tool which detects things you might be
57  * doing by accident and brings them to your attention so you can fix
58  * them.
59  *
60  * <p>StrictMode is most commonly used to catch accidental disk or
61  * network access on the application's main thread, where UI
62  * operations are received and animations take place.  Keeping disk
63  * and network operations off the main thread makes for much smoother,
64  * more responsive applications.  By keeping your application's main thread
65  * responsive, you also prevent
66  * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
67  * from being shown to users.
68  *
69  * <p class="note">Note that even though an Android device's disk is
70  * often on flash memory, many devices run a filesystem on top of that
71  * memory with very limited concurrency.  It's often the case that
72  * almost all disk accesses are fast, but may in individual cases be
73  * dramatically slower when certain I/O is happening in the background
74  * from other processes.  If possible, it's best to assume that such
75  * things are not fast.</p>
76  *
77  * <p>Example code to enable from early in your
78  * {@link android.app.Application}, {@link android.app.Activity}, or
79  * other application component's
80  * {@link android.app.Application#onCreate} method:
81  *
82  * <pre>
83  * public void onCreate() {
84  *     if (DEVELOPER_MODE) {
85  *         StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
86  *                 .detectDiskReads()
87  *                 .detectDiskWrites()
88  *                 .detectNetwork()   // or .detectAll() for all detectable problems
89  *                 .penaltyLog()
90  *                 .build());
91  *         StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
92  *                 .detectLeakedSqlLiteObjects()
93  *                 .detectLeakedClosableObjects()
94  *                 .penaltyLog()
95  *                 .penaltyDeath()
96  *                 .build());
97  *     }
98  *     super.onCreate();
99  * }
100  * </pre>
101  *
102  * <p>You can decide what should happen when a violation is detected.
103  * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can
104  * watch the output of <code>adb logcat</code> while you use your
105  * application to see the violations as they happen.
106  *
107  * <p>If you find violations that you feel are problematic, there are
108  * a variety of tools to help solve them: threads, {@link android.os.Handler},
109  * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
110  * But don't feel compelled to fix everything that StrictMode finds.  In particular,
111  * many cases of disk access are often necessary during the normal activity lifecycle.  Use
112  * StrictMode to find things you did by accident.  Network requests on the UI thread
113  * are almost always a problem, though.
114  *
115  * <p class="note">StrictMode is not a security mechanism and is not
116  * guaranteed to find all disk or network accesses.  While it does
117  * propagate its state across process boundaries when doing
118  * {@link android.os.Binder} calls, it's still ultimately a best
119  * effort mechanism.  Notably, disk or network access from JNI calls
120  * won't necessarily trigger it.  Future versions of Android may catch
121  * more (or fewer) operations, so you should never leave StrictMode
122  * enabled in applications distributed on Google Play.
123  */
124 public final class StrictMode {
125     private static final String TAG = "StrictMode";
126     private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
127 
128     /**
129      * Boolean system property to disable strict mode checks outright.
130      * Set this to 'true' to force disable; 'false' has no effect on other
131      * enable/disable policy.
132      * @hide
133      */
134     public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
135 
136     /**
137      * The boolean system property to control screen flashes on violations.
138      *
139      * @hide
140      */
141     public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
142 
143     /**
144      * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK}
145      * in {@link VmPolicy.Builder#detectAll()}. Apps can still always opt-into
146      * detection using {@link VmPolicy.Builder#detectCleartextNetwork()}.
147      */
148     private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.clear";
149 
150     // Only log a duplicate stack trace to the logs every second.
151     private static final long MIN_LOG_INTERVAL_MS = 1000;
152 
153     // Only show an annoying dialog at most every 30 seconds
154     private static final long MIN_DIALOG_INTERVAL_MS = 30000;
155 
156     // How many Span tags (e.g. animations) to report.
157     private static final int MAX_SPAN_TAGS = 20;
158 
159     // How many offending stacks to keep track of (and time) per loop
160     // of the Looper.
161     private static final int MAX_OFFENSES_PER_LOOP = 10;
162 
163     // Byte 1: Thread-policy
164 
165     /**
166      * @hide
167      */
168     public static final int DETECT_DISK_WRITE = 0x01;  // for ThreadPolicy
169 
170     /**
171       * @hide
172      */
173     public static final int DETECT_DISK_READ = 0x02;  // for ThreadPolicy
174 
175     /**
176      * @hide
177      */
178     public static final int DETECT_NETWORK = 0x04;  // for ThreadPolicy
179 
180     /**
181      * For StrictMode.noteSlowCall()
182      *
183      * @hide
184      */
185     public static final int DETECT_CUSTOM = 0x08;  // for ThreadPolicy
186 
187     /**
188      * For StrictMode.noteResourceMismatch()
189      *
190      * @hide
191      */
192     public static final int DETECT_RESOURCE_MISMATCH = 0x10;  // for ThreadPolicy
193 
194     /**
195      * @hide
196      */
197     public static final int DETECT_UNBUFFERED_IO = 0x20;  // for ThreadPolicy
198 
199     private static final int ALL_THREAD_DETECT_BITS =
200             DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM |
201             DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO;
202 
203     // Byte 2: Process-policy
204 
205     /**
206      * Note, a "VM_" bit, not thread.
207      * @hide
208      */
209     public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8;  // for VmPolicy
210 
211     /**
212      * Note, a "VM_" bit, not thread.
213      * @hide
214      */
215     public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8;  // for VmPolicy
216 
217     /**
218      * Note, a "VM_" bit, not thread.
219      * @hide
220      */
221     public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8;  // for VmPolicy
222 
223     /**
224      * @hide
225      */
226     private static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8;  // for VmPolicy
227 
228     /**
229      * @hide
230      */
231     public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8;  // for VmPolicy
232 
233     /**
234      * @hide
235      */
236     private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8;  // for VmPolicy
237 
238     /**
239      * @hide
240      */
241     private static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8;  // for VmPolicy
242 
243     /**
244      * @hide
245      */
246     private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8;  // for VmPolicy
247 
248     /**
249      * @hide
250      */
251     private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24;  // for VmPolicy
252 
253     private static final int ALL_VM_DETECT_BITS =
254             DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
255             DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
256             DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE |
257             DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION |
258             DETECT_VM_UNTAGGED_SOCKET;
259 
260     // Byte 3: Penalty
261 
262     /** {@hide} */
263     public static final int PENALTY_LOG = 0x01 << 16;  // normal android.util.Log
264     /** {@hide} */
265     public static final int PENALTY_DIALOG = 0x02 << 16;
266     /** {@hide} */
267     public static final int PENALTY_DEATH = 0x04 << 16;
268     /** {@hide} */
269     public static final int PENALTY_FLASH = 0x10 << 16;
270     /** {@hide} */
271     public static final int PENALTY_DROPBOX = 0x20 << 16;
272 
273     /**
274      * Non-public penalty mode which overrides all the other penalty
275      * bits and signals that we're in a Binder call and we should
276      * ignore the other penalty bits and instead serialize back all
277      * our offending stack traces to the caller to ultimately handle
278      * in the originating process.
279      *
280      * This must be kept in sync with the constant in libs/binder/Parcel.cpp
281      *
282      * @hide
283      */
284     public static final int PENALTY_GATHER = 0x40 << 16;
285 
286     // Byte 4: Special cases
287 
288     /**
289      * Death when network traffic is detected on main thread.
290      *
291      * @hide
292      */
293     public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
294 
295     /**
296      * Death when cleartext network traffic is detected.
297      *
298      * @hide
299      */
300     public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
301 
302     /**
303      * Death when file exposure is detected.
304      *
305      * @hide
306      */
307     public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
308 
309     // CAUTION: we started stealing the top bits of Byte 4 for VM above
310 
311     /**
312      * Mask of all the penalty bits valid for thread policies.
313      */
314     private static final int THREAD_PENALTY_MASK =
315             PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
316             PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;
317 
318     /**
319      * Mask of all the penalty bits valid for VM policies.
320      */
321     private static final int VM_PENALTY_MASK = PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX
322             | PENALTY_DEATH_ON_CLEARTEXT_NETWORK | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
323 
324     /** {@hide} */
325     public static final int NETWORK_POLICY_ACCEPT = 0;
326     /** {@hide} */
327     public static final int NETWORK_POLICY_LOG = 1;
328     /** {@hide} */
329     public static final int NETWORK_POLICY_REJECT = 2;
330 
331     // TODO: wrap in some ImmutableHashMap thing.
332     // Note: must be before static initialization of sVmPolicy.
333     private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP = new HashMap<Class, Integer>();
334 
335     /**
336      * The current VmPolicy in effect.
337      *
338      * TODO: these are redundant (mask is in VmPolicy).  Should remove sVmPolicyMask.
339      */
340     private static volatile int sVmPolicyMask = 0;
341     private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
342 
343     /** {@hide} */
344     @TestApi
345     public interface ViolationListener {
onViolation(String message)346         public void onViolation(String message);
347     }
348 
349     private static volatile ViolationListener sListener;
350 
351     /** {@hide} */
352     @TestApi
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 an explicit 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 && (Build.IS_USER || 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 (Build.IS_ENG) {
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 (!Build.IS_USER) {
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 (Build.IS_USER) {
1220             setCloseGuardEnabled(false);
1221         } else {
1222             VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll();
1223             if (!Build.IS_ENG) {
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 (Build.IS_ENG) {
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.enable(DETECT_VM_UNTAGGED_SOCKET);
1236             } else {
1237                 policyBuilder.disable(DETECT_VM_UNTAGGED_SOCKET);
1238             }
1239             setVmPolicy(policyBuilder.build());
1240             setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
1241         }
1242         return true;
1243     }
1244 
1245     /**
1246      * Used by the framework to make network usage on the main
1247      * thread a fatal error.
1248      *
1249      * @hide
1250      */
enableDeathOnNetwork()1251     public static void enableDeathOnNetwork() {
1252         int oldPolicy = getThreadPolicyMask();
1253         int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
1254         setThreadPolicyMask(newPolicy);
1255     }
1256 
1257     /**
1258      * Used by the framework to make file usage a fatal error.
1259      *
1260      * @hide
1261      */
enableDeathOnFileUriExposure()1262     public static void enableDeathOnFileUriExposure() {
1263         sVmPolicyMask |= DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
1264     }
1265 
1266     /**
1267      * Used by lame internal apps that haven't done the hard work to get
1268      * themselves off file:// Uris yet.
1269      *
1270      * @hide
1271      */
disableDeathOnFileUriExposure()1272     public static void disableDeathOnFileUriExposure() {
1273         sVmPolicyMask &= ~(DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
1274     }
1275 
1276     /**
1277      * Parses the BlockGuard policy mask out from the Exception's
1278      * getMessage() String value.  Kinda gross, but least
1279      * invasive.  :/
1280      *
1281      * Input is of the following forms:
1282      *     "policy=137 violation=64"
1283      *     "policy=137 violation=64 msg=Arbitrary text"
1284      *
1285      * Returns 0 on failure, which is a valid policy, but not a
1286      * valid policy during a violation (else there must've been
1287      * some policy in effect to violate).
1288      */
parsePolicyFromMessage(String message)1289     private static int parsePolicyFromMessage(String message) {
1290         if (message == null || !message.startsWith("policy=")) {
1291             return 0;
1292         }
1293         int spaceIndex = message.indexOf(' ');
1294         if (spaceIndex == -1) {
1295             return 0;
1296         }
1297         String policyString = message.substring(7, spaceIndex);
1298         try {
1299             return Integer.parseInt(policyString);
1300         } catch (NumberFormatException e) {
1301             return 0;
1302         }
1303     }
1304 
1305     /**
1306      * Like parsePolicyFromMessage(), but returns the violation.
1307      */
parseViolationFromMessage(String message)1308     private static int parseViolationFromMessage(String message) {
1309         if (message == null) {
1310             return 0;
1311         }
1312         int violationIndex = message.indexOf("violation=");
1313         if (violationIndex == -1) {
1314             return 0;
1315         }
1316         int numberStartIndex = violationIndex + "violation=".length();
1317         int numberEndIndex = message.indexOf(' ', numberStartIndex);
1318         if (numberEndIndex == -1) {
1319             numberEndIndex = message.length();
1320         }
1321         String violationString = message.substring(numberStartIndex, numberEndIndex);
1322         try {
1323             return Integer.parseInt(violationString);
1324         } catch (NumberFormatException e) {
1325             return 0;
1326         }
1327     }
1328 
1329     private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
1330             new ThreadLocal<ArrayList<ViolationInfo>>() {
1331         @Override protected ArrayList<ViolationInfo> initialValue() {
1332             return new ArrayList<ViolationInfo>();
1333         }
1334     };
1335 
1336     // Note: only access this once verifying the thread has a Looper.
1337     private static final ThreadLocal<Handler> threadHandler = new ThreadLocal<Handler>() {
1338         @Override protected Handler initialValue() {
1339             return new Handler();
1340         }
1341     };
1342 
1343     private static final ThreadLocal<AndroidBlockGuardPolicy>
1344             threadAndroidPolicy = new ThreadLocal<AndroidBlockGuardPolicy>() {
1345         @Override
1346         protected AndroidBlockGuardPolicy initialValue() {
1347             return new AndroidBlockGuardPolicy(0);
1348         }
1349     };
1350 
tooManyViolationsThisLoop()1351     private static boolean tooManyViolationsThisLoop() {
1352         return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
1353     }
1354 
1355     private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
1356         private int mPolicyMask;
1357 
1358         // Map from violation stacktrace hashcode -> uptimeMillis of
1359         // last violation.  No locking needed, as this is only
1360         // accessed by the same thread.
1361         private ArrayMap<Integer, Long> mLastViolationTime;
1362 
AndroidBlockGuardPolicy(final int policyMask)1363         public AndroidBlockGuardPolicy(final int policyMask) {
1364             mPolicyMask = policyMask;
1365         }
1366 
1367         @Override
toString()1368         public String toString() {
1369             return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
1370         }
1371 
1372         // Part of BlockGuard.Policy interface:
getPolicyMask()1373         public int getPolicyMask() {
1374             return mPolicyMask;
1375         }
1376 
1377         // Part of BlockGuard.Policy interface:
onWriteToDisk()1378         public void onWriteToDisk() {
1379             if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
1380                 return;
1381             }
1382             if (tooManyViolationsThisLoop()) {
1383                 return;
1384             }
1385             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
1386             e.fillInStackTrace();
1387             startHandlingViolationException(e);
1388         }
1389 
1390         // Not part of BlockGuard.Policy; just part of StrictMode:
onCustomSlowCall(String name)1391         void onCustomSlowCall(String name) {
1392             if ((mPolicyMask & DETECT_CUSTOM) == 0) {
1393                 return;
1394             }
1395             if (tooManyViolationsThisLoop()) {
1396                 return;
1397             }
1398             BlockGuard.BlockGuardPolicyException e = new StrictModeCustomViolation(mPolicyMask, name);
1399             e.fillInStackTrace();
1400             startHandlingViolationException(e);
1401         }
1402 
1403         // Not part of BlockGuard.Policy; just part of StrictMode:
onResourceMismatch(Object tag)1404         void onResourceMismatch(Object tag) {
1405             if ((mPolicyMask & DETECT_RESOURCE_MISMATCH) == 0) {
1406                 return;
1407             }
1408             if (tooManyViolationsThisLoop()) {
1409                 return;
1410             }
1411             BlockGuard.BlockGuardPolicyException e =
1412                     new StrictModeResourceMismatchViolation(mPolicyMask, tag);
1413             e.fillInStackTrace();
1414             startHandlingViolationException(e);
1415         }
1416 
1417         // Part of BlockGuard.Policy; just part of StrictMode:
onUnbufferedIO()1418         public void onUnbufferedIO() {
1419             if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
1420                 return;
1421             }
1422             if (tooManyViolationsThisLoop()) {
1423                 return;
1424             }
1425             BlockGuard.BlockGuardPolicyException e =
1426                     new StrictModeUnbufferedIOViolation(mPolicyMask);
1427             e.fillInStackTrace();
1428             startHandlingViolationException(e);
1429         }
1430 
1431         // Part of BlockGuard.Policy interface:
onReadFromDisk()1432         public void onReadFromDisk() {
1433             if ((mPolicyMask & DETECT_DISK_READ) == 0) {
1434                 return;
1435             }
1436             if (tooManyViolationsThisLoop()) {
1437                 return;
1438             }
1439             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
1440             e.fillInStackTrace();
1441             startHandlingViolationException(e);
1442         }
1443 
1444         // Part of BlockGuard.Policy interface:
onNetwork()1445         public void onNetwork() {
1446             if ((mPolicyMask & DETECT_NETWORK) == 0) {
1447                 return;
1448             }
1449             if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
1450                 throw new NetworkOnMainThreadException();
1451             }
1452             if (tooManyViolationsThisLoop()) {
1453                 return;
1454             }
1455             BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
1456             e.fillInStackTrace();
1457             startHandlingViolationException(e);
1458         }
1459 
setPolicyMask(int policyMask)1460         public void setPolicyMask(int policyMask) {
1461             mPolicyMask = policyMask;
1462         }
1463 
1464         // Start handling a violation that just started and hasn't
1465         // actually run yet (e.g. no disk write or network operation
1466         // has yet occurred).  This sees if we're in an event loop
1467         // thread and, if so, uses it to roughly measure how long the
1468         // violation took.
startHandlingViolationException(BlockGuard.BlockGuardPolicyException e)1469         void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) {
1470             final ViolationInfo info = new ViolationInfo(e, e.getPolicy());
1471             info.violationUptimeMillis = SystemClock.uptimeMillis();
1472             handleViolationWithTimingAttempt(info);
1473         }
1474 
1475         // Attempts to fill in the provided ViolationInfo's
1476         // durationMillis field if this thread has a Looper we can use
1477         // to measure with.  We measure from the time of violation
1478         // until the time the looper is idle again (right before
1479         // the next epoll_wait)
handleViolationWithTimingAttempt(final ViolationInfo info)1480         void handleViolationWithTimingAttempt(final ViolationInfo info) {
1481             Looper looper = Looper.myLooper();
1482 
1483             // Without a Looper, we're unable to time how long the
1484             // violation takes place.  This case should be rare, as
1485             // most users will care about timing violations that
1486             // happen on their main UI thread.  Note that this case is
1487             // also hit when a violation takes place in a Binder
1488             // thread, in "gather" mode.  In this case, the duration
1489             // of the violation is computed by the ultimate caller and
1490             // its Looper, if any.
1491             //
1492             // Also, as a special short-cut case when the only penalty
1493             // bit is death, we die immediately, rather than timing
1494             // the violation's duration.  This makes it convenient to
1495             // use in unit tests too, rather than waiting on a Looper.
1496             //
1497             // TODO: if in gather mode, ignore Looper.myLooper() and always
1498             //       go into this immediate mode?
1499             if (looper == null ||
1500                 (info.policy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
1501                 info.durationMillis = -1;  // unknown (redundant, already set)
1502                 handleViolation(info);
1503                 return;
1504             }
1505 
1506             final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
1507             if (records.size() >= MAX_OFFENSES_PER_LOOP) {
1508                 // Not worth measuring.  Too many offenses in one loop.
1509                 return;
1510             }
1511             records.add(info);
1512             if (records.size() > 1) {
1513                 // There's already been a violation this loop, so we've already
1514                 // registered an idle handler to process the list of violations
1515                 // at the end of this Looper's loop.
1516                 return;
1517             }
1518 
1519             final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ?
1520                     sWindowManager.get() : null;
1521             if (windowManager != null) {
1522                 try {
1523                     windowManager.showStrictModeViolation(true);
1524                 } catch (RemoteException unused) {
1525                 }
1526             }
1527 
1528             // We post a runnable to a Handler (== delay 0 ms) for
1529             // measuring the end time of a violation instead of using
1530             // an IdleHandler (as was previously used) because an
1531             // IdleHandler may not run for quite a long period of time
1532             // if an ongoing animation is happening and continually
1533             // posting ASAP (0 ms) animation steps.  Animations are
1534             // throttled back to 60fps via SurfaceFlinger/View
1535             // invalidates, _not_ by posting frame updates every 16
1536             // milliseconds.
1537             threadHandler.get().postAtFrontOfQueue(new Runnable() {
1538                     public void run() {
1539                         long loopFinishTime = SystemClock.uptimeMillis();
1540 
1541                         // Note: we do this early, before handling the
1542                         // violation below, as handling the violation
1543                         // may include PENALTY_DEATH and we don't want
1544                         // to keep the red border on.
1545                         if (windowManager != null) {
1546                             try {
1547                                 windowManager.showStrictModeViolation(false);
1548                             } catch (RemoteException unused) {
1549                             }
1550                         }
1551 
1552                         for (int n = 0; n < records.size(); ++n) {
1553                             ViolationInfo v = records.get(n);
1554                             v.violationNumThisLoop = n + 1;
1555                             v.durationMillis =
1556                                     (int) (loopFinishTime - v.violationUptimeMillis);
1557                             handleViolation(v);
1558                         }
1559                         records.clear();
1560                     }
1561                 });
1562         }
1563 
1564         // Note: It's possible (even quite likely) that the
1565         // thread-local policy mask has changed from the time the
1566         // violation fired and now (after the violating code ran) due
1567         // to people who push/pop temporary policy in regions of code,
1568         // hence the policy being passed around.
handleViolation(final ViolationInfo info)1569         void handleViolation(final ViolationInfo info) {
1570             if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) {
1571                 Log.wtf(TAG, "unexpected null stacktrace");
1572                 return;
1573             }
1574 
1575             if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy);
1576 
1577             if ((info.policy & PENALTY_GATHER) != 0) {
1578                 ArrayList<ViolationInfo> violations = gatheredViolations.get();
1579                 if (violations == null) {
1580                     violations = new ArrayList<ViolationInfo>(1);
1581                     gatheredViolations.set(violations);
1582                 }
1583                 for (ViolationInfo previous : violations) {
1584                     if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
1585                         // Duplicate. Don't log.
1586                         return;
1587                     }
1588                 }
1589                 violations.add(info);
1590                 return;
1591             }
1592 
1593             // Not perfect, but fast and good enough for dup suppression.
1594             Integer crashFingerprint = info.hashCode();
1595             long lastViolationTime = 0;
1596             if (mLastViolationTime != null) {
1597                 Long vtime = mLastViolationTime.get(crashFingerprint);
1598                 if (vtime != null) {
1599                     lastViolationTime = vtime;
1600                 }
1601             } else {
1602                 mLastViolationTime = new ArrayMap<Integer, Long>(1);
1603             }
1604             long now = SystemClock.uptimeMillis();
1605             mLastViolationTime.put(crashFingerprint, now);
1606             long timeSinceLastViolationMillis = lastViolationTime == 0 ?
1607                     Long.MAX_VALUE : (now - lastViolationTime);
1608 
1609             if ((info.policy & PENALTY_LOG) != 0 && sListener != null) {
1610                 sListener.onViolation(info.crashInfo.stackTrace);
1611             }
1612             if ((info.policy & PENALTY_LOG) != 0 &&
1613                 timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
1614                 if (info.durationMillis != -1) {
1615                     Log.d(TAG, "StrictMode policy violation; ~duration=" +
1616                           info.durationMillis + " ms: " + info.crashInfo.stackTrace);
1617                 } else {
1618                     Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
1619                 }
1620             }
1621 
1622             // The violationMaskSubset, passed to ActivityManager, is a
1623             // subset of the original StrictMode policy bitmask, with
1624             // only the bit violated and penalty bits to be executed
1625             // by the ActivityManagerService remaining set.
1626             int violationMaskSubset = 0;
1627 
1628             if ((info.policy & PENALTY_DIALOG) != 0 &&
1629                 timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
1630                 violationMaskSubset |= PENALTY_DIALOG;
1631             }
1632 
1633             if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
1634                 violationMaskSubset |= PENALTY_DROPBOX;
1635             }
1636 
1637             if (violationMaskSubset != 0) {
1638                 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1639                 violationMaskSubset |= violationBit;
1640                 final int savedPolicyMask = getThreadPolicyMask();
1641 
1642                 final boolean justDropBox = (info.policy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
1643                 if (justDropBox) {
1644                     // If all we're going to ask the activity manager
1645                     // to do is dropbox it (the common case during
1646                     // platform development), we can avoid doing this
1647                     // call synchronously which Binder data suggests
1648                     // isn't always super fast, despite the implementation
1649                     // in the ActivityManager trying to be mostly async.
1650                     dropboxViolationAsync(violationMaskSubset, info);
1651                     return;
1652                 }
1653 
1654                 // Normal synchronous call to the ActivityManager.
1655                 try {
1656                     // First, remove any policy before we call into the Activity Manager,
1657                     // otherwise we'll infinite recurse as we try to log policy violations
1658                     // to disk, thus violating policy, thus requiring logging, etc...
1659                     // We restore the current policy below, in the finally block.
1660                     setThreadPolicyMask(0);
1661 
1662                     ActivityManager.getService().handleApplicationStrictModeViolation(
1663                         RuntimeInit.getApplicationObject(),
1664                         violationMaskSubset,
1665                         info);
1666                 } catch (RemoteException e) {
1667                     if (e instanceof DeadObjectException) {
1668                         // System process is dead; ignore
1669                     } else {
1670                         Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1671                     }
1672                 } finally {
1673                     // Restore the policy.
1674                     setThreadPolicyMask(savedPolicyMask);
1675                 }
1676             }
1677 
1678             if ((info.policy & PENALTY_DEATH) != 0) {
1679                 executeDeathPenalty(info);
1680             }
1681         }
1682     }
1683 
executeDeathPenalty(ViolationInfo info)1684     private static void executeDeathPenalty(ViolationInfo info) {
1685         int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1686         throw new StrictModeViolation(info.policy, violationBit, null);
1687     }
1688 
1689     /**
1690      * In the common case, as set by conditionallyEnableDebugLogging,
1691      * we're just dropboxing any violations but not showing a dialog,
1692      * not loggging, and not killing the process.  In these cases we
1693      * don't need to do a synchronous call to the ActivityManager.
1694      * This is used by both per-thread and vm-wide violations when
1695      * applicable.
1696      */
dropboxViolationAsync( final int violationMaskSubset, final ViolationInfo info)1697     private static void dropboxViolationAsync(
1698             final int violationMaskSubset, final ViolationInfo info) {
1699         int outstanding = sDropboxCallsInFlight.incrementAndGet();
1700         if (outstanding > 20) {
1701             // What's going on?  Let's not make make the situation
1702             // worse and just not log.
1703             sDropboxCallsInFlight.decrementAndGet();
1704             return;
1705         }
1706 
1707         if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1708 
1709         new Thread("callActivityManagerForStrictModeDropbox") {
1710             public void run() {
1711                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1712                 try {
1713                     IActivityManager am = ActivityManager.getService();
1714                     if (am == null) {
1715                         Log.d(TAG, "No activity manager; failed to Dropbox violation.");
1716                     } else {
1717                         am.handleApplicationStrictModeViolation(
1718                             RuntimeInit.getApplicationObject(),
1719                             violationMaskSubset,
1720                             info);
1721                     }
1722                 } catch (RemoteException e) {
1723                     if (e instanceof DeadObjectException) {
1724                         // System process is dead; ignore
1725                     } else {
1726                         Log.e(TAG, "RemoteException handling StrictMode violation", e);
1727                     }
1728                 }
1729                 int outstanding = sDropboxCallsInFlight.decrementAndGet();
1730                 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
1731             }
1732         }.start();
1733     }
1734 
1735     private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
report(String message, Throwable allocationSite)1736         public void report(String message, Throwable allocationSite) {
1737             onVmPolicyViolation(message, allocationSite);
1738         }
1739     }
1740 
1741     /**
1742      * Called from Parcel.writeNoException()
1743      */
hasGatheredViolations()1744     /* package */ static boolean hasGatheredViolations() {
1745         return gatheredViolations.get() != null;
1746     }
1747 
1748     /**
1749      * Called from Parcel.writeException(), so we drop this memory and
1750      * don't incorrectly attribute it to the wrong caller on the next
1751      * Binder call on this thread.
1752      */
clearGatheredViolations()1753     /* package */ static void clearGatheredViolations() {
1754         gatheredViolations.set(null);
1755     }
1756 
1757     /**
1758      * @hide
1759      */
conditionallyCheckInstanceCounts()1760     public static void conditionallyCheckInstanceCounts() {
1761         VmPolicy policy = getVmPolicy();
1762         int policySize = policy.classInstanceLimit.size();
1763         if (policySize == 0) {
1764             return;
1765         }
1766 
1767         System.gc();
1768         System.runFinalization();
1769         System.gc();
1770 
1771         // Note: classInstanceLimit is immutable, so this is lock-free
1772         // Create the classes array.
1773         Class[] classes = policy.classInstanceLimit.keySet().toArray(new Class[policySize]);
1774         long[] instanceCounts = VMDebug.countInstancesOfClasses(classes, false);
1775         for (int i = 0; i < classes.length; ++i) {
1776             Class klass = classes[i];
1777             int limit = policy.classInstanceLimit.get(klass);
1778             long instances = instanceCounts[i];
1779             if (instances > limit) {
1780                 Throwable tr = new InstanceCountViolation(klass, instances, limit);
1781                 onVmPolicyViolation(tr.getMessage(), tr);
1782             }
1783         }
1784     }
1785 
1786     private static long sLastInstanceCountCheckMillis = 0;
1787     private static boolean sIsIdlerRegistered = false;  // guarded by StrictMode.class
1788     private static final MessageQueue.IdleHandler sProcessIdleHandler =
1789             new MessageQueue.IdleHandler() {
1790                 public boolean queueIdle() {
1791                     long now = SystemClock.uptimeMillis();
1792                     if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1793                         sLastInstanceCountCheckMillis = now;
1794                         conditionallyCheckInstanceCounts();
1795                     }
1796                     return true;
1797                 }
1798             };
1799 
1800     /**
1801      * Sets the policy for what actions in the VM process (on any
1802      * thread) should be detected, as well as the penalty if such
1803      * actions occur.
1804      *
1805      * @param policy the policy to put into place
1806      */
setVmPolicy(final VmPolicy policy)1807     public static void setVmPolicy(final VmPolicy policy) {
1808         synchronized (StrictMode.class) {
1809             sVmPolicy = policy;
1810             sVmPolicyMask = policy.mask;
1811             setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
1812 
1813             Looper looper = Looper.getMainLooper();
1814             if (looper != null) {
1815                 MessageQueue mq = looper.mQueue;
1816                 if (policy.classInstanceLimit.size() == 0 ||
1817                     (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
1818                     mq.removeIdleHandler(sProcessIdleHandler);
1819                     sIsIdlerRegistered = false;
1820                 } else if (!sIsIdlerRegistered) {
1821                     mq.addIdleHandler(sProcessIdleHandler);
1822                     sIsIdlerRegistered = true;
1823                 }
1824             }
1825 
1826             int networkPolicy = NETWORK_POLICY_ACCEPT;
1827             if ((sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
1828                 if ((sVmPolicyMask & PENALTY_DEATH) != 0
1829                         || (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
1830                     networkPolicy = NETWORK_POLICY_REJECT;
1831                 } else {
1832                     networkPolicy = NETWORK_POLICY_LOG;
1833                 }
1834             }
1835 
1836             final INetworkManagementService netd = INetworkManagementService.Stub.asInterface(
1837                     ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
1838             if (netd != null) {
1839                 try {
1840                     netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
1841                 } catch (RemoteException ignored) {
1842                 }
1843             } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
1844                 Log.w(TAG, "Dropping requested network policy due to missing service!");
1845             }
1846         }
1847     }
1848 
1849     /**
1850      * Gets the current VM policy.
1851      */
getVmPolicy()1852     public static VmPolicy getVmPolicy() {
1853         synchronized (StrictMode.class) {
1854             return sVmPolicy;
1855         }
1856     }
1857 
1858     /**
1859      * Enable the recommended StrictMode defaults, with violations just being logged.
1860      *
1861      * <p>This catches disk and network access on the main thread, as
1862      * well as leaked SQLite cursors and unclosed resources.  This is
1863      * simply a wrapper around {@link #setVmPolicy} and {@link
1864      * #setThreadPolicy}.
1865      */
enableDefaults()1866     public static void enableDefaults() {
1867         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
1868                                    .detectAll()
1869                                    .penaltyLog()
1870                                    .build());
1871         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
1872                                .detectAll()
1873                                .penaltyLog()
1874                                .build());
1875     }
1876 
1877     /**
1878      * @hide
1879      */
vmSqliteObjectLeaksEnabled()1880     public static boolean vmSqliteObjectLeaksEnabled() {
1881         return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
1882     }
1883 
1884     /**
1885      * @hide
1886      */
vmClosableObjectLeaksEnabled()1887     public static boolean vmClosableObjectLeaksEnabled() {
1888         return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
1889     }
1890 
1891     /**
1892      * @hide
1893      */
vmRegistrationLeaksEnabled()1894     public static boolean vmRegistrationLeaksEnabled() {
1895         return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
1896     }
1897 
1898     /**
1899      * @hide
1900      */
vmFileUriExposureEnabled()1901     public static boolean vmFileUriExposureEnabled() {
1902         return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
1903     }
1904 
1905     /**
1906      * @hide
1907      */
vmCleartextNetworkEnabled()1908     public static boolean vmCleartextNetworkEnabled() {
1909         return (sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
1910     }
1911 
1912     /**
1913      * @hide
1914      */
vmContentUriWithoutPermissionEnabled()1915     public static boolean vmContentUriWithoutPermissionEnabled() {
1916         return (sVmPolicyMask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
1917     }
1918 
1919     /**
1920      * @hide
1921      */
vmUntaggedSocketEnabled()1922     public static boolean vmUntaggedSocketEnabled() {
1923         return (sVmPolicyMask & DETECT_VM_UNTAGGED_SOCKET) != 0;
1924     }
1925 
1926     /**
1927      * @hide
1928      */
onSqliteObjectLeaked(String message, Throwable originStack)1929     public static void onSqliteObjectLeaked(String message, Throwable originStack) {
1930         onVmPolicyViolation(message, originStack);
1931     }
1932 
1933     /**
1934      * @hide
1935      */
onWebViewMethodCalledOnWrongThread(Throwable originStack)1936     public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
1937         onVmPolicyViolation(null, originStack);
1938     }
1939 
1940     /**
1941      * @hide
1942      */
onIntentReceiverLeaked(Throwable originStack)1943     public static void onIntentReceiverLeaked(Throwable originStack) {
1944         onVmPolicyViolation(null, originStack);
1945     }
1946 
1947     /**
1948      * @hide
1949      */
onServiceConnectionLeaked(Throwable originStack)1950     public static void onServiceConnectionLeaked(Throwable originStack) {
1951         onVmPolicyViolation(null, originStack);
1952     }
1953 
1954     /**
1955      * @hide
1956      */
onFileUriExposed(Uri uri, String location)1957     public static void onFileUriExposed(Uri uri, String location) {
1958         final String message = uri + " exposed beyond app through " + location;
1959         if ((sVmPolicyMask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
1960             throw new FileUriExposedException(message);
1961         } else {
1962             onVmPolicyViolation(null, new Throwable(message));
1963         }
1964     }
1965 
1966     /**
1967      * @hide
1968      */
onContentUriWithoutPermission(Uri uri, String location)1969     public static void onContentUriWithoutPermission(Uri uri, String location) {
1970         final String message = uri + " exposed beyond app through " + location
1971                 + " without permission grant flags; did you forget"
1972                 + " FLAG_GRANT_READ_URI_PERMISSION?";
1973         onVmPolicyViolation(null, new Throwable(message));
1974     }
1975 
1976     /**
1977      * @hide
1978      */
onCleartextNetworkDetected(byte[] firstPacket)1979     public static void onCleartextNetworkDetected(byte[] firstPacket) {
1980         byte[] rawAddr = null;
1981         if (firstPacket != null) {
1982             if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
1983                 // IPv4
1984                 rawAddr = new byte[4];
1985                 System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
1986             } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
1987                 // IPv6
1988                 rawAddr = new byte[16];
1989                 System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
1990             }
1991         }
1992 
1993         final int uid = android.os.Process.myUid();
1994         String msg = "Detected cleartext network traffic from UID " + uid;
1995         if (rawAddr != null) {
1996             try {
1997                 msg = "Detected cleartext network traffic from UID " + uid + " to "
1998                         + InetAddress.getByAddress(rawAddr);
1999             } catch (UnknownHostException ignored) {
2000             }
2001         }
2002 
2003         final boolean forceDeath = (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
2004         onVmPolicyViolation(HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg),
2005                 forceDeath);
2006     }
2007 
2008     /**
2009      * @hide
2010      */
onUntaggedSocket()2011     public static void onUntaggedSocket() {
2012         onVmPolicyViolation(null, new Throwable("Untagged socket detected; use"
2013                 + " TrafficStats.setThreadSocketTag() to track all network usage"));
2014     }
2015 
2016     // Map from VM violation fingerprint to uptime millis.
2017     private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
2018 
2019     /**
2020      * @hide
2021      */
onVmPolicyViolation(String message, Throwable originStack)2022     public static void onVmPolicyViolation(String message, Throwable originStack) {
2023         onVmPolicyViolation(message, originStack, false);
2024     }
2025 
2026     /**
2027      * @hide
2028      */
onVmPolicyViolation(String message, Throwable originStack, boolean forceDeath)2029     public static void onVmPolicyViolation(String message, Throwable originStack,
2030             boolean forceDeath) {
2031         final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
2032         final boolean penaltyDeath = ((sVmPolicyMask & PENALTY_DEATH) != 0) || forceDeath;
2033         final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
2034         final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicyMask);
2035 
2036         // Erase stuff not relevant for process-wide violations
2037         info.numAnimationsRunning = 0;
2038         info.tags = null;
2039         info.broadcastIntentAction = null;
2040 
2041         final Integer fingerprint = info.hashCode();
2042         final long now = SystemClock.uptimeMillis();
2043         long lastViolationTime = 0;
2044         long timeSinceLastViolationMillis = Long.MAX_VALUE;
2045         synchronized (sLastVmViolationTime) {
2046             if (sLastVmViolationTime.containsKey(fingerprint)) {
2047                 lastViolationTime = sLastVmViolationTime.get(fingerprint);
2048                 timeSinceLastViolationMillis = now - lastViolationTime;
2049             }
2050             if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
2051                 sLastVmViolationTime.put(fingerprint, now);
2052             }
2053         }
2054 
2055         if (penaltyLog && sListener != null) {
2056             sListener.onViolation(originStack.toString());
2057         }
2058         if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
2059             Log.e(TAG, message, originStack);
2060         }
2061 
2062         int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
2063 
2064         if (penaltyDropbox && !penaltyDeath) {
2065             // Common case for userdebug/eng builds.  If no death and
2066             // just dropboxing, we can do the ActivityManager call
2067             // asynchronously.
2068             dropboxViolationAsync(violationMaskSubset, info);
2069             return;
2070         }
2071 
2072         if (penaltyDropbox && lastViolationTime == 0) {
2073             // The violationMask, passed to ActivityManager, is a
2074             // subset of the original StrictMode policy bitmask, with
2075             // only the bit violated and penalty bits to be executed
2076             // by the ActivityManagerService remaining set.
2077             final int savedPolicyMask = getThreadPolicyMask();
2078             try {
2079                 // First, remove any policy before we call into the Activity Manager,
2080                 // otherwise we'll infinite recurse as we try to log policy violations
2081                 // to disk, thus violating policy, thus requiring logging, etc...
2082                 // We restore the current policy below, in the finally block.
2083                 setThreadPolicyMask(0);
2084 
2085                 ActivityManager.getService().handleApplicationStrictModeViolation(
2086                     RuntimeInit.getApplicationObject(),
2087                     violationMaskSubset,
2088                     info);
2089             } catch (RemoteException e) {
2090                 if (e instanceof DeadObjectException) {
2091                     // System process is dead; ignore
2092                 } else {
2093                     Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
2094                 }
2095             } finally {
2096                 // Restore the policy.
2097                 setThreadPolicyMask(savedPolicyMask);
2098             }
2099         }
2100 
2101         if (penaltyDeath) {
2102             System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
2103             Process.killProcess(Process.myPid());
2104             System.exit(10);
2105         }
2106     }
2107 
2108     /**
2109      * Called from Parcel.writeNoException()
2110      */
writeGatheredViolationsToParcel(Parcel p)2111     /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
2112         ArrayList<ViolationInfo> violations = gatheredViolations.get();
2113         if (violations == null) {
2114             p.writeInt(0);
2115         } else {
2116             // To avoid taking up too much transaction space, only include
2117             // details for the first 3 violations. Deep inside, CrashInfo
2118             // will truncate each stack trace to ~20kB.
2119             final int size = Math.min(violations.size(), 3);
2120             p.writeInt(size);
2121             for (int i = 0; i < size; i++) {
2122                 violations.get(i).writeToParcel(p, 0);
2123             }
2124         }
2125         gatheredViolations.set(null);
2126     }
2127 
2128     private static class LogStackTrace extends Exception {}
2129 
2130     /**
2131      * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
2132      * we here read back all the encoded violations.
2133      */
readAndHandleBinderCallViolations(Parcel p)2134     /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
2135         // Our own stack trace to append
2136         StringWriter sw = new StringWriter();
2137         sw.append("# via Binder call with stack:\n");
2138         PrintWriter pw = new FastPrintWriter(sw, false, 256);
2139         new LogStackTrace().printStackTrace(pw);
2140         pw.flush();
2141         String ourStack = sw.toString();
2142 
2143         final int policyMask = getThreadPolicyMask();
2144         final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
2145 
2146         final int size = p.readInt();
2147         for (int i = 0; i < size; i++) {
2148             final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
2149             info.crashInfo.appendStackTrace(ourStack);
2150             BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2151             if (policy instanceof AndroidBlockGuardPolicy) {
2152                 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
2153             }
2154         }
2155     }
2156 
2157     /**
2158      * Called from android_util_Binder.cpp's
2159      * android_os_Parcel_enforceInterface when an incoming Binder call
2160      * requires changing the StrictMode policy mask.  The role of this
2161      * function is to ask Binder for its current (native) thread-local
2162      * policy value and synchronize it to libcore's (Java)
2163      * thread-local policy value.
2164      */
onBinderStrictModePolicyChange(int newPolicy)2165     private static void onBinderStrictModePolicyChange(int newPolicy) {
2166         setBlockGuardPolicy(newPolicy);
2167     }
2168 
2169     /**
2170      * A tracked, critical time span.  (e.g. during an animation.)
2171      *
2172      * The object itself is a linked list node, to avoid any allocations
2173      * during rapid span entries and exits.
2174      *
2175      * @hide
2176      */
2177     public static class Span {
2178         private String mName;
2179         private long mCreateMillis;
2180         private Span mNext;
2181         private Span mPrev;  // not used when in freeList, only active
2182         private final ThreadSpanState mContainerState;
2183 
Span(ThreadSpanState threadState)2184         Span(ThreadSpanState threadState) {
2185             mContainerState = threadState;
2186         }
2187 
2188         // Empty constructor for the NO_OP_SPAN
Span()2189         protected Span() {
2190             mContainerState = null;
2191         }
2192 
2193         /**
2194          * To be called when the critical span is complete (i.e. the
2195          * animation is done animating).  This can be called on any
2196          * thread (even a different one from where the animation was
2197          * taking place), but that's only a defensive implementation
2198          * measure.  It really makes no sense for you to call this on
2199          * thread other than that where you created it.
2200          *
2201          * @hide
2202          */
finish()2203         public void finish() {
2204             ThreadSpanState state = mContainerState;
2205             synchronized (state) {
2206                 if (mName == null) {
2207                     // Duplicate finish call.  Ignore.
2208                     return;
2209                 }
2210 
2211                 // Remove ourselves from the active list.
2212                 if (mPrev != null) {
2213                     mPrev.mNext = mNext;
2214                 }
2215                 if (mNext != null) {
2216                     mNext.mPrev = mPrev;
2217                 }
2218                 if (state.mActiveHead == this) {
2219                     state.mActiveHead = mNext;
2220                 }
2221 
2222                 state.mActiveSize--;
2223 
2224                 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
2225 
2226                 this.mCreateMillis = -1;
2227                 this.mName = null;
2228                 this.mPrev = null;
2229                 this.mNext = null;
2230 
2231                 // Add ourselves to the freeList, if it's not already
2232                 // too big.
2233                 if (state.mFreeListSize < 5) {
2234                     this.mNext = state.mFreeListHead;
2235                     state.mFreeListHead = this;
2236                     state.mFreeListSize++;
2237                 }
2238             }
2239         }
2240     }
2241 
2242     // The no-op span that's used in user builds.
2243     private static final Span NO_OP_SPAN = new Span() {
2244             public void finish() {
2245                 // Do nothing.
2246             }
2247         };
2248 
2249     /**
2250      * Linked lists of active spans and a freelist.
2251      *
2252      * Locking notes: there's one of these structures per thread and
2253      * all members of this structure (as well as the Span nodes under
2254      * it) are guarded by the ThreadSpanState object instance.  While
2255      * in theory there'd be no locking required because it's all local
2256      * per-thread, the finish() method above is defensive against
2257      * people calling it on a different thread from where they created
2258      * the Span, hence the locking.
2259      */
2260     private static class ThreadSpanState {
2261         public Span mActiveHead;    // doubly-linked list.
2262         public int mActiveSize;
2263         public Span mFreeListHead;  // singly-linked list.  only changes at head.
2264         public int mFreeListSize;
2265     }
2266 
2267     private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
2268             new ThreadLocal<ThreadSpanState>() {
2269         @Override protected ThreadSpanState initialValue() {
2270             return new ThreadSpanState();
2271         }
2272     };
2273 
2274     private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
2275         protected IWindowManager create() {
2276             return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
2277         }
2278     };
2279 
2280     /**
2281      * Enter a named critical span (e.g. an animation)
2282      *
2283      * <p>The name is an arbitary label (or tag) that will be applied
2284      * to any strictmode violation that happens while this span is
2285      * active.  You must call finish() on the span when done.
2286      *
2287      * <p>This will never return null, but on devices without debugging
2288      * enabled, this may return a dummy object on which the finish()
2289      * method is a no-op.
2290      *
2291      * <p>TODO: add CloseGuard to this, verifying callers call finish.
2292      *
2293      * @hide
2294      */
enterCriticalSpan(String name)2295     public static Span enterCriticalSpan(String name) {
2296         if (Build.IS_USER) {
2297             return NO_OP_SPAN;
2298         }
2299         if (name == null || name.isEmpty()) {
2300             throw new IllegalArgumentException("name must be non-null and non-empty");
2301         }
2302         ThreadSpanState state = sThisThreadSpanState.get();
2303         Span span = null;
2304         synchronized (state) {
2305             if (state.mFreeListHead != null) {
2306                 span = state.mFreeListHead;
2307                 state.mFreeListHead = span.mNext;
2308                 state.mFreeListSize--;
2309             } else {
2310                 // Shouldn't have to do this often.
2311                 span = new Span(state);
2312             }
2313             span.mName = name;
2314             span.mCreateMillis = SystemClock.uptimeMillis();
2315             span.mNext = state.mActiveHead;
2316             span.mPrev = null;
2317             state.mActiveHead = span;
2318             state.mActiveSize++;
2319             if (span.mNext != null) {
2320                 span.mNext.mPrev = span;
2321             }
2322             if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
2323         }
2324         return span;
2325     }
2326 
2327     /**
2328      * For code to note that it's slow.  This is a no-op unless the
2329      * current thread's {@link android.os.StrictMode.ThreadPolicy} has
2330      * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls}
2331      * enabled.
2332      *
2333      * @param name a short string for the exception stack trace that's
2334      *             built if when this fires.
2335      */
noteSlowCall(String name)2336     public static void noteSlowCall(String name) {
2337         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2338         if (!(policy instanceof AndroidBlockGuardPolicy)) {
2339             // StrictMode not enabled.
2340             return;
2341         }
2342         ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
2343     }
2344 
2345     /**
2346      * For code to note that a resource was obtained using a type other than
2347      * its defined type. This is a no-op unless the current thread's
2348      * {@link android.os.StrictMode.ThreadPolicy} has
2349      * {@link android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()}
2350      * enabled.
2351      *
2352      * @param tag an object for the exception stack trace that's
2353      *            built if when this fires.
2354      * @hide
2355      */
noteResourceMismatch(Object tag)2356     public static void noteResourceMismatch(Object tag) {
2357         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2358         if (!(policy instanceof AndroidBlockGuardPolicy)) {
2359             // StrictMode not enabled.
2360             return;
2361         }
2362         ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag);
2363     }
2364 
2365     /**
2366      * @hide
2367      */
noteUnbufferedIO()2368     public static void noteUnbufferedIO() {
2369         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2370         if (!(policy instanceof AndroidBlockGuardPolicy)) {
2371             // StrictMode not enabled.
2372             return;
2373         }
2374         ((AndroidBlockGuardPolicy) policy).onUnbufferedIO();
2375     }
2376 
2377     /**
2378      * @hide
2379      */
noteDiskRead()2380     public static void noteDiskRead() {
2381         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2382         if (!(policy instanceof AndroidBlockGuardPolicy)) {
2383             // StrictMode not enabled.
2384             return;
2385         }
2386         ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
2387     }
2388 
2389     /**
2390      * @hide
2391      */
noteDiskWrite()2392     public static void noteDiskWrite() {
2393         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2394         if (!(policy instanceof AndroidBlockGuardPolicy)) {
2395             // StrictMode not enabled.
2396             return;
2397         }
2398         ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
2399     }
2400 
2401     // Guarded by StrictMode.class
2402     private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
2403             new HashMap<Class, Integer>();
2404 
2405     /**
2406      * Returns an object that is used to track instances of activites.
2407      * The activity should store a reference to the tracker object in one of its fields.
2408      * @hide
2409      */
trackActivity(Object instance)2410     public static Object trackActivity(Object instance) {
2411         return new InstanceTracker(instance);
2412     }
2413 
2414     /**
2415      * @hide
2416      */
incrementExpectedActivityCount(Class klass)2417     public static void incrementExpectedActivityCount(Class klass) {
2418         if (klass == null) {
2419             return;
2420         }
2421 
2422         synchronized (StrictMode.class) {
2423             if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2424                 return;
2425             }
2426 
2427             Integer expected = sExpectedActivityInstanceCount.get(klass);
2428             Integer newExpected = expected == null ? 1 : expected + 1;
2429             sExpectedActivityInstanceCount.put(klass, newExpected);
2430         }
2431     }
2432 
2433     /**
2434      * @hide
2435      */
decrementExpectedActivityCount(Class klass)2436     public static void decrementExpectedActivityCount(Class klass) {
2437         if (klass == null) {
2438             return;
2439         }
2440 
2441         final int limit;
2442         synchronized (StrictMode.class) {
2443             if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2444                 return;
2445             }
2446 
2447             Integer expected = sExpectedActivityInstanceCount.get(klass);
2448             int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
2449             if (newExpected == 0) {
2450                 sExpectedActivityInstanceCount.remove(klass);
2451             } else {
2452                 sExpectedActivityInstanceCount.put(klass, newExpected);
2453             }
2454 
2455             // Note: adding 1 here to give some breathing room during
2456             // orientation changes.  (shouldn't be necessary, though?)
2457             limit = newExpected + 1;
2458         }
2459 
2460         // Quick check.
2461         int actual = InstanceTracker.getInstanceCount(klass);
2462         if (actual <= limit) {
2463             return;
2464         }
2465 
2466         // Do a GC and explicit count to double-check.
2467         // This is the work that we are trying to avoid by tracking the object instances
2468         // explicity.  Running an explicit GC can be expensive (80ms) and so can walking
2469         // the heap to count instance (30ms).  This extra work can make the system feel
2470         // noticeably less responsive during orientation changes when activities are
2471         // being restarted.  Granted, it is only a problem when StrictMode is enabled
2472         // but it is annoying.
2473 
2474         System.gc();
2475         System.runFinalization();
2476         System.gc();
2477 
2478         long instances = VMDebug.countInstancesOfClass(klass, false);
2479         if (instances > limit) {
2480             Throwable tr = new InstanceCountViolation(klass, instances, limit);
2481             onVmPolicyViolation(tr.getMessage(), tr);
2482         }
2483     }
2484 
2485     /**
2486      * Parcelable that gets sent in Binder call headers back to callers
2487      * to report violations that happened during a cross-process call.
2488      *
2489      * @hide
2490      */
2491     public static class ViolationInfo implements Parcelable {
2492         public final String message;
2493 
2494         /**
2495          * Stack and other stuff info.
2496          */
2497         public final ApplicationErrorReport.CrashInfo crashInfo;
2498 
2499         /**
2500          * The strict mode policy mask at the time of violation.
2501          */
2502         public final int policy;
2503 
2504         /**
2505          * The wall time duration of the violation, when known.  -1 when
2506          * not known.
2507          */
2508         public int durationMillis = -1;
2509 
2510         /**
2511          * The number of animations currently running.
2512          */
2513         public int numAnimationsRunning = 0;
2514 
2515         /**
2516          * List of tags from active Span instances during this
2517          * violation, or null for none.
2518          */
2519         public String[] tags;
2520 
2521         /**
2522          * Which violation number this was (1-based) since the last Looper loop,
2523          * from the perspective of the root caller (if it crossed any processes
2524          * via Binder calls).  The value is 0 if the root caller wasn't on a Looper
2525          * thread.
2526          */
2527         public int violationNumThisLoop;
2528 
2529         /**
2530          * The time (in terms of SystemClock.uptimeMillis()) that the
2531          * violation occurred.
2532          */
2533         public long violationUptimeMillis;
2534 
2535         /**
2536          * The action of the Intent being broadcast to somebody's onReceive
2537          * on this thread right now, or null.
2538          */
2539         public String broadcastIntentAction;
2540 
2541         /**
2542          * If this is a instance count violation, the number of instances in memory,
2543          * else -1.
2544          */
2545         public long numInstances = -1;
2546 
2547         /**
2548          * Create an uninitialized instance of ViolationInfo
2549          */
ViolationInfo()2550         public ViolationInfo() {
2551             message = null;
2552             crashInfo = null;
2553             policy = 0;
2554         }
2555 
ViolationInfo(Throwable tr, int policy)2556         public ViolationInfo(Throwable tr, int policy) {
2557             this(null, tr, policy);
2558         }
2559 
2560         /**
2561          * Create an instance of ViolationInfo initialized from an exception.
2562          */
ViolationInfo(String message, Throwable tr, int policy)2563         public ViolationInfo(String message, Throwable tr, int policy) {
2564             this.message = message;
2565             crashInfo = new ApplicationErrorReport.CrashInfo(tr);
2566             violationUptimeMillis = SystemClock.uptimeMillis();
2567             this.policy = policy;
2568             this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
2569             Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2570             if (broadcastIntent != null) {
2571                 broadcastIntentAction = broadcastIntent.getAction();
2572             }
2573             ThreadSpanState state = sThisThreadSpanState.get();
2574             if (tr instanceof InstanceCountViolation) {
2575                 this.numInstances = ((InstanceCountViolation) tr).mInstances;
2576             }
2577             synchronized (state) {
2578                 int spanActiveCount = state.mActiveSize;
2579                 if (spanActiveCount > MAX_SPAN_TAGS) {
2580                     spanActiveCount = MAX_SPAN_TAGS;
2581                 }
2582                 if (spanActiveCount != 0) {
2583                     this.tags = new String[spanActiveCount];
2584                     Span iter = state.mActiveHead;
2585                     int index = 0;
2586                     while (iter != null && index < spanActiveCount) {
2587                         this.tags[index] = iter.mName;
2588                         index++;
2589                         iter = iter.mNext;
2590                     }
2591                 }
2592             }
2593         }
2594 
2595         @Override
hashCode()2596         public int hashCode() {
2597             int result = 17;
2598             if (crashInfo != null) {
2599                 result = 37 * result + crashInfo.stackTrace.hashCode();
2600             }
2601             if (numAnimationsRunning != 0) {
2602                 result *= 37;
2603             }
2604             if (broadcastIntentAction != null) {
2605                 result = 37 * result + broadcastIntentAction.hashCode();
2606             }
2607             if (tags != null) {
2608                 for (String tag : tags) {
2609                     result = 37 * result + tag.hashCode();
2610                 }
2611             }
2612             return result;
2613         }
2614 
2615         /**
2616          * Create an instance of ViolationInfo initialized from a Parcel.
2617          */
ViolationInfo(Parcel in)2618         public ViolationInfo(Parcel in) {
2619             this(in, false);
2620         }
2621 
2622         /**
2623          * Create an instance of ViolationInfo initialized from a Parcel.
2624          *
2625          * @param unsetGatheringBit if true, the caller is the root caller
2626          *   and the gathering penalty should be removed.
2627          */
ViolationInfo(Parcel in, boolean unsetGatheringBit)2628         public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
2629             message = in.readString();
2630             if (in.readInt() != 0) {
2631                 crashInfo = new ApplicationErrorReport.CrashInfo(in);
2632             } else {
2633                 crashInfo = null;
2634             }
2635             int rawPolicy = in.readInt();
2636             if (unsetGatheringBit) {
2637                 policy = rawPolicy & ~PENALTY_GATHER;
2638             } else {
2639                 policy = rawPolicy;
2640             }
2641             durationMillis = in.readInt();
2642             violationNumThisLoop = in.readInt();
2643             numAnimationsRunning = in.readInt();
2644             violationUptimeMillis = in.readLong();
2645             numInstances = in.readLong();
2646             broadcastIntentAction = in.readString();
2647             tags = in.readStringArray();
2648         }
2649 
2650         /**
2651          * Save a ViolationInfo instance to a parcel.
2652          */
2653         @Override
writeToParcel(Parcel dest, int flags)2654         public void writeToParcel(Parcel dest, int flags) {
2655             dest.writeString(message);
2656             if (crashInfo != null) {
2657                 dest.writeInt(1);
2658                 crashInfo.writeToParcel(dest, flags);
2659             } else {
2660                 dest.writeInt(0);
2661             }
2662             int start = dest.dataPosition();
2663             dest.writeInt(policy);
2664             dest.writeInt(durationMillis);
2665             dest.writeInt(violationNumThisLoop);
2666             dest.writeInt(numAnimationsRunning);
2667             dest.writeLong(violationUptimeMillis);
2668             dest.writeLong(numInstances);
2669             dest.writeString(broadcastIntentAction);
2670             dest.writeStringArray(tags);
2671             int total = dest.dataPosition()-start;
2672             if (Binder.CHECK_PARCEL_SIZE && total > 10*1024) {
2673                 Slog.d(TAG, "VIO: policy=" + policy + " dur=" + durationMillis
2674                         + " numLoop=" + violationNumThisLoop
2675                         + " anim=" + numAnimationsRunning
2676                         + " uptime=" + violationUptimeMillis
2677                         + " numInst=" + numInstances);
2678                 Slog.d(TAG, "VIO: action=" + broadcastIntentAction);
2679                 Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags));
2680                 Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition()-start));
2681             }
2682         }
2683 
2684 
2685         /**
2686          * Dump a ViolationInfo instance to a Printer.
2687          */
dump(Printer pw, String prefix)2688         public void dump(Printer pw, String prefix) {
2689             if (crashInfo != null) {
2690                 crashInfo.dump(pw, prefix);
2691             }
2692             pw.println(prefix + "policy: " + policy);
2693             if (durationMillis != -1) {
2694                 pw.println(prefix + "durationMillis: " + durationMillis);
2695             }
2696             if (numInstances != -1) {
2697                 pw.println(prefix + "numInstances: " + numInstances);
2698             }
2699             if (violationNumThisLoop != 0) {
2700                 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2701             }
2702             if (numAnimationsRunning != 0) {
2703                 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2704             }
2705             pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
2706             if (broadcastIntentAction != null) {
2707                 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2708             }
2709             if (tags != null) {
2710                 int index = 0;
2711                 for (String tag : tags) {
2712                     pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2713                 }
2714             }
2715         }
2716 
2717         @Override
describeContents()2718         public int describeContents() {
2719             return 0;
2720         }
2721 
2722         public static final Parcelable.Creator<ViolationInfo> CREATOR =
2723                 new Parcelable.Creator<ViolationInfo>() {
2724                     @Override
2725                     public ViolationInfo createFromParcel(Parcel in) {
2726                         return new ViolationInfo(in);
2727                     }
2728 
2729                     @Override
2730                     public ViolationInfo[] newArray(int size) {
2731                         return new ViolationInfo[size];
2732                     }
2733                 };
2734     }
2735 
2736     // Dummy throwable, for now, since we don't know when or where the
2737     // leaked instances came from.  We might in the future, but for
2738     // now we suppress the stack trace because it's useless and/or
2739     // misleading.
2740     private static class InstanceCountViolation extends Throwable {
2741         final Class mClass;
2742         final long mInstances;
2743         final int mLimit;
2744 
2745         private static final StackTraceElement[] FAKE_STACK = {
2746             new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
2747                                   "StrictMode.java", 1)
2748         };
2749 
InstanceCountViolation(Class klass, long instances, int limit)2750         public InstanceCountViolation(Class klass, long instances, int limit) {
2751             super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
2752             setStackTrace(FAKE_STACK);
2753             mClass = klass;
2754             mInstances = instances;
2755             mLimit = limit;
2756         }
2757     }
2758 
2759     private static final class InstanceTracker {
2760         private static final HashMap<Class<?>, Integer> sInstanceCounts =
2761                 new HashMap<Class<?>, Integer>();
2762 
2763         private final Class<?> mKlass;
2764 
InstanceTracker(Object instance)2765         public InstanceTracker(Object instance) {
2766             mKlass = instance.getClass();
2767 
2768             synchronized (sInstanceCounts) {
2769                 final Integer value = sInstanceCounts.get(mKlass);
2770                 final int newValue = value != null ? value + 1 : 1;
2771                 sInstanceCounts.put(mKlass, newValue);
2772             }
2773         }
2774 
2775         @Override
finalize()2776         protected void finalize() throws Throwable {
2777             try {
2778                 synchronized (sInstanceCounts) {
2779                     final Integer value = sInstanceCounts.get(mKlass);
2780                     if (value != null) {
2781                         final int newValue = value - 1;
2782                         if (newValue > 0) {
2783                             sInstanceCounts.put(mKlass, newValue);
2784                         } else {
2785                             sInstanceCounts.remove(mKlass);
2786                         }
2787                     }
2788                 }
2789             } finally {
2790                 super.finalize();
2791             }
2792         }
2793 
getInstanceCount(Class<?> klass)2794         public static int getInstanceCount(Class<?> klass) {
2795             synchronized (sInstanceCounts) {
2796                 final Integer value = sInstanceCounts.get(klass);
2797                 return value != null ? value : 0;
2798             }
2799         }
2800     }
2801 }
2802