blob: 38f9325851b779787a52c758f0e9e29f34daa918 [file] [log] [blame]
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.os;
17
Brad Fitzpatrick599ca292010-10-22 14:47:03 -070018import android.animation.ValueAnimator;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070019import android.app.ActivityManagerNative;
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -070020import android.app.ActivityThread;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070021import android.app.ApplicationErrorReport;
Brad Fitzpatrick10656852010-11-23 19:01:13 -080022import android.app.IActivityManager;
Jeff Sharkeyd7026f12012-03-01 20:50:32 -080023import android.content.BroadcastReceiver;
24import android.content.Context;
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -070025import android.content.Intent;
Jeff Sharkeyd7026f12012-03-01 20:50:32 -080026import android.content.ServiceConnection;
Jeff Sharkey344744b2016-01-28 19:03:30 -070027import android.net.Uri;
Dianne Hackborn390517b2013-05-30 15:03:32 -070028import android.util.ArrayMap;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070029import android.util.Log;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070030import android.util.Printer;
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -080031import android.util.Singleton;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070032import android.util.Slog;
Brad Fitzpatrick68044332010-11-22 18:19:48 -080033import android.view.IWindowManager;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070034
35import com.android.internal.os.RuntimeInit;
Dianne Hackborn8c841092013-06-24 13:46:13 -070036import com.android.internal.util.FastPrintWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080037import com.android.internal.util.HexDump;
38
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070039import dalvik.system.BlockGuard;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070040import dalvik.system.CloseGuard;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -080041import dalvik.system.VMDebug;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070042
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070043import java.io.PrintWriter;
44import java.io.StringWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080045import java.net.InetAddress;
46import java.net.UnknownHostException;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070047import java.util.ArrayList;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070048import java.util.Arrays;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070049import java.util.HashMap;
Brad Fitzpatrickbee24872010-11-20 12:09:10 -080050import java.util.concurrent.atomic.AtomicInteger;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070051
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070052/**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070053 * <p>StrictMode is a developer tool which detects things you might be
54 * doing by accident and brings them to your attention so you can fix
55 * them.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070056 *
57 * <p>StrictMode is most commonly used to catch accidental disk or
58 * network access on the application's main thread, where UI
59 * operations are received and animations take place. Keeping disk
60 * and network operations off the main thread makes for much smoother,
Brad Fitzpatrick9fc2fc52010-10-11 12:52:35 -070061 * more responsive applications. By keeping your application's main thread
62 * responsive, you also prevent
63 * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
64 * from being shown to users.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070065 *
66 * <p class="note">Note that even though an Android device's disk is
67 * often on flash memory, many devices run a filesystem on top of that
68 * memory with very limited concurrency. It's often the case that
69 * almost all disk accesses are fast, but may in individual cases be
70 * dramatically slower when certain I/O is happening in the background
71 * from other processes. If possible, it's best to assume that such
72 * things are not fast.</p>
73 *
74 * <p>Example code to enable from early in your
75 * {@link android.app.Application}, {@link android.app.Activity}, or
76 * other application component's
77 * {@link android.app.Application#onCreate} method:
78 *
79 * <pre>
80 * public void onCreate() {
81 * if (DEVELOPER_MODE) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070082 * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
83 * .detectDiskReads()
84 * .detectDiskWrites()
85 * .detectNetwork() // or .detectAll() for all detectable problems
86 * .penaltyLog()
87 * .build());
88 * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -070089 * .detectLeakedSqlLiteObjects()
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070090 * .detectLeakedClosableObjects()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070091 * .penaltyLog()
92 * .penaltyDeath()
93 * .build());
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070094 * }
95 * super.onCreate();
96 * }
97 * </pre>
98 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070099 * <p>You can decide what should happen when a violation is detected.
100 * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can
101 * watch the output of <code>adb logcat</code> while you use your
102 * application to see the violations as they happen.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700103 *
104 * <p>If you find violations that you feel are problematic, there are
105 * a variety of tools to help solve them: threads, {@link android.os.Handler},
106 * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
107 * But don't feel compelled to fix everything that StrictMode finds. In particular,
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700108 * many cases of disk access are often necessary during the normal activity lifecycle. Use
109 * StrictMode to find things you did by accident. Network requests on the UI thread
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700110 * are almost always a problem, though.
111 *
112 * <p class="note">StrictMode is not a security mechanism and is not
113 * guaranteed to find all disk or network accesses. While it does
114 * propagate its state across process boundaries when doing
115 * {@link android.os.Binder} calls, it's still ultimately a best
116 * effort mechanism. Notably, disk or network access from JNI calls
117 * won't necessarily trigger it. Future versions of Android may catch
118 * more (or fewer) operations, so you should never leave StrictMode
Dirk Dougherty4d7bc6552012-01-27 17:56:49 -0800119 * enabled in applications distributed on Google Play.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700120 */
121public final class StrictMode {
122 private static final String TAG = "StrictMode";
Brad Fitzpatrick82829ef2010-11-18 18:25:08 -0800123 private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700124
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -0800125 private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800126 private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE);
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -0800127
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800128 /**
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700129 * 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 /**
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800137 * 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
Jeff Sharkey605eb792014-11-04 13:34:06 -0800143 /**
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 */
Jeff Sharkey2e571642015-01-22 11:51:43 -0700148 private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.clear";
Jeff Sharkey605eb792014-11-04 13:34:06 -0800149
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700150 // 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
Brad Fitzpatricke7520d82010-11-10 18:08:36 -0800156 // How many Span tags (e.g. animations) to report.
157 private static final int MAX_SPAN_TAGS = 20;
158
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -0700159 // 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
Jeff Sharkey605eb792014-11-04 13:34:06 -0800163 // Byte 1: Thread-policy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700164
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700165 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700166 * @hide
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700167 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700168 public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700169
170 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700171 * @hide
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700172 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700173 public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700174
175 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700176 * @hide
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700177 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700178 public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700179
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800180 /**
181 * For StrictMode.noteSlowCall()
182 *
183 * @hide
184 */
185 public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy
186
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800187 /**
188 * For StrictMode.noteResourceMismatch()
189 *
190 * @hide
191 */
192 public static final int DETECT_RESOURCE_MISMATCH = 0x10; // for ThreadPolicy
193
Shubham Ajmerac95b2c82016-09-29 16:35:36 +0100194 /**
195 * @hide
196 */
197 public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy
198
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800199 private static final int ALL_THREAD_DETECT_BITS =
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800200 DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM |
Shubham Ajmerac95b2c82016-09-29 16:35:36 +0100201 DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO;
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800202
Jeff Sharkey605eb792014-11-04 13:34:06 -0800203 // Byte 2: Process-policy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700204
205 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700206 * Note, a "VM_" bit, not thread.
207 * @hide
208 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800209 public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8; // for VmPolicy
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700210
211 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700212 * Note, a "VM_" bit, not thread.
213 * @hide
214 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800215 public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8; // for VmPolicy
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800216
217 /**
218 * Note, a "VM_" bit, not thread.
219 * @hide
220 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800221 public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8; // for VmPolicy
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700222
223 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700224 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700225 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800226 private static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8; // for VmPolicy
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800227
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800228 /**
229 * @hide
230 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800231 public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8; // for VmPolicy
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800232
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700233 /**
234 * @hide
235 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800236 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
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700242
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800243 private static final int ALL_VM_DETECT_BITS =
244 DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800245 DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
Jeff Sharkey605eb792014-11-04 13:34:06 -0800246 DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE |
247 DETECT_VM_CLEARTEXT_NETWORK;
248
249 // Byte 3: Penalty
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800250
Jeff Sharkey344744b2016-01-28 19:03:30 -0700251 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800252 public static final int PENALTY_LOG = 0x01 << 16; // normal android.util.Log
Jeff Sharkey344744b2016-01-28 19:03:30 -0700253 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800254 public static final int PENALTY_DIALOG = 0x02 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700255 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800256 public static final int PENALTY_DEATH = 0x04 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700257 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800258 public static final int PENALTY_FLASH = 0x10 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700259 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800260 public static final int PENALTY_DROPBOX = 0x20 << 16;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700261
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700262 /**
263 * Non-public penalty mode which overrides all the other penalty
264 * bits and signals that we're in a Binder call and we should
265 * ignore the other penalty bits and instead serialize back all
266 * our offending stack traces to the caller to ultimately handle
267 * in the originating process.
268 *
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700269 * This must be kept in sync with the constant in libs/binder/Parcel.cpp
270 *
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700271 * @hide
272 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800273 public static final int PENALTY_GATHER = 0x40 << 16;
274
Jeff Sharkey344744b2016-01-28 19:03:30 -0700275 // Byte 4: Special cases
276
277 /**
278 * Death when network traffic is detected on main thread.
279 *
280 * @hide
281 */
282 public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
283
Jeff Sharkey605eb792014-11-04 13:34:06 -0800284 /**
285 * Death when cleartext network traffic is detected.
286 *
287 * @hide
288 */
Jeff Sharkey344744b2016-01-28 19:03:30 -0700289 public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
290
291 /**
292 * Death when file exposure is detected.
293 *
294 * @hide
295 */
296 public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700297
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700298 /**
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800299 * Mask of all the penalty bits valid for thread policies.
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700300 */
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800301 private static final int THREAD_PENALTY_MASK =
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700302 PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800303 PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700304
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800305 /**
306 * Mask of all the penalty bits valid for VM policies.
307 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800308 private static final int VM_PENALTY_MASK = PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX
Jeff Sharkey344744b2016-01-28 19:03:30 -0700309 | PENALTY_DEATH_ON_CLEARTEXT_NETWORK | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800310
Jeff Sharkey605eb792014-11-04 13:34:06 -0800311 /** {@hide} */
312 public static final int NETWORK_POLICY_ACCEPT = 0;
313 /** {@hide} */
314 public static final int NETWORK_POLICY_LOG = 1;
315 /** {@hide} */
316 public static final int NETWORK_POLICY_REJECT = 2;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800317
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800318 // TODO: wrap in some ImmutableHashMap thing.
319 // Note: must be before static initialization of sVmPolicy.
320 private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP = new HashMap<Class, Integer>();
321
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700322 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700323 * The current VmPolicy in effect.
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800324 *
325 * TODO: these are redundant (mask is in VmPolicy). Should remove sVmPolicyMask.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700326 */
327 private static volatile int sVmPolicyMask = 0;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800328 private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700329
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800330 /**
331 * The number of threads trying to do an async dropbox write.
332 * Just to limit ourselves out of paranoia.
333 */
334 private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
335
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700336 private StrictMode() {}
337
338 /**
339 * {@link StrictMode} policy applied to a certain thread.
340 *
341 * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy
342 * can be retrieved with {@link #getThreadPolicy}.
343 *
344 * <p>Note that multiple penalties may be provided and they're run
345 * in order from least to most severe (logging before process
346 * death, for example). There's currently no mechanism to choose
347 * different penalties for different detected actions.
348 */
349 public static final class ThreadPolicy {
350 /**
351 * The default, lax policy which doesn't catch anything.
352 */
353 public static final ThreadPolicy LAX = new ThreadPolicy(0);
354
355 final int mask;
356
357 private ThreadPolicy(int mask) {
358 this.mask = mask;
359 }
360
361 @Override
362 public String toString() {
363 return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
364 }
365
366 /**
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800367 * Creates {@link ThreadPolicy} instances. Methods whose names start
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700368 * with {@code detect} specify what problems we should look
369 * for. Methods whose names start with {@code penalty} specify what
370 * we should do when we detect a problem.
371 *
372 * <p>You can call as many {@code detect} and {@code penalty}
373 * methods as you like. Currently order is insignificant: all
374 * penalties apply to all detected problems.
375 *
376 * <p>For example, detect everything and log anything that's found:
377 * <pre>
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800378 * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700379 * .detectAll()
380 * .penaltyLog()
381 * .build();
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800382 * StrictMode.setThreadPolicy(policy);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700383 * </pre>
384 */
385 public static final class Builder {
386 private int mMask = 0;
387
388 /**
389 * Create a Builder that detects nothing and has no
390 * violations. (but note that {@link #build} will default
391 * to enabling {@link #penaltyLog} if no other penalties
392 * are specified)
393 */
394 public Builder() {
395 mMask = 0;
396 }
397
398 /**
399 * Initialize a Builder from an existing ThreadPolicy.
400 */
401 public Builder(ThreadPolicy policy) {
402 mMask = policy.mask;
403 }
404
405 /**
406 * Detect everything that's potentially suspect.
407 *
408 * <p>As of the Gingerbread release this includes network and
409 * disk operations but will likely expand in future releases.
410 */
411 public Builder detectAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800412 return enable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700413 }
414
415 /**
416 * Disable the detection of everything.
417 */
418 public Builder permitAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800419 return disable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700420 }
421
422 /**
423 * Enable detection of network operations.
424 */
425 public Builder detectNetwork() {
426 return enable(DETECT_NETWORK);
427 }
428
429 /**
430 * Disable detection of network operations.
431 */
432 public Builder permitNetwork() {
433 return disable(DETECT_NETWORK);
434 }
435
436 /**
437 * Enable detection of disk reads.
438 */
439 public Builder detectDiskReads() {
440 return enable(DETECT_DISK_READ);
441 }
442
443 /**
444 * Disable detection of disk reads.
445 */
446 public Builder permitDiskReads() {
447 return disable(DETECT_DISK_READ);
448 }
449
450 /**
Qi Wang097fbf22012-07-13 09:26:03 +0800451 * Enable detection of slow calls.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800452 */
453 public Builder detectCustomSlowCalls() {
454 return enable(DETECT_CUSTOM);
455 }
456
457 /**
Qi Wang097fbf22012-07-13 09:26:03 +0800458 * Disable detection of slow calls.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800459 */
460 public Builder permitCustomSlowCalls() {
Qi Wang097fbf22012-07-13 09:26:03 +0800461 return disable(DETECT_CUSTOM);
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800462 }
463
464 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800465 * Disable detection of mismatches between defined resource types
466 * and getter calls.
467 */
468 public Builder permitResourceMismatches() {
469 return disable(DETECT_RESOURCE_MISMATCH);
470 }
471
472 /**
Shubham Ajmerac95b2c82016-09-29 16:35:36 +0100473 * Detect unbuffered input/output operations.
474 */
475 public Builder detectUnbufferedIo() {
476 return enable(DETECT_UNBUFFERED_IO);
477 }
478
479 /**
480 * Detect unbuffered input/output operations.
481 */
482 public Builder permitUnbufferedIo() {
483 return disable(DETECT_UNBUFFERED_IO);
484 }
485
486 /**
Alan Viverette39bf9a12015-05-13 17:22:34 -0700487 * Enables detection of mismatches between defined resource types
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800488 * and getter calls.
Alan Viverette39bf9a12015-05-13 17:22:34 -0700489 * <p>
490 * This helps detect accidental type mismatches and potentially
491 * expensive type conversions when obtaining typed resources.
492 * <p>
493 * For example, a strict mode violation would be thrown when
494 * calling {@link android.content.res.TypedArray#getInt(int, int)}
495 * on an index that contains a String-type resource. If the string
496 * value can be parsed as an integer, this method call will return
497 * a value without crashing; however, the developer should format
498 * the resource as an integer to avoid unnecessary type conversion.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800499 */
500 public Builder detectResourceMismatches() {
501 return enable(DETECT_RESOURCE_MISMATCH);
502 }
503
504 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700505 * Enable detection of disk writes.
506 */
507 public Builder detectDiskWrites() {
508 return enable(DETECT_DISK_WRITE);
509 }
510
511 /**
512 * Disable detection of disk writes.
513 */
514 public Builder permitDiskWrites() {
515 return disable(DETECT_DISK_WRITE);
516 }
517
518 /**
519 * Show an annoying dialog to the developer on detected
520 * violations, rate-limited to be only a little annoying.
521 */
522 public Builder penaltyDialog() {
523 return enable(PENALTY_DIALOG);
524 }
525
526 /**
527 * Crash the whole process on violation. This penalty runs at
528 * the end of all enabled penalties so you'll still get
529 * see logging or other violations before the process dies.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700530 *
531 * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies
532 * to disk reads, disk writes, and network usage if their
533 * corresponding detect flags are set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700534 */
535 public Builder penaltyDeath() {
536 return enable(PENALTY_DEATH);
537 }
538
539 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700540 * Crash the whole process on any network usage. Unlike
541 * {@link #penaltyDeath}, this penalty runs
542 * <em>before</em> anything else. You must still have
543 * called {@link #detectNetwork} to enable this.
544 *
545 * <p>In the Honeycomb or later SDKs, this is on by default.
546 */
547 public Builder penaltyDeathOnNetwork() {
548 return enable(PENALTY_DEATH_ON_NETWORK);
549 }
550
551 /**
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800552 * Flash the screen during a violation.
553 */
554 public Builder penaltyFlashScreen() {
555 return enable(PENALTY_FLASH);
556 }
557
558 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700559 * Log detected violations to the system log.
560 */
561 public Builder penaltyLog() {
562 return enable(PENALTY_LOG);
563 }
564
565 /**
566 * Enable detected violations log a stacktrace and timing data
567 * to the {@link android.os.DropBoxManager DropBox} on policy
568 * violation. Intended mostly for platform integrators doing
569 * beta user field data collection.
570 */
571 public Builder penaltyDropBox() {
572 return enable(PENALTY_DROPBOX);
573 }
574
575 private Builder enable(int bit) {
576 mMask |= bit;
577 return this;
578 }
579
580 private Builder disable(int bit) {
581 mMask &= ~bit;
582 return this;
583 }
584
585 /**
586 * Construct the ThreadPolicy instance.
587 *
588 * <p>Note: if no penalties are enabled before calling
589 * <code>build</code>, {@link #penaltyLog} is implicitly
590 * set.
591 */
592 public ThreadPolicy build() {
593 // If there are detection bits set but no violation bits
594 // set, enable simple logging.
595 if (mMask != 0 &&
596 (mMask & (PENALTY_DEATH | PENALTY_LOG |
597 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
598 penaltyLog();
599 }
600 return new ThreadPolicy(mMask);
601 }
602 }
603 }
604
605 /**
606 * {@link StrictMode} policy applied to all threads in the virtual machine's process.
607 *
608 * <p>The policy is enabled by {@link #setVmPolicy}.
609 */
610 public static final class VmPolicy {
611 /**
612 * The default, lax policy which doesn't catch anything.
613 */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800614 public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700615
616 final int mask;
617
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800618 // Map from class to max number of allowed instances in memory.
619 final HashMap<Class, Integer> classInstanceLimit;
620
621 private VmPolicy(int mask, HashMap<Class, Integer> classInstanceLimit) {
622 if (classInstanceLimit == null) {
623 throw new NullPointerException("classInstanceLimit == null");
624 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700625 this.mask = mask;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800626 this.classInstanceLimit = classInstanceLimit;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700627 }
628
629 @Override
630 public String toString() {
631 return "[StrictMode.VmPolicy; mask=" + mask + "]";
632 }
633
634 /**
635 * Creates {@link VmPolicy} instances. Methods whose names start
636 * with {@code detect} specify what problems we should look
637 * for. Methods whose names start with {@code penalty} specify what
638 * we should do when we detect a problem.
639 *
640 * <p>You can call as many {@code detect} and {@code penalty}
641 * methods as you like. Currently order is insignificant: all
642 * penalties apply to all detected problems.
643 *
644 * <p>For example, detect everything and log anything that's found:
645 * <pre>
646 * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
647 * .detectAll()
648 * .penaltyLog()
649 * .build();
650 * StrictMode.setVmPolicy(policy);
651 * </pre>
652 */
653 public static final class Builder {
654 private int mMask;
655
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800656 private HashMap<Class, Integer> mClassInstanceLimit; // null until needed
657 private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write
658
659 public Builder() {
660 mMask = 0;
661 }
662
663 /**
664 * Build upon an existing VmPolicy.
665 */
666 public Builder(VmPolicy base) {
667 mMask = base.mask;
668 mClassInstanceLimitNeedCow = true;
669 mClassInstanceLimit = base.classInstanceLimit;
670 }
671
672 /**
673 * Set an upper bound on how many instances of a class can be in memory
674 * at once. Helps to prevent object leaks.
675 */
676 public Builder setClassInstanceLimit(Class klass, int instanceLimit) {
677 if (klass == null) {
678 throw new NullPointerException("klass == null");
679 }
680 if (mClassInstanceLimitNeedCow) {
681 if (mClassInstanceLimit.containsKey(klass) &&
682 mClassInstanceLimit.get(klass) == instanceLimit) {
683 // no-op; don't break COW
684 return this;
685 }
686 mClassInstanceLimitNeedCow = false;
687 mClassInstanceLimit = (HashMap<Class, Integer>) mClassInstanceLimit.clone();
688 } else if (mClassInstanceLimit == null) {
689 mClassInstanceLimit = new HashMap<Class, Integer>();
690 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800691 mMask |= DETECT_VM_INSTANCE_LEAKS;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800692 mClassInstanceLimit.put(klass, instanceLimit);
693 return this;
694 }
695
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800696 /**
697 * Detect leaks of {@link android.app.Activity} subclasses.
698 */
699 public Builder detectActivityLeaks() {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800700 return enable(DETECT_VM_ACTIVITY_LEAKS);
701 }
702
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700703 /**
704 * Detect everything that's potentially suspect.
705 *
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700706 * <p>In the Honeycomb release this includes leaks of
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800707 * SQLite cursors, Activities, and other closable objects
708 * but will likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700709 */
710 public Builder detectAll() {
Jeff Sharkey605eb792014-11-04 13:34:06 -0800711 int flags = DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700712 | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS
Jeff Sharkey605eb792014-11-04 13:34:06 -0800713 | DETECT_VM_FILE_URI_EXPOSURE;
714
715 // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have facility
716 // for apps to mark sockets that should be ignored
717 if (SystemProperties.getBoolean(CLEARTEXT_PROPERTY, false)) {
718 flags |= DETECT_VM_CLEARTEXT_NETWORK;
719 }
720
721 return enable(flags);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700722 }
723
724 /**
725 * Detect when an
726 * {@link android.database.sqlite.SQLiteCursor} or other
727 * SQLite object is finalized without having been closed.
728 *
729 * <p>You always want to explicitly close your SQLite
730 * cursors to avoid unnecessary database contention and
731 * temporary memory leaks.
732 */
733 public Builder detectLeakedSqlLiteObjects() {
734 return enable(DETECT_VM_CURSOR_LEAKS);
735 }
736
737 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700738 * Detect when an {@link java.io.Closeable} or other
739 * object with a explict termination method is finalized
740 * without having been closed.
741 *
742 * <p>You always want to explicitly close such objects to
743 * avoid unnecessary resources leaks.
744 */
745 public Builder detectLeakedClosableObjects() {
746 return enable(DETECT_VM_CLOSABLE_LEAKS);
747 }
748
749 /**
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800750 * Detect when a {@link BroadcastReceiver} or
751 * {@link ServiceConnection} is leaked during {@link Context}
752 * teardown.
753 */
754 public Builder detectLeakedRegistrationObjects() {
755 return enable(DETECT_VM_REGISTRATION_LEAKS);
756 }
757
758 /**
Jeff Sharkey344744b2016-01-28 19:03:30 -0700759 * Detect when this application exposes a {@code file://}
760 * {@link android.net.Uri} to another app.
761 * <p>
762 * This exposure is discouraged since the receiving app may not have
763 * access to the shared path. For example, the receiving app may not
764 * have requested the
765 * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime
766 * permission, or the platform may be sharing the
767 * {@link android.net.Uri} across user profile boundaries.
768 * <p>
769 * Instead, apps should use {@code content://} Uris so the platform
770 * can extend temporary permission for the receiving app to access
771 * the resource.
772 *
773 * @see android.support.v4.content.FileProvider
774 * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700775 */
776 public Builder detectFileUriExposure() {
777 return enable(DETECT_VM_FILE_URI_EXPOSURE);
778 }
779
780 /**
Jeff Sharkey605eb792014-11-04 13:34:06 -0800781 * Detect any network traffic from the calling app which is not
782 * wrapped in SSL/TLS. This can help you detect places that your app
783 * is inadvertently sending cleartext data across the network.
784 * <p>
785 * Using {@link #penaltyDeath()} or
786 * {@link #penaltyDeathOnCleartextNetwork()} will block further
787 * traffic on that socket to prevent accidental data leakage, in
788 * addition to crashing your process.
789 * <p>
790 * Using {@link #penaltyDropBox()} will log the raw contents of the
791 * packet that triggered the violation.
792 * <p>
793 * This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it
794 * may be subject to false positives, such as when STARTTLS
795 * protocols or HTTP proxies are used.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800796 */
797 public Builder detectCleartextNetwork() {
798 return enable(DETECT_VM_CLEARTEXT_NETWORK);
799 }
800
801 /**
802 * Crashes the whole process on violation. This penalty runs at the
803 * end of all enabled penalties so you'll still get your logging or
804 * other violations before the process dies.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700805 */
806 public Builder penaltyDeath() {
807 return enable(PENALTY_DEATH);
808 }
809
810 /**
Jeff Sharkey605eb792014-11-04 13:34:06 -0800811 * Crashes the whole process when cleartext network traffic is
812 * detected.
813 *
814 * @see #detectCleartextNetwork()
Jeff Sharkey605eb792014-11-04 13:34:06 -0800815 */
816 public Builder penaltyDeathOnCleartextNetwork() {
817 return enable(PENALTY_DEATH_ON_CLEARTEXT_NETWORK);
818 }
819
820 /**
Jeff Sharkey344744b2016-01-28 19:03:30 -0700821 * Crashes the whole process when a {@code file://}
822 * {@link android.net.Uri} is exposed beyond this app.
823 *
824 * @see #detectFileUriExposure()
825 */
826 public Builder penaltyDeathOnFileUriExposure() {
827 return enable(PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
828 }
829
830 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700831 * Log detected violations to the system log.
832 */
833 public Builder penaltyLog() {
834 return enable(PENALTY_LOG);
835 }
836
837 /**
838 * Enable detected violations log a stacktrace and timing data
839 * to the {@link android.os.DropBoxManager DropBox} on policy
840 * violation. Intended mostly for platform integrators doing
841 * beta user field data collection.
842 */
843 public Builder penaltyDropBox() {
844 return enable(PENALTY_DROPBOX);
845 }
846
847 private Builder enable(int bit) {
848 mMask |= bit;
849 return this;
850 }
851
852 /**
853 * Construct the VmPolicy instance.
854 *
855 * <p>Note: if no penalties are enabled before calling
856 * <code>build</code>, {@link #penaltyLog} is implicitly
857 * set.
858 */
859 public VmPolicy build() {
860 // If there are detection bits set but no violation bits
861 // set, enable simple logging.
862 if (mMask != 0 &&
863 (mMask & (PENALTY_DEATH | PENALTY_LOG |
864 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
865 penaltyLog();
866 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800867 return new VmPolicy(mMask,
868 mClassInstanceLimit != null ? mClassInstanceLimit : EMPTY_CLASS_LIMIT_MAP);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700869 }
870 }
871 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700872
873 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700874 * Log of strict mode violation stack traces that have occurred
875 * during a Binder call, to be serialized back later to the caller
876 * via Parcel.writeNoException() (amusingly) where the caller can
877 * choose how to react.
878 */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -0700879 private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
880 new ThreadLocal<ArrayList<ViolationInfo>>() {
881 @Override protected ArrayList<ViolationInfo> initialValue() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700882 // Starts null to avoid unnecessary allocations when
883 // checking whether there are any violations or not in
884 // hasGatheredViolations() below.
885 return null;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700886 }
887 };
888
889 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700890 * Sets the policy for what actions on the current thread should
891 * be detected, as well as the penalty if such actions occur.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700892 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700893 * <p>Internally this sets a thread-local variable which is
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700894 * propagated across cross-process IPC calls, meaning you can
895 * catch violations when a system service or another process
896 * accesses the disk or network on your behalf.
897 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700898 * @param policy the policy to put into place
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700899 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700900 public static void setThreadPolicy(final ThreadPolicy policy) {
901 setThreadPolicyMask(policy.mask);
902 }
903
904 private static void setThreadPolicyMask(final int policyMask) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700905 // In addition to the Java-level thread-local in Dalvik's
906 // BlockGuard, we also need to keep a native thread-local in
907 // Binder in order to propagate the value across Binder calls,
908 // even across native-only processes. The two are kept in
909 // sync via the callback to onStrictModePolicyChange, below.
910 setBlockGuardPolicy(policyMask);
911
912 // And set the Android native version...
913 Binder.setThreadStrictModePolicy(policyMask);
914 }
915
916 // Sets the policy in Dalvik/libcore (BlockGuard)
917 private static void setBlockGuardPolicy(final int policyMask) {
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700918 if (policyMask == 0) {
919 BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
920 return;
921 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -0700922 final BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
923 final AndroidBlockGuardPolicy androidPolicy;
924 if (policy instanceof AndroidBlockGuardPolicy) {
925 androidPolicy = (AndroidBlockGuardPolicy) policy;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700926 } else {
Jeff Sharkeya2934d52013-06-14 14:43:18 -0700927 androidPolicy = threadAndroidPolicy.get();
928 BlockGuard.setThreadPolicy(androidPolicy);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700929 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -0700930 androidPolicy.setPolicyMask(policyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700931 }
932
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -0800933 // Sets up CloseGuard in Dalvik/libcore
934 private static void setCloseGuardEnabled(boolean enabled) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -0800935 if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -0800936 CloseGuard.setReporter(new AndroidCloseGuardReporter());
937 }
938 CloseGuard.setEnabled(enabled);
939 }
940
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800941 /**
942 * @hide
943 */
944 public static class StrictModeViolation extends BlockGuard.BlockGuardPolicyException {
945 public StrictModeViolation(int policyState, int policyViolated, String message) {
946 super(policyState, policyViolated, message);
947 }
948 }
949
950 /**
951 * @hide
952 */
953 public static class StrictModeNetworkViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700954 public StrictModeNetworkViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800955 super(policyMask, DETECT_NETWORK, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700956 }
957 }
958
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800959 /**
960 * @hide
961 */
962 private static class StrictModeDiskReadViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700963 public StrictModeDiskReadViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800964 super(policyMask, DETECT_DISK_READ, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700965 }
966 }
967
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800968 /**
969 * @hide
970 */
971 private static class StrictModeDiskWriteViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700972 public StrictModeDiskWriteViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800973 super(policyMask, DETECT_DISK_WRITE, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700974 }
975 }
976
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800977 /**
978 * @hide
979 */
980 private static class StrictModeCustomViolation extends StrictModeViolation {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800981 public StrictModeCustomViolation(int policyMask, String name) {
982 super(policyMask, DETECT_CUSTOM, name);
983 }
984 }
985
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700986 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800987 * @hide
988 */
989 private static class StrictModeResourceMismatchViolation extends StrictModeViolation {
990 public StrictModeResourceMismatchViolation(int policyMask, Object tag) {
991 super(policyMask, DETECT_RESOURCE_MISMATCH, tag != null ? tag.toString() : null);
992 }
993 }
994
995 /**
Shubham Ajmerac95b2c82016-09-29 16:35:36 +0100996 * @hide
997 */
998 private static class StrictModeUnbufferedIOViolation extends StrictModeViolation {
999 public StrictModeUnbufferedIOViolation(int policyMask) {
1000 super(policyMask, DETECT_UNBUFFERED_IO, null);
1001 }
1002 }
1003
1004 /**
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -07001005 * Returns the bitmask of the current thread's policy.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001006 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001007 * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
1008 *
1009 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001010 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001011 public static int getThreadPolicyMask() {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001012 return BlockGuard.getThreadPolicy().getPolicyMask();
1013 }
1014
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001015 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001016 * Returns the current thread's policy.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001017 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001018 public static ThreadPolicy getThreadPolicy() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001019 // TODO: this was a last minute Gingerbread API change (to
1020 // introduce VmPolicy cleanly) but this isn't particularly
1021 // optimal for users who might call this method often. This
1022 // should be in a thread-local and not allocate on each call.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001023 return new ThreadPolicy(getThreadPolicyMask());
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001024 }
1025
1026 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001027 * A convenience wrapper that takes the current
1028 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
1029 * to permit both disk reads &amp; writes, and sets the new policy
1030 * with {@link #setThreadPolicy}, returning the old policy so you
1031 * can restore it at the end of a block.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001032 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001033 * @return the old policy, to be passed to {@link #setThreadPolicy} to
1034 * restore the policy at the end of a block
1035 */
1036 public static ThreadPolicy allowThreadDiskWrites() {
1037 int oldPolicyMask = getThreadPolicyMask();
1038 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
1039 if (newPolicyMask != oldPolicyMask) {
1040 setThreadPolicyMask(newPolicyMask);
1041 }
1042 return new ThreadPolicy(oldPolicyMask);
1043 }
1044
1045 /**
1046 * A convenience wrapper that takes the current
1047 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
1048 * to permit disk reads, and sets the new policy
1049 * with {@link #setThreadPolicy}, returning the old policy so you
1050 * can restore it at the end of a block.
1051 *
1052 * @return the old policy, to be passed to setThreadPolicy to
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001053 * restore the policy.
1054 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001055 public static ThreadPolicy allowThreadDiskReads() {
1056 int oldPolicyMask = getThreadPolicyMask();
1057 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
1058 if (newPolicyMask != oldPolicyMask) {
1059 setThreadPolicyMask(newPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001060 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001061 return new ThreadPolicy(oldPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001062 }
1063
Brad Fitzpatrickf5454592010-11-24 15:27:51 -08001064 // We don't want to flash the screen red in the system server
1065 // process, nor do we want to modify all the call sites of
1066 // conditionallyEnableDebugLogging() in the system server,
1067 // so instead we use this to determine if we are the system server.
1068 private static boolean amTheSystemServerProcess() {
1069 // Fast path. Most apps don't have the system server's UID.
1070 if (Process.myUid() != Process.SYSTEM_UID) {
1071 return false;
1072 }
1073
1074 // The settings app, though, has the system server's UID so
1075 // look up our stack to see if we came from the system server.
1076 Throwable stack = new Throwable();
1077 stack.fillInStackTrace();
1078 for (StackTraceElement ste : stack.getStackTrace()) {
1079 String clsName = ste.getClassName();
1080 if (clsName != null && clsName.startsWith("com.android.server.")) {
1081 return true;
1082 }
1083 }
1084 return false;
1085 }
1086
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001087 /**
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001088 * Enable DropBox logging for debug phone builds.
1089 *
1090 * @hide
1091 */
1092 public static boolean conditionallyEnableDebugLogging() {
Christopher Tatebc6f0ce2011-11-03 12:18:43 -07001093 boolean doFlashes = SystemProperties.getBoolean(VISUAL_PROPERTY, false)
1094 && !amTheSystemServerProcess();
1095 final boolean suppress = SystemProperties.getBoolean(DISABLE_PROPERTY, false);
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001096
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001097 // For debug builds, log event loop stalls to dropbox for analysis.
1098 // Similar logic also appears in ActivityThread.java for system apps.
Christopher Tatebc6f0ce2011-11-03 12:18:43 -07001099 if (!doFlashes && (IS_USER_BUILD || suppress)) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -08001100 setCloseGuardEnabled(false);
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001101 return false;
1102 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001103
Christopher Tatebc6f0ce2011-11-03 12:18:43 -07001104 // Eng builds have flashes on all the time. The suppression property
1105 // overrides this, so we force the behavior only after the short-circuit
1106 // check above.
1107 if (IS_ENG_BUILD) {
1108 doFlashes = true;
1109 }
1110
Jeff Brownbe7c29c2011-10-11 11:35:23 -07001111 // Thread policy controls BlockGuard.
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001112 int threadPolicyMask = StrictMode.DETECT_DISK_WRITE |
1113 StrictMode.DETECT_DISK_READ |
1114 StrictMode.DETECT_NETWORK;
1115
1116 if (!IS_USER_BUILD) {
1117 threadPolicyMask |= StrictMode.PENALTY_DROPBOX;
1118 }
1119 if (doFlashes) {
1120 threadPolicyMask |= StrictMode.PENALTY_FLASH;
1121 }
1122
1123 StrictMode.setThreadPolicyMask(threadPolicyMask);
1124
Jeff Brownbe7c29c2011-10-11 11:35:23 -07001125 // VM Policy controls CloseGuard, detection of Activity leaks,
1126 // and instance counting.
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001127 if (IS_USER_BUILD) {
1128 setCloseGuardEnabled(false);
1129 } else {
Jeff Brownd5875d92011-10-09 14:59:37 -07001130 VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll().penaltyDropBox();
1131 if (IS_ENG_BUILD) {
1132 policyBuilder.penaltyLog();
1133 }
1134 setVmPolicy(policyBuilder.build());
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001135 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
1136 }
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001137 return true;
1138 }
1139
1140 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001141 * Used by the framework to make network usage on the main
1142 * thread a fatal error.
1143 *
1144 * @hide
1145 */
1146 public static void enableDeathOnNetwork() {
1147 int oldPolicy = getThreadPolicyMask();
1148 int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
1149 setThreadPolicyMask(newPolicy);
1150 }
1151
1152 /**
Jeff Sharkey344744b2016-01-28 19:03:30 -07001153 * Used by the framework to make file usage a fatal error.
1154 *
1155 * @hide
1156 */
1157 public static void enableDeathOnFileUriExposure() {
1158 sVmPolicyMask |= DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
1159 }
1160
1161 /**
1162 * Used by lame internal apps that haven't done the hard work to get
1163 * themselves off file:// Uris yet.
1164 *
1165 * @hide
1166 */
1167 public static void disableDeathOnFileUriExposure() {
1168 sVmPolicyMask &= ~(DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
1169 }
1170
1171 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001172 * Parses the BlockGuard policy mask out from the Exception's
1173 * getMessage() String value. Kinda gross, but least
1174 * invasive. :/
1175 *
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001176 * Input is of the following forms:
1177 * "policy=137 violation=64"
1178 * "policy=137 violation=64 msg=Arbitrary text"
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001179 *
1180 * Returns 0 on failure, which is a valid policy, but not a
1181 * valid policy during a violation (else there must've been
1182 * some policy in effect to violate).
1183 */
1184 private static int parsePolicyFromMessage(String message) {
1185 if (message == null || !message.startsWith("policy=")) {
1186 return 0;
1187 }
1188 int spaceIndex = message.indexOf(' ');
1189 if (spaceIndex == -1) {
1190 return 0;
1191 }
1192 String policyString = message.substring(7, spaceIndex);
1193 try {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001194 return Integer.parseInt(policyString);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001195 } catch (NumberFormatException e) {
1196 return 0;
1197 }
1198 }
1199
1200 /**
1201 * Like parsePolicyFromMessage(), but returns the violation.
1202 */
1203 private static int parseViolationFromMessage(String message) {
1204 if (message == null) {
1205 return 0;
1206 }
1207 int violationIndex = message.indexOf("violation=");
1208 if (violationIndex == -1) {
1209 return 0;
1210 }
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001211 int numberStartIndex = violationIndex + "violation=".length();
1212 int numberEndIndex = message.indexOf(' ', numberStartIndex);
1213 if (numberEndIndex == -1) {
1214 numberEndIndex = message.length();
1215 }
1216 String violationString = message.substring(numberStartIndex, numberEndIndex);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001217 try {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001218 return Integer.parseInt(violationString);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001219 } catch (NumberFormatException e) {
1220 return 0;
1221 }
1222 }
1223
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001224 private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
1225 new ThreadLocal<ArrayList<ViolationInfo>>() {
1226 @Override protected ArrayList<ViolationInfo> initialValue() {
1227 return new ArrayList<ViolationInfo>();
1228 }
1229 };
1230
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001231 // Note: only access this once verifying the thread has a Looper.
1232 private static final ThreadLocal<Handler> threadHandler = new ThreadLocal<Handler>() {
1233 @Override protected Handler initialValue() {
1234 return new Handler();
1235 }
1236 };
1237
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001238 private static final ThreadLocal<AndroidBlockGuardPolicy>
1239 threadAndroidPolicy = new ThreadLocal<AndroidBlockGuardPolicy>() {
1240 @Override
1241 protected AndroidBlockGuardPolicy initialValue() {
1242 return new AndroidBlockGuardPolicy(0);
1243 }
1244 };
1245
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001246 private static boolean tooManyViolationsThisLoop() {
1247 return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
1248 }
1249
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001250 private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
1251 private int mPolicyMask;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001252
1253 // Map from violation stacktrace hashcode -> uptimeMillis of
1254 // last violation. No locking needed, as this is only
1255 // accessed by the same thread.
Dianne Hackborn390517b2013-05-30 15:03:32 -07001256 private ArrayMap<Integer, Long> mLastViolationTime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001257
1258 public AndroidBlockGuardPolicy(final int policyMask) {
1259 mPolicyMask = policyMask;
1260 }
1261
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001262 @Override
1263 public String toString() {
1264 return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
1265 }
1266
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001267 // Part of BlockGuard.Policy interface:
1268 public int getPolicyMask() {
1269 return mPolicyMask;
1270 }
1271
1272 // Part of BlockGuard.Policy interface:
1273 public void onWriteToDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001274 if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001275 return;
1276 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001277 if (tooManyViolationsThisLoop()) {
1278 return;
1279 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001280 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
1281 e.fillInStackTrace();
1282 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001283 }
1284
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001285 // Not part of BlockGuard.Policy; just part of StrictMode:
1286 void onCustomSlowCall(String name) {
1287 if ((mPolicyMask & DETECT_CUSTOM) == 0) {
1288 return;
1289 }
1290 if (tooManyViolationsThisLoop()) {
1291 return;
1292 }
1293 BlockGuard.BlockGuardPolicyException e = new StrictModeCustomViolation(mPolicyMask, name);
1294 e.fillInStackTrace();
1295 startHandlingViolationException(e);
1296 }
1297
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001298 // Not part of BlockGuard.Policy; just part of StrictMode:
1299 void onResourceMismatch(Object tag) {
1300 if ((mPolicyMask & DETECT_RESOURCE_MISMATCH) == 0) {
1301 return;
1302 }
1303 if (tooManyViolationsThisLoop()) {
1304 return;
1305 }
1306 BlockGuard.BlockGuardPolicyException e =
1307 new StrictModeResourceMismatchViolation(mPolicyMask, tag);
1308 e.fillInStackTrace();
1309 startHandlingViolationException(e);
1310 }
1311
Shubham Ajmerac95b2c82016-09-29 16:35:36 +01001312 // Part of BlockGuard.Policy; just part of StrictMode:
1313 public void onUnbufferedIO() {
1314 if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
1315 return;
1316 }
1317 if (tooManyViolationsThisLoop()) {
1318 return;
1319 }
1320 BlockGuard.BlockGuardPolicyException e =
1321 new StrictModeUnbufferedIOViolation(mPolicyMask);
1322 e.fillInStackTrace();
1323 startHandlingViolationException(e);
1324 }
1325
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001326 // Part of BlockGuard.Policy interface:
1327 public void onReadFromDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001328 if ((mPolicyMask & DETECT_DISK_READ) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001329 return;
1330 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001331 if (tooManyViolationsThisLoop()) {
1332 return;
1333 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001334 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
1335 e.fillInStackTrace();
1336 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001337 }
1338
1339 // Part of BlockGuard.Policy interface:
1340 public void onNetwork() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001341 if ((mPolicyMask & DETECT_NETWORK) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001342 return;
1343 }
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001344 if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
1345 throw new NetworkOnMainThreadException();
1346 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001347 if (tooManyViolationsThisLoop()) {
1348 return;
1349 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001350 BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
1351 e.fillInStackTrace();
1352 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001353 }
1354
1355 public void setPolicyMask(int policyMask) {
1356 mPolicyMask = policyMask;
1357 }
1358
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001359 // Start handling a violation that just started and hasn't
1360 // actually run yet (e.g. no disk write or network operation
1361 // has yet occurred). This sees if we're in an event loop
1362 // thread and, if so, uses it to roughly measure how long the
1363 // violation took.
1364 void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001365 final ViolationInfo info = new ViolationInfo(e, e.getPolicy());
1366 info.violationUptimeMillis = SystemClock.uptimeMillis();
1367 handleViolationWithTimingAttempt(info);
1368 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001369
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001370 // Attempts to fill in the provided ViolationInfo's
1371 // durationMillis field if this thread has a Looper we can use
1372 // to measure with. We measure from the time of violation
1373 // until the time the looper is idle again (right before
1374 // the next epoll_wait)
1375 void handleViolationWithTimingAttempt(final ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001376 Looper looper = Looper.myLooper();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001377
1378 // Without a Looper, we're unable to time how long the
1379 // violation takes place. This case should be rare, as
1380 // most users will care about timing violations that
1381 // happen on their main UI thread. Note that this case is
1382 // also hit when a violation takes place in a Binder
1383 // thread, in "gather" mode. In this case, the duration
1384 // of the violation is computed by the ultimate caller and
1385 // its Looper, if any.
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001386 //
1387 // Also, as a special short-cut case when the only penalty
1388 // bit is death, we die immediately, rather than timing
1389 // the violation's duration. This makes it convenient to
1390 // use in unit tests too, rather than waiting on a Looper.
1391 //
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001392 // TODO: if in gather mode, ignore Looper.myLooper() and always
1393 // go into this immediate mode?
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001394 if (looper == null ||
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001395 (info.policy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001396 info.durationMillis = -1; // unknown (redundant, already set)
1397 handleViolation(info);
1398 return;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001399 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001400
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001401 final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001402 if (records.size() >= MAX_OFFENSES_PER_LOOP) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001403 // Not worth measuring. Too many offenses in one loop.
1404 return;
1405 }
1406 records.add(info);
1407 if (records.size() > 1) {
1408 // There's already been a violation this loop, so we've already
1409 // registered an idle handler to process the list of violations
1410 // at the end of this Looper's loop.
1411 return;
1412 }
1413
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001414 final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ?
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08001415 sWindowManager.get() : null;
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001416 if (windowManager != null) {
1417 try {
1418 windowManager.showStrictModeViolation(true);
1419 } catch (RemoteException unused) {
1420 }
1421 }
1422
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001423 // We post a runnable to a Handler (== delay 0 ms) for
1424 // measuring the end time of a violation instead of using
1425 // an IdleHandler (as was previously used) because an
1426 // IdleHandler may not run for quite a long period of time
1427 // if an ongoing animation is happening and continually
1428 // posting ASAP (0 ms) animation steps. Animations are
1429 // throttled back to 60fps via SurfaceFlinger/View
1430 // invalidates, _not_ by posting frame updates every 16
1431 // milliseconds.
Jeff Sharkey3761f332012-03-16 15:46:46 -07001432 threadHandler.get().postAtFrontOfQueue(new Runnable() {
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001433 public void run() {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001434 long loopFinishTime = SystemClock.uptimeMillis();
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001435
1436 // Note: we do this early, before handling the
1437 // violation below, as handling the violation
1438 // may include PENALTY_DEATH and we don't want
1439 // to keep the red border on.
1440 if (windowManager != null) {
1441 try {
1442 windowManager.showStrictModeViolation(false);
1443 } catch (RemoteException unused) {
1444 }
1445 }
1446
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001447 for (int n = 0; n < records.size(); ++n) {
1448 ViolationInfo v = records.get(n);
1449 v.violationNumThisLoop = n + 1;
1450 v.durationMillis =
1451 (int) (loopFinishTime - v.violationUptimeMillis);
1452 handleViolation(v);
1453 }
1454 records.clear();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001455 }
1456 });
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001457 }
1458
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001459 // Note: It's possible (even quite likely) that the
1460 // thread-local policy mask has changed from the time the
1461 // violation fired and now (after the violating code ran) due
1462 // to people who push/pop temporary policy in regions of code,
1463 // hence the policy being passed around.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001464 void handleViolation(final ViolationInfo info) {
1465 if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) {
1466 Log.wtf(TAG, "unexpected null stacktrace");
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001467 return;
1468 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001469
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001470 if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001471
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001472 if ((info.policy & PENALTY_GATHER) != 0) {
1473 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001474 if (violations == null) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001475 violations = new ArrayList<ViolationInfo>(1);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001476 gatheredViolations.set(violations);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001477 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001478 for (ViolationInfo previous : violations) {
1479 if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001480 // Duplicate. Don't log.
1481 return;
1482 }
1483 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001484 violations.add(info);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001485 return;
1486 }
1487
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001488 // Not perfect, but fast and good enough for dup suppression.
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08001489 Integer crashFingerprint = info.hashCode();
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001490 long lastViolationTime = 0;
Dianne Hackborn390517b2013-05-30 15:03:32 -07001491 if (mLastViolationTime != null) {
1492 Long vtime = mLastViolationTime.get(crashFingerprint);
1493 if (vtime != null) {
1494 lastViolationTime = vtime;
1495 }
1496 } else {
1497 mLastViolationTime = new ArrayMap<Integer, Long>(1);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001498 }
1499 long now = SystemClock.uptimeMillis();
1500 mLastViolationTime.put(crashFingerprint, now);
1501 long timeSinceLastViolationMillis = lastViolationTime == 0 ?
1502 Long.MAX_VALUE : (now - lastViolationTime);
1503
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001504 if ((info.policy & PENALTY_LOG) != 0 &&
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001505 timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001506 if (info.durationMillis != -1) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001507 Log.d(TAG, "StrictMode policy violation; ~duration=" +
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001508 info.durationMillis + " ms: " + info.crashInfo.stackTrace);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001509 } else {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001510 Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001511 }
1512 }
1513
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001514 // The violationMaskSubset, passed to ActivityManager, is a
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001515 // subset of the original StrictMode policy bitmask, with
1516 // only the bit violated and penalty bits to be executed
1517 // by the ActivityManagerService remaining set.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001518 int violationMaskSubset = 0;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001519
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001520 if ((info.policy & PENALTY_DIALOG) != 0 &&
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001521 timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001522 violationMaskSubset |= PENALTY_DIALOG;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001523 }
1524
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001525 if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
1526 violationMaskSubset |= PENALTY_DROPBOX;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001527 }
1528
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001529 if (violationMaskSubset != 0) {
1530 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1531 violationMaskSubset |= violationBit;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001532 final int savedPolicyMask = getThreadPolicyMask();
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001533
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001534 final boolean justDropBox = (info.policy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001535 if (justDropBox) {
1536 // If all we're going to ask the activity manager
1537 // to do is dropbox it (the common case during
1538 // platform development), we can avoid doing this
1539 // call synchronously which Binder data suggests
1540 // isn't always super fast, despite the implementation
1541 // in the ActivityManager trying to be mostly async.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001542 dropboxViolationAsync(violationMaskSubset, info);
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001543 return;
1544 }
1545
1546 // Normal synchronous call to the ActivityManager.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001547 try {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001548 // First, remove any policy before we call into the Activity Manager,
1549 // otherwise we'll infinite recurse as we try to log policy violations
1550 // to disk, thus violating policy, thus requiring logging, etc...
1551 // We restore the current policy below, in the finally block.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001552 setThreadPolicyMask(0);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001553
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001554 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1555 RuntimeInit.getApplicationObject(),
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001556 violationMaskSubset,
1557 info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001558 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001559 if (e instanceof DeadObjectException) {
1560 // System process is dead; ignore
1561 } else {
1562 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1563 }
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001564 } finally {
1565 // Restore the policy.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001566 setThreadPolicyMask(savedPolicyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001567 }
1568 }
1569
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001570 if ((info.policy & PENALTY_DEATH) != 0) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001571 executeDeathPenalty(info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001572 }
1573 }
1574 }
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001575
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001576 private static void executeDeathPenalty(ViolationInfo info) {
1577 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1578 throw new StrictModeViolation(info.policy, violationBit, null);
1579 }
1580
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001581 /**
1582 * In the common case, as set by conditionallyEnableDebugLogging,
1583 * we're just dropboxing any violations but not showing a dialog,
1584 * not loggging, and not killing the process. In these cases we
1585 * don't need to do a synchronous call to the ActivityManager.
1586 * This is used by both per-thread and vm-wide violations when
1587 * applicable.
1588 */
1589 private static void dropboxViolationAsync(
1590 final int violationMaskSubset, final ViolationInfo info) {
1591 int outstanding = sDropboxCallsInFlight.incrementAndGet();
1592 if (outstanding > 20) {
1593 // What's going on? Let's not make make the situation
1594 // worse and just not log.
1595 sDropboxCallsInFlight.decrementAndGet();
1596 return;
1597 }
1598
1599 if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1600
1601 new Thread("callActivityManagerForStrictModeDropbox") {
1602 public void run() {
1603 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1604 try {
Brad Fitzpatrick10656852010-11-23 19:01:13 -08001605 IActivityManager am = ActivityManagerNative.getDefault();
1606 if (am == null) {
1607 Log.d(TAG, "No activity manager; failed to Dropbox violation.");
1608 } else {
1609 am.handleApplicationStrictModeViolation(
1610 RuntimeInit.getApplicationObject(),
1611 violationMaskSubset,
1612 info);
1613 }
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001614 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001615 if (e instanceof DeadObjectException) {
1616 // System process is dead; ignore
1617 } else {
1618 Log.e(TAG, "RemoteException handling StrictMode violation", e);
1619 }
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001620 }
1621 int outstanding = sDropboxCallsInFlight.decrementAndGet();
1622 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
1623 }
1624 }.start();
1625 }
1626
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001627 private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
Jeff Sharkey605eb792014-11-04 13:34:06 -08001628 public void report(String message, Throwable allocationSite) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001629 onVmPolicyViolation(message, allocationSite);
1630 }
1631 }
1632
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001633 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001634 * Called from Parcel.writeNoException()
1635 */
1636 /* package */ static boolean hasGatheredViolations() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001637 return gatheredViolations.get() != null;
1638 }
1639
1640 /**
1641 * Called from Parcel.writeException(), so we drop this memory and
1642 * don't incorrectly attribute it to the wrong caller on the next
1643 * Binder call on this thread.
1644 */
1645 /* package */ static void clearGatheredViolations() {
1646 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001647 }
1648
1649 /**
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001650 * @hide
1651 */
1652 public static void conditionallyCheckInstanceCounts() {
1653 VmPolicy policy = getVmPolicy();
Mathieu Chartierd288a262015-07-10 13:44:42 -07001654 int policySize = policy.classInstanceLimit.size();
1655 if (policySize == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001656 return;
1657 }
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08001658
1659 System.gc();
1660 System.runFinalization();
1661 System.gc();
1662
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001663 // Note: classInstanceLimit is immutable, so this is lock-free
Mathieu Chartierd288a262015-07-10 13:44:42 -07001664 // Create the classes array.
1665 Class[] classes = policy.classInstanceLimit.keySet().toArray(new Class[policySize]);
1666 long[] instanceCounts = VMDebug.countInstancesOfClasses(classes, false);
1667 for (int i = 0; i < classes.length; ++i) {
1668 Class klass = classes[i];
1669 int limit = policy.classInstanceLimit.get(klass);
1670 long instances = instanceCounts[i];
1671 if (instances > limit) {
1672 Throwable tr = new InstanceCountViolation(klass, instances, limit);
1673 onVmPolicyViolation(tr.getMessage(), tr);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001674 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001675 }
1676 }
1677
1678 private static long sLastInstanceCountCheckMillis = 0;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001679 private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001680 private static final MessageQueue.IdleHandler sProcessIdleHandler =
1681 new MessageQueue.IdleHandler() {
1682 public boolean queueIdle() {
1683 long now = SystemClock.uptimeMillis();
1684 if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1685 sLastInstanceCountCheckMillis = now;
1686 conditionallyCheckInstanceCounts();
1687 }
1688 return true;
1689 }
1690 };
1691
1692 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001693 * Sets the policy for what actions in the VM process (on any
1694 * thread) should be detected, as well as the penalty if such
1695 * actions occur.
1696 *
1697 * @param policy the policy to put into place
1698 */
1699 public static void setVmPolicy(final VmPolicy policy) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001700 synchronized (StrictMode.class) {
1701 sVmPolicy = policy;
1702 sVmPolicyMask = policy.mask;
1703 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001704
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001705 Looper looper = Looper.getMainLooper();
1706 if (looper != null) {
1707 MessageQueue mq = looper.mQueue;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001708 if (policy.classInstanceLimit.size() == 0 ||
1709 (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001710 mq.removeIdleHandler(sProcessIdleHandler);
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001711 sIsIdlerRegistered = false;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001712 } else if (!sIsIdlerRegistered) {
1713 mq.addIdleHandler(sProcessIdleHandler);
1714 sIsIdlerRegistered = true;
1715 }
1716 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08001717
1718 int networkPolicy = NETWORK_POLICY_ACCEPT;
1719 if ((sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
1720 if ((sVmPolicyMask & PENALTY_DEATH) != 0
1721 || (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
1722 networkPolicy = NETWORK_POLICY_REJECT;
1723 } else {
1724 networkPolicy = NETWORK_POLICY_LOG;
1725 }
1726 }
1727
1728 final INetworkManagementService netd = INetworkManagementService.Stub.asInterface(
1729 ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
1730 if (netd != null) {
1731 try {
1732 netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
1733 } catch (RemoteException ignored) {
1734 }
1735 } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
1736 Log.w(TAG, "Dropping requested network policy due to missing service!");
1737 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001738 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001739 }
1740
1741 /**
1742 * Gets the current VM policy.
1743 */
1744 public static VmPolicy getVmPolicy() {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001745 synchronized (StrictMode.class) {
1746 return sVmPolicy;
1747 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001748 }
1749
1750 /**
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001751 * Enable the recommended StrictMode defaults, with violations just being logged.
1752 *
1753 * <p>This catches disk and network access on the main thread, as
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001754 * well as leaked SQLite cursors and unclosed resources. This is
1755 * simply a wrapper around {@link #setVmPolicy} and {@link
1756 * #setThreadPolicy}.
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001757 */
1758 public static void enableDefaults() {
1759 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
1760 .detectAll()
1761 .penaltyLog()
1762 .build());
1763 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001764 .detectAll()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001765 .penaltyLog()
1766 .build());
1767 }
1768
1769 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001770 * @hide
1771 */
1772 public static boolean vmSqliteObjectLeaksEnabled() {
1773 return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
1774 }
1775
1776 /**
1777 * @hide
1778 */
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001779 public static boolean vmClosableObjectLeaksEnabled() {
1780 return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
1781 }
1782
1783 /**
1784 * @hide
1785 */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001786 public static boolean vmRegistrationLeaksEnabled() {
1787 return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
1788 }
1789
1790 /**
1791 * @hide
1792 */
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001793 public static boolean vmFileUriExposureEnabled() {
1794 return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
1795 }
1796
1797 /**
1798 * @hide
1799 */
Jeff Sharkey605eb792014-11-04 13:34:06 -08001800 public static boolean vmCleartextNetworkEnabled() {
1801 return (sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
1802 }
1803
1804 /**
1805 * @hide
1806 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001807 public static void onSqliteObjectLeaked(String message, Throwable originStack) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001808 onVmPolicyViolation(message, originStack);
1809 }
1810
Steve Block08d584c2011-05-17 19:05:03 +01001811 /**
1812 * @hide
1813 */
1814 public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
1815 onVmPolicyViolation(null, originStack);
1816 }
1817
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001818 /**
1819 * @hide
1820 */
1821 public static void onIntentReceiverLeaked(Throwable originStack) {
1822 onVmPolicyViolation(null, originStack);
1823 }
1824
1825 /**
1826 * @hide
1827 */
1828 public static void onServiceConnectionLeaked(Throwable originStack) {
1829 onVmPolicyViolation(null, originStack);
1830 }
1831
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001832 /**
1833 * @hide
1834 */
Jeff Sharkey344744b2016-01-28 19:03:30 -07001835 public static void onFileUriExposed(Uri uri, String location) {
1836 final String message = uri + " exposed beyond app through " + location;
1837 if ((sVmPolicyMask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
1838 throw new FileUriExposedException(message);
1839 } else {
1840 onVmPolicyViolation(null, new Throwable(message));
1841 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08001842 }
1843
1844 /**
1845 * @hide
1846 */
1847 public static void onCleartextNetworkDetected(byte[] firstPacket) {
1848 byte[] rawAddr = null;
1849 if (firstPacket != null) {
1850 if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
1851 // IPv4
1852 rawAddr = new byte[4];
1853 System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
1854 } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
1855 // IPv6
1856 rawAddr = new byte[16];
1857 System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
1858 }
1859 }
1860
1861 final int uid = android.os.Process.myUid();
1862 String msg = "Detected cleartext network traffic from UID " + uid;
1863 if (rawAddr != null) {
1864 try {
1865 msg = "Detected cleartext network traffic from UID " + uid + " to "
1866 + InetAddress.getByAddress(rawAddr);
1867 } catch (UnknownHostException ignored) {
1868 }
1869 }
1870
1871 final boolean forceDeath = (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
1872 onVmPolicyViolation(HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg),
1873 forceDeath);
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001874 }
1875
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001876 // Map from VM violation fingerprint to uptime millis.
1877 private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
1878
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001879 /**
1880 * @hide
1881 */
1882 public static void onVmPolicyViolation(String message, Throwable originStack) {
Jeff Sharkey605eb792014-11-04 13:34:06 -08001883 onVmPolicyViolation(message, originStack, false);
1884 }
1885
1886 /**
1887 * @hide
1888 */
1889 public static void onVmPolicyViolation(String message, Throwable originStack,
1890 boolean forceDeath) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001891 final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
Jeff Sharkey605eb792014-11-04 13:34:06 -08001892 final boolean penaltyDeath = ((sVmPolicyMask & PENALTY_DEATH) != 0) || forceDeath;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001893 final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
Jeff Sharkey605eb792014-11-04 13:34:06 -08001894 final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicyMask);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001895
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001896 // Erase stuff not relevant for process-wide violations
1897 info.numAnimationsRunning = 0;
1898 info.tags = null;
1899 info.broadcastIntentAction = null;
1900
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001901 final Integer fingerprint = info.hashCode();
1902 final long now = SystemClock.uptimeMillis();
1903 long lastViolationTime = 0;
1904 long timeSinceLastViolationMillis = Long.MAX_VALUE;
1905 synchronized (sLastVmViolationTime) {
1906 if (sLastVmViolationTime.containsKey(fingerprint)) {
1907 lastViolationTime = sLastVmViolationTime.get(fingerprint);
1908 timeSinceLastViolationMillis = now - lastViolationTime;
1909 }
1910 if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
1911 sLastVmViolationTime.put(fingerprint, now);
1912 }
1913 }
1914
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001915 if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001916 Log.e(TAG, message, originStack);
1917 }
1918
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001919 int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001920
1921 if (penaltyDropbox && !penaltyDeath) {
1922 // Common case for userdebug/eng builds. If no death and
1923 // just dropboxing, we can do the ActivityManager call
1924 // asynchronously.
1925 dropboxViolationAsync(violationMaskSubset, info);
1926 return;
1927 }
1928
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001929 if (penaltyDropbox && lastViolationTime == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001930 // The violationMask, passed to ActivityManager, is a
1931 // subset of the original StrictMode policy bitmask, with
1932 // only the bit violated and penalty bits to be executed
1933 // by the ActivityManagerService remaining set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001934 final int savedPolicyMask = getThreadPolicyMask();
1935 try {
1936 // First, remove any policy before we call into the Activity Manager,
1937 // otherwise we'll infinite recurse as we try to log policy violations
1938 // to disk, thus violating policy, thus requiring logging, etc...
1939 // We restore the current policy below, in the finally block.
1940 setThreadPolicyMask(0);
1941
1942 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1943 RuntimeInit.getApplicationObject(),
1944 violationMaskSubset,
1945 info);
1946 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001947 if (e instanceof DeadObjectException) {
1948 // System process is dead; ignore
1949 } else {
1950 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1951 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001952 } finally {
1953 // Restore the policy.
1954 setThreadPolicyMask(savedPolicyMask);
1955 }
1956 }
1957
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001958 if (penaltyDeath) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001959 System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
1960 Process.killProcess(Process.myPid());
1961 System.exit(10);
1962 }
1963 }
1964
1965 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001966 * Called from Parcel.writeNoException()
1967 */
1968 /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001969 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001970 if (violations == null) {
1971 p.writeInt(0);
1972 } else {
Jeff Sharkey20db11c2016-12-06 16:47:00 -07001973 // To avoid taking up too much transaction space, only include
1974 // details for the first 3 violations. Deep inside, CrashInfo
1975 // will truncate each stack trace to ~20kB.
1976 final int size = Math.min(violations.size(), 3);
1977 p.writeInt(size);
1978 for (int i = 0; i < size; i++) {
1979 violations.get(i).writeToParcel(p, 0);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001980 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001981 }
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001982 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001983 }
1984
1985 private static class LogStackTrace extends Exception {}
1986
1987 /**
1988 * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
1989 * we here read back all the encoded violations.
1990 */
1991 /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
1992 // Our own stack trace to append
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001993 StringWriter sw = new StringWriter();
Jeff Sharkey20db11c2016-12-06 16:47:00 -07001994 sw.append("# via Binder call with stack:\n");
Dianne Hackborn8c841092013-06-24 13:46:13 -07001995 PrintWriter pw = new FastPrintWriter(sw, false, 256);
1996 new LogStackTrace().printStackTrace(pw);
1997 pw.flush();
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001998 String ourStack = sw.toString();
1999
Jeff Sharkey20db11c2016-12-06 16:47:00 -07002000 final int policyMask = getThreadPolicyMask();
2001 final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002002
Jeff Sharkey20db11c2016-12-06 16:47:00 -07002003 final int size = p.readInt();
2004 for (int i = 0; i < size; i++) {
2005 final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
2006 info.crashInfo.appendStackTrace(ourStack);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002007 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2008 if (policy instanceof AndroidBlockGuardPolicy) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002009 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002010 }
2011 }
2012 }
2013
2014 /**
Brad Fitzpatrick727de402010-07-07 16:06:39 -07002015 * Called from android_util_Binder.cpp's
2016 * android_os_Parcel_enforceInterface when an incoming Binder call
2017 * requires changing the StrictMode policy mask. The role of this
2018 * function is to ask Binder for its current (native) thread-local
2019 * policy value and synchronize it to libcore's (Java)
2020 * thread-local policy value.
2021 */
2022 private static void onBinderStrictModePolicyChange(int newPolicy) {
2023 setBlockGuardPolicy(newPolicy);
2024 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002025
2026 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002027 * A tracked, critical time span. (e.g. during an animation.)
2028 *
2029 * The object itself is a linked list node, to avoid any allocations
2030 * during rapid span entries and exits.
2031 *
2032 * @hide
2033 */
2034 public static class Span {
2035 private String mName;
2036 private long mCreateMillis;
2037 private Span mNext;
2038 private Span mPrev; // not used when in freeList, only active
2039 private final ThreadSpanState mContainerState;
2040
2041 Span(ThreadSpanState threadState) {
2042 mContainerState = threadState;
2043 }
2044
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002045 // Empty constructor for the NO_OP_SPAN
2046 protected Span() {
2047 mContainerState = null;
2048 }
2049
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002050 /**
2051 * To be called when the critical span is complete (i.e. the
2052 * animation is done animating). This can be called on any
2053 * thread (even a different one from where the animation was
2054 * taking place), but that's only a defensive implementation
2055 * measure. It really makes no sense for you to call this on
2056 * thread other than that where you created it.
2057 *
2058 * @hide
2059 */
2060 public void finish() {
2061 ThreadSpanState state = mContainerState;
2062 synchronized (state) {
2063 if (mName == null) {
2064 // Duplicate finish call. Ignore.
2065 return;
2066 }
2067
2068 // Remove ourselves from the active list.
2069 if (mPrev != null) {
2070 mPrev.mNext = mNext;
2071 }
2072 if (mNext != null) {
2073 mNext.mPrev = mPrev;
2074 }
2075 if (state.mActiveHead == this) {
2076 state.mActiveHead = mNext;
2077 }
2078
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002079 state.mActiveSize--;
2080
2081 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
2082
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002083 this.mCreateMillis = -1;
2084 this.mName = null;
2085 this.mPrev = null;
2086 this.mNext = null;
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002087
2088 // Add ourselves to the freeList, if it's not already
2089 // too big.
2090 if (state.mFreeListSize < 5) {
2091 this.mNext = state.mFreeListHead;
2092 state.mFreeListHead = this;
2093 state.mFreeListSize++;
2094 }
2095 }
2096 }
2097 }
2098
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002099 // The no-op span that's used in user builds.
2100 private static final Span NO_OP_SPAN = new Span() {
2101 public void finish() {
2102 // Do nothing.
2103 }
2104 };
2105
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002106 /**
2107 * Linked lists of active spans and a freelist.
2108 *
2109 * Locking notes: there's one of these structures per thread and
2110 * all members of this structure (as well as the Span nodes under
2111 * it) are guarded by the ThreadSpanState object instance. While
2112 * in theory there'd be no locking required because it's all local
2113 * per-thread, the finish() method above is defensive against
2114 * people calling it on a different thread from where they created
2115 * the Span, hence the locking.
2116 */
2117 private static class ThreadSpanState {
2118 public Span mActiveHead; // doubly-linked list.
2119 public int mActiveSize;
2120 public Span mFreeListHead; // singly-linked list. only changes at head.
2121 public int mFreeListSize;
2122 }
2123
2124 private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
2125 new ThreadLocal<ThreadSpanState>() {
2126 @Override protected ThreadSpanState initialValue() {
2127 return new ThreadSpanState();
2128 }
2129 };
2130
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08002131 private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
2132 protected IWindowManager create() {
2133 return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
2134 }
2135 };
2136
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002137 /**
2138 * Enter a named critical span (e.g. an animation)
2139 *
2140 * <p>The name is an arbitary label (or tag) that will be applied
2141 * to any strictmode violation that happens while this span is
2142 * active. You must call finish() on the span when done.
2143 *
2144 * <p>This will never return null, but on devices without debugging
2145 * enabled, this may return a dummy object on which the finish()
2146 * method is a no-op.
2147 *
2148 * <p>TODO: add CloseGuard to this, verifying callers call finish.
2149 *
2150 * @hide
2151 */
2152 public static Span enterCriticalSpan(String name) {
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002153 if (IS_USER_BUILD) {
2154 return NO_OP_SPAN;
2155 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002156 if (name == null || name.isEmpty()) {
2157 throw new IllegalArgumentException("name must be non-null and non-empty");
2158 }
2159 ThreadSpanState state = sThisThreadSpanState.get();
2160 Span span = null;
2161 synchronized (state) {
2162 if (state.mFreeListHead != null) {
2163 span = state.mFreeListHead;
2164 state.mFreeListHead = span.mNext;
2165 state.mFreeListSize--;
2166 } else {
2167 // Shouldn't have to do this often.
2168 span = new Span(state);
2169 }
2170 span.mName = name;
2171 span.mCreateMillis = SystemClock.uptimeMillis();
2172 span.mNext = state.mActiveHead;
2173 span.mPrev = null;
2174 state.mActiveHead = span;
2175 state.mActiveSize++;
2176 if (span.mNext != null) {
2177 span.mNext.mPrev = span;
2178 }
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002179 if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002180 }
2181 return span;
2182 }
2183
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002184 /**
2185 * For code to note that it's slow. This is a no-op unless the
2186 * current thread's {@link android.os.StrictMode.ThreadPolicy} has
2187 * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls}
2188 * enabled.
2189 *
2190 * @param name a short string for the exception stack trace that's
2191 * built if when this fires.
2192 */
2193 public static void noteSlowCall(String name) {
2194 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2195 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2196 // StrictMode not enabled.
2197 return;
2198 }
2199 ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
2200 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002201
2202 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -08002203 * For code to note that a resource was obtained using a type other than
2204 * its defined type. This is a no-op unless the current thread's
2205 * {@link android.os.StrictMode.ThreadPolicy} has
2206 * {@link android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()}
2207 * enabled.
2208 *
2209 * @param tag an object for the exception stack trace that's
2210 * built if when this fires.
2211 * @hide
2212 */
2213 public static void noteResourceMismatch(Object tag) {
2214 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2215 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2216 // StrictMode not enabled.
2217 return;
2218 }
2219 ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag);
2220 }
2221
2222 /**
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002223 * @hide
2224 */
Shubham Ajmerac95b2c82016-09-29 16:35:36 +01002225 public static void noteUnbufferedIO() {
2226 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2227 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2228 // StrictMode not enabled.
2229 return;
2230 }
2231 ((AndroidBlockGuardPolicy) policy).onUnbufferedIO();
2232 }
2233
2234 /**
2235 * @hide
2236 */
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002237 public static void noteDiskRead() {
2238 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002239 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2240 // StrictMode not enabled.
2241 return;
2242 }
2243 ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
2244 }
2245
2246 /**
2247 * @hide
2248 */
2249 public static void noteDiskWrite() {
2250 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2251 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2252 // StrictMode not enabled.
2253 return;
2254 }
2255 ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
2256 }
2257
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002258 // Guarded by StrictMode.class
2259 private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
2260 new HashMap<Class, Integer>();
2261
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002262 /**
Jeff Brown7e442832011-06-10 18:00:16 -07002263 * Returns an object that is used to track instances of activites.
2264 * The activity should store a reference to the tracker object in one of its fields.
2265 * @hide
2266 */
2267 public static Object trackActivity(Object instance) {
2268 return new InstanceTracker(instance);
2269 }
2270
2271 /**
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002272 * @hide
2273 */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002274 public static void incrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002275 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002276 return;
2277 }
Jeff Brown7e442832011-06-10 18:00:16 -07002278
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002279 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002280 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2281 return;
2282 }
2283
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002284 Integer expected = sExpectedActivityInstanceCount.get(klass);
2285 Integer newExpected = expected == null ? 1 : expected + 1;
2286 sExpectedActivityInstanceCount.put(klass, newExpected);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002287 }
2288 }
2289
2290 /**
2291 * @hide
2292 */
2293 public static void decrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002294 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002295 return;
2296 }
Jeff Brown7e442832011-06-10 18:00:16 -07002297
2298 final int limit;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002299 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002300 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2301 return;
2302 }
2303
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002304 Integer expected = sExpectedActivityInstanceCount.get(klass);
Jeff Brown7e442832011-06-10 18:00:16 -07002305 int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002306 if (newExpected == 0) {
2307 sExpectedActivityInstanceCount.remove(klass);
2308 } else {
2309 sExpectedActivityInstanceCount.put(klass, newExpected);
2310 }
Jeff Brown7e442832011-06-10 18:00:16 -07002311
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002312 // Note: adding 1 here to give some breathing room during
2313 // orientation changes. (shouldn't be necessary, though?)
Jeff Brown7e442832011-06-10 18:00:16 -07002314 limit = newExpected + 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002315 }
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002316
Jeff Brown7e442832011-06-10 18:00:16 -07002317 // Quick check.
2318 int actual = InstanceTracker.getInstanceCount(klass);
2319 if (actual <= limit) {
2320 return;
2321 }
2322
2323 // Do a GC and explicit count to double-check.
2324 // This is the work that we are trying to avoid by tracking the object instances
2325 // explicity. Running an explicit GC can be expensive (80ms) and so can walking
2326 // the heap to count instance (30ms). This extra work can make the system feel
2327 // noticeably less responsive during orientation changes when activities are
2328 // being restarted. Granted, it is only a problem when StrictMode is enabled
2329 // but it is annoying.
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08002330
2331 System.gc();
2332 System.runFinalization();
2333 System.gc();
Jeff Brown7e442832011-06-10 18:00:16 -07002334
2335 long instances = VMDebug.countInstancesOfClass(klass, false);
2336 if (instances > limit) {
2337 Throwable tr = new InstanceCountViolation(klass, instances, limit);
2338 onVmPolicyViolation(tr.getMessage(), tr);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002339 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002340 }
2341
2342 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002343 * Parcelable that gets sent in Binder call headers back to callers
2344 * to report violations that happened during a cross-process call.
2345 *
2346 * @hide
2347 */
2348 public static class ViolationInfo {
Jeff Sharkey20db11c2016-12-06 16:47:00 -07002349 public final String message;
Jeff Sharkey605eb792014-11-04 13:34:06 -08002350
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002351 /**
2352 * Stack and other stuff info.
2353 */
2354 public final ApplicationErrorReport.CrashInfo crashInfo;
2355
2356 /**
2357 * The strict mode policy mask at the time of violation.
2358 */
2359 public final int policy;
2360
2361 /**
2362 * The wall time duration of the violation, when known. -1 when
2363 * not known.
2364 */
2365 public int durationMillis = -1;
2366
2367 /**
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002368 * The number of animations currently running.
2369 */
2370 public int numAnimationsRunning = 0;
2371
2372 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002373 * List of tags from active Span instances during this
2374 * violation, or null for none.
2375 */
2376 public String[] tags;
2377
2378 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002379 * Which violation number this was (1-based) since the last Looper loop,
2380 * from the perspective of the root caller (if it crossed any processes
2381 * via Binder calls). The value is 0 if the root caller wasn't on a Looper
2382 * thread.
2383 */
2384 public int violationNumThisLoop;
2385
2386 /**
2387 * The time (in terms of SystemClock.uptimeMillis()) that the
2388 * violation occurred.
2389 */
2390 public long violationUptimeMillis;
2391
2392 /**
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002393 * The action of the Intent being broadcast to somebody's onReceive
2394 * on this thread right now, or null.
2395 */
2396 public String broadcastIntentAction;
2397
2398 /**
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002399 * If this is a instance count violation, the number of instances in memory,
2400 * else -1.
2401 */
2402 public long numInstances = -1;
2403
2404 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002405 * Create an uninitialized instance of ViolationInfo
2406 */
2407 public ViolationInfo() {
Jeff Sharkey20db11c2016-12-06 16:47:00 -07002408 message = null;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002409 crashInfo = null;
2410 policy = 0;
2411 }
2412
Jeff Sharkey605eb792014-11-04 13:34:06 -08002413 public ViolationInfo(Throwable tr, int policy) {
2414 this(null, tr, policy);
2415 }
2416
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002417 /**
2418 * Create an instance of ViolationInfo initialized from an exception.
2419 */
Jeff Sharkey605eb792014-11-04 13:34:06 -08002420 public ViolationInfo(String message, Throwable tr, int policy) {
2421 this.message = message;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002422 crashInfo = new ApplicationErrorReport.CrashInfo(tr);
2423 violationUptimeMillis = SystemClock.uptimeMillis();
2424 this.policy = policy;
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002425 this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002426 Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2427 if (broadcastIntent != null) {
2428 broadcastIntentAction = broadcastIntent.getAction();
2429 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002430 ThreadSpanState state = sThisThreadSpanState.get();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002431 if (tr instanceof InstanceCountViolation) {
2432 this.numInstances = ((InstanceCountViolation) tr).mInstances;
2433 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002434 synchronized (state) {
2435 int spanActiveCount = state.mActiveSize;
2436 if (spanActiveCount > MAX_SPAN_TAGS) {
2437 spanActiveCount = MAX_SPAN_TAGS;
2438 }
2439 if (spanActiveCount != 0) {
2440 this.tags = new String[spanActiveCount];
2441 Span iter = state.mActiveHead;
2442 int index = 0;
2443 while (iter != null && index < spanActiveCount) {
2444 this.tags[index] = iter.mName;
2445 index++;
2446 iter = iter.mNext;
2447 }
2448 }
2449 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002450 }
2451
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002452 @Override
2453 public int hashCode() {
2454 int result = 17;
Jeff Sharkey20db11c2016-12-06 16:47:00 -07002455 if (crashInfo != null) {
2456 result = 37 * result + crashInfo.stackTrace.hashCode();
2457 }
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002458 if (numAnimationsRunning != 0) {
2459 result *= 37;
2460 }
2461 if (broadcastIntentAction != null) {
2462 result = 37 * result + broadcastIntentAction.hashCode();
2463 }
2464 if (tags != null) {
2465 for (String tag : tags) {
2466 result = 37 * result + tag.hashCode();
2467 }
2468 }
2469 return result;
2470 }
2471
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002472 /**
2473 * Create an instance of ViolationInfo initialized from a Parcel.
2474 */
2475 public ViolationInfo(Parcel in) {
2476 this(in, false);
2477 }
2478
2479 /**
2480 * Create an instance of ViolationInfo initialized from a Parcel.
2481 *
2482 * @param unsetGatheringBit if true, the caller is the root caller
2483 * and the gathering penalty should be removed.
2484 */
2485 public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
Jeff Sharkey605eb792014-11-04 13:34:06 -08002486 message = in.readString();
Jeff Sharkey20db11c2016-12-06 16:47:00 -07002487 if (in.readInt() != 0) {
2488 crashInfo = new ApplicationErrorReport.CrashInfo(in);
2489 } else {
2490 crashInfo = null;
2491 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002492 int rawPolicy = in.readInt();
2493 if (unsetGatheringBit) {
2494 policy = rawPolicy & ~PENALTY_GATHER;
2495 } else {
2496 policy = rawPolicy;
2497 }
2498 durationMillis = in.readInt();
2499 violationNumThisLoop = in.readInt();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002500 numAnimationsRunning = in.readInt();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002501 violationUptimeMillis = in.readLong();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002502 numInstances = in.readLong();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002503 broadcastIntentAction = in.readString();
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002504 tags = in.readStringArray();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002505 }
2506
2507 /**
2508 * Save a ViolationInfo instance to a parcel.
2509 */
2510 public void writeToParcel(Parcel dest, int flags) {
Jeff Sharkey605eb792014-11-04 13:34:06 -08002511 dest.writeString(message);
Jeff Sharkey20db11c2016-12-06 16:47:00 -07002512 if (crashInfo != null) {
2513 dest.writeInt(1);
2514 crashInfo.writeToParcel(dest, flags);
2515 } else {
2516 dest.writeInt(0);
2517 }
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002518 int start = dest.dataPosition();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002519 dest.writeInt(policy);
2520 dest.writeInt(durationMillis);
2521 dest.writeInt(violationNumThisLoop);
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002522 dest.writeInt(numAnimationsRunning);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002523 dest.writeLong(violationUptimeMillis);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002524 dest.writeLong(numInstances);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002525 dest.writeString(broadcastIntentAction);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002526 dest.writeStringArray(tags);
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002527 int total = dest.dataPosition()-start;
Dianne Hackbornce92b0d2014-09-30 11:28:18 -07002528 if (total > 10*1024) {
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002529 Slog.d(TAG, "VIO: policy=" + policy + " dur=" + durationMillis
2530 + " numLoop=" + violationNumThisLoop
2531 + " anim=" + numAnimationsRunning
2532 + " uptime=" + violationUptimeMillis
2533 + " numInst=" + numInstances);
2534 Slog.d(TAG, "VIO: action=" + broadcastIntentAction);
2535 Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags));
2536 Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition()-start));
2537 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002538 }
2539
2540
2541 /**
2542 * Dump a ViolationInfo instance to a Printer.
2543 */
2544 public void dump(Printer pw, String prefix) {
Jeff Sharkey20db11c2016-12-06 16:47:00 -07002545 if (crashInfo != null) {
2546 crashInfo.dump(pw, prefix);
2547 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002548 pw.println(prefix + "policy: " + policy);
2549 if (durationMillis != -1) {
2550 pw.println(prefix + "durationMillis: " + durationMillis);
2551 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002552 if (numInstances != -1) {
2553 pw.println(prefix + "numInstances: " + numInstances);
2554 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002555 if (violationNumThisLoop != 0) {
2556 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2557 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002558 if (numAnimationsRunning != 0) {
2559 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2560 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002561 pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002562 if (broadcastIntentAction != null) {
2563 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2564 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002565 if (tags != null) {
2566 int index = 0;
2567 for (String tag : tags) {
2568 pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2569 }
2570 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002571 }
2572
2573 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002574
2575 // Dummy throwable, for now, since we don't know when or where the
2576 // leaked instances came from. We might in the future, but for
2577 // now we suppress the stack trace because it's useless and/or
2578 // misleading.
2579 private static class InstanceCountViolation extends Throwable {
2580 final Class mClass;
2581 final long mInstances;
2582 final int mLimit;
2583
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002584 private static final StackTraceElement[] FAKE_STACK = {
2585 new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
2586 "StrictMode.java", 1)
2587 };
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002588
2589 public InstanceCountViolation(Class klass, long instances, int limit) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002590 super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002591 setStackTrace(FAKE_STACK);
2592 mClass = klass;
2593 mInstances = instances;
2594 mLimit = limit;
2595 }
2596 }
Jeff Brown7e442832011-06-10 18:00:16 -07002597
2598 private static final class InstanceTracker {
2599 private static final HashMap<Class<?>, Integer> sInstanceCounts =
2600 new HashMap<Class<?>, Integer>();
2601
2602 private final Class<?> mKlass;
2603
2604 public InstanceTracker(Object instance) {
2605 mKlass = instance.getClass();
2606
2607 synchronized (sInstanceCounts) {
2608 final Integer value = sInstanceCounts.get(mKlass);
2609 final int newValue = value != null ? value + 1 : 1;
2610 sInstanceCounts.put(mKlass, newValue);
2611 }
2612 }
2613
2614 @Override
2615 protected void finalize() throws Throwable {
2616 try {
2617 synchronized (sInstanceCounts) {
2618 final Integer value = sInstanceCounts.get(mKlass);
2619 if (value != null) {
2620 final int newValue = value - 1;
2621 if (newValue > 0) {
2622 sInstanceCounts.put(mKlass, newValue);
2623 } else {
2624 sInstanceCounts.remove(mKlass);
2625 }
2626 }
2627 }
2628 } finally {
2629 super.finalize();
2630 }
2631 }
2632
2633 public static int getInstanceCount(Class<?> klass) {
2634 synchronized (sInstanceCounts) {
2635 final Integer value = sInstanceCounts.get(klass);
2636 return value != null ? value : 0;
2637 }
2638 }
2639 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07002640}