blob: ea71ad8c05635d2241ec7ff63fc9c5d7b168a492 [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;
Dianne Hackborn390517b2013-05-30 15:03:32 -070027import android.util.ArrayMap;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070028import android.util.Log;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070029import android.util.Printer;
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -080030import android.util.Singleton;
Brad Fitzpatrick68044332010-11-22 18:19:48 -080031import android.view.IWindowManager;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070032
33import com.android.internal.os.RuntimeInit;
34
Dianne Hackborn8c841092013-06-24 13:46:13 -070035import com.android.internal.util.FastPrintWriter;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070036import dalvik.system.BlockGuard;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070037import dalvik.system.CloseGuard;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -080038import dalvik.system.VMDebug;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070039
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070040import java.io.PrintWriter;
41import java.io.StringWriter;
42import java.util.ArrayList;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070043import java.util.HashMap;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -080044import java.util.Map;
Brad Fitzpatrickbee24872010-11-20 12:09:10 -080045import java.util.concurrent.atomic.AtomicInteger;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070046
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070047/**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070048 * <p>StrictMode is a developer tool which detects things you might be
49 * doing by accident and brings them to your attention so you can fix
50 * them.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070051 *
52 * <p>StrictMode is most commonly used to catch accidental disk or
53 * network access on the application's main thread, where UI
54 * operations are received and animations take place. Keeping disk
55 * and network operations off the main thread makes for much smoother,
Brad Fitzpatrick9fc2fc52010-10-11 12:52:35 -070056 * more responsive applications. By keeping your application's main thread
57 * responsive, you also prevent
58 * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
59 * from being shown to users.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070060 *
61 * <p class="note">Note that even though an Android device's disk is
62 * often on flash memory, many devices run a filesystem on top of that
63 * memory with very limited concurrency. It's often the case that
64 * almost all disk accesses are fast, but may in individual cases be
65 * dramatically slower when certain I/O is happening in the background
66 * from other processes. If possible, it's best to assume that such
67 * things are not fast.</p>
68 *
69 * <p>Example code to enable from early in your
70 * {@link android.app.Application}, {@link android.app.Activity}, or
71 * other application component's
72 * {@link android.app.Application#onCreate} method:
73 *
74 * <pre>
75 * public void onCreate() {
76 * if (DEVELOPER_MODE) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070077 * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
78 * .detectDiskReads()
79 * .detectDiskWrites()
80 * .detectNetwork() // or .detectAll() for all detectable problems
81 * .penaltyLog()
82 * .build());
83 * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -070084 * .detectLeakedSqlLiteObjects()
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070085 * .detectLeakedClosableObjects()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070086 * .penaltyLog()
87 * .penaltyDeath()
88 * .build());
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070089 * }
90 * super.onCreate();
91 * }
92 * </pre>
93 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070094 * <p>You can decide what should happen when a violation is detected.
95 * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can
96 * watch the output of <code>adb logcat</code> while you use your
97 * application to see the violations as they happen.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070098 *
99 * <p>If you find violations that you feel are problematic, there are
100 * a variety of tools to help solve them: threads, {@link android.os.Handler},
101 * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
102 * But don't feel compelled to fix everything that StrictMode finds. In particular,
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700103 * many cases of disk access are often necessary during the normal activity lifecycle. Use
104 * StrictMode to find things you did by accident. Network requests on the UI thread
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700105 * are almost always a problem, though.
106 *
107 * <p class="note">StrictMode is not a security mechanism and is not
108 * guaranteed to find all disk or network accesses. While it does
109 * propagate its state across process boundaries when doing
110 * {@link android.os.Binder} calls, it's still ultimately a best
111 * effort mechanism. Notably, disk or network access from JNI calls
112 * won't necessarily trigger it. Future versions of Android may catch
113 * more (or fewer) operations, so you should never leave StrictMode
Dirk Dougherty4d7bc6552012-01-27 17:56:49 -0800114 * enabled in applications distributed on Google Play.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700115 */
116public final class StrictMode {
117 private static final String TAG = "StrictMode";
Brad Fitzpatrick82829ef2010-11-18 18:25:08 -0800118 private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700119
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -0800120 private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800121 private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE);
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -0800122
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800123 /**
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700124 * Boolean system property to disable strict mode checks outright.
125 * Set this to 'true' to force disable; 'false' has no effect on other
126 * enable/disable policy.
127 * @hide
128 */
129 public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
130
131 /**
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800132 * The boolean system property to control screen flashes on violations.
133 *
134 * @hide
135 */
136 public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
137
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700138 // Only log a duplicate stack trace to the logs every second.
139 private static final long MIN_LOG_INTERVAL_MS = 1000;
140
141 // Only show an annoying dialog at most every 30 seconds
142 private static final long MIN_DIALOG_INTERVAL_MS = 30000;
143
Brad Fitzpatricke7520d82010-11-10 18:08:36 -0800144 // How many Span tags (e.g. animations) to report.
145 private static final int MAX_SPAN_TAGS = 20;
146
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -0700147 // How many offending stacks to keep track of (and time) per loop
148 // of the Looper.
149 private static final int MAX_OFFENSES_PER_LOOP = 10;
150
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700151 // Thread-policy:
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700152
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700153 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700154 * @hide
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700155 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700156 public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700157
158 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700159 * @hide
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700160 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700161 public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700162
163 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700164 * @hide
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700165 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700166 public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700167
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800168 /**
169 * For StrictMode.noteSlowCall()
170 *
171 * @hide
172 */
173 public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy
174
175 private static final int ALL_THREAD_DETECT_BITS =
176 DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM;
177
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700178 // Process-policy:
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700179
180 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700181 * Note, a "VM_" bit, not thread.
182 * @hide
183 */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800184 public static final int DETECT_VM_CURSOR_LEAKS = 0x200; // for VmPolicy
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700185
186 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700187 * Note, a "VM_" bit, not thread.
188 * @hide
189 */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800190 public static final int DETECT_VM_CLOSABLE_LEAKS = 0x400; // for VmPolicy
191
192 /**
193 * Note, a "VM_" bit, not thread.
194 * @hide
195 */
196 public static final int DETECT_VM_ACTIVITY_LEAKS = 0x800; // for VmPolicy
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700197
198 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700199 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700200 */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800201 private static final int DETECT_VM_INSTANCE_LEAKS = 0x1000; // for VmPolicy
202
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800203 /**
204 * @hide
205 */
206 public static final int DETECT_VM_REGISTRATION_LEAKS = 0x2000; // for VmPolicy
207
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700208 /**
209 * @hide
210 */
211 private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x4000; // for VmPolicy
212
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800213 private static final int ALL_VM_DETECT_BITS =
214 DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800215 DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700216 DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800217
218 /**
219 * @hide
220 */
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700221 public static final int PENALTY_LOG = 0x10; // normal android.util.Log
222
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700223 // Used for both process and thread policy:
224
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700225 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700226 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700227 */
228 public static final int PENALTY_DIALOG = 0x20;
229
230 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700231 * Death on any detected violation.
232 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700233 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700234 */
235 public static final int PENALTY_DEATH = 0x40;
236
237 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700238 * Death just for detected network usage.
239 *
240 * @hide
241 */
242 public static final int PENALTY_DEATH_ON_NETWORK = 0x200;
243
244 /**
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800245 * Flash the screen during violations.
246 *
247 * @hide
248 */
249 public static final int PENALTY_FLASH = 0x800;
250
251 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700252 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700253 */
254 public static final int PENALTY_DROPBOX = 0x80;
255
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700256 /**
257 * Non-public penalty mode which overrides all the other penalty
258 * bits and signals that we're in a Binder call and we should
259 * ignore the other penalty bits and instead serialize back all
260 * our offending stack traces to the caller to ultimately handle
261 * in the originating process.
262 *
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700263 * This must be kept in sync with the constant in libs/binder/Parcel.cpp
264 *
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700265 * @hide
266 */
267 public static final int PENALTY_GATHER = 0x100;
268
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700269 /**
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800270 * Mask of all the penalty bits valid for thread policies.
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700271 */
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800272 private static final int THREAD_PENALTY_MASK =
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700273 PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800274 PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700275
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800276
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800277 /**
278 * Mask of all the penalty bits valid for VM policies.
279 */
280 private static final int VM_PENALTY_MASK =
281 PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX;
282
283
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800284 // TODO: wrap in some ImmutableHashMap thing.
285 // Note: must be before static initialization of sVmPolicy.
286 private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP = new HashMap<Class, Integer>();
287
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700288 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700289 * The current VmPolicy in effect.
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800290 *
291 * TODO: these are redundant (mask is in VmPolicy). Should remove sVmPolicyMask.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700292 */
293 private static volatile int sVmPolicyMask = 0;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800294 private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700295
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800296 /**
297 * The number of threads trying to do an async dropbox write.
298 * Just to limit ourselves out of paranoia.
299 */
300 private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
301
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700302 private StrictMode() {}
303
304 /**
305 * {@link StrictMode} policy applied to a certain thread.
306 *
307 * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy
308 * can be retrieved with {@link #getThreadPolicy}.
309 *
310 * <p>Note that multiple penalties may be provided and they're run
311 * in order from least to most severe (logging before process
312 * death, for example). There's currently no mechanism to choose
313 * different penalties for different detected actions.
314 */
315 public static final class ThreadPolicy {
316 /**
317 * The default, lax policy which doesn't catch anything.
318 */
319 public static final ThreadPolicy LAX = new ThreadPolicy(0);
320
321 final int mask;
322
323 private ThreadPolicy(int mask) {
324 this.mask = mask;
325 }
326
327 @Override
328 public String toString() {
329 return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
330 }
331
332 /**
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800333 * Creates {@link ThreadPolicy} instances. Methods whose names start
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700334 * with {@code detect} specify what problems we should look
335 * for. Methods whose names start with {@code penalty} specify what
336 * we should do when we detect a problem.
337 *
338 * <p>You can call as many {@code detect} and {@code penalty}
339 * methods as you like. Currently order is insignificant: all
340 * penalties apply to all detected problems.
341 *
342 * <p>For example, detect everything and log anything that's found:
343 * <pre>
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800344 * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700345 * .detectAll()
346 * .penaltyLog()
347 * .build();
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800348 * StrictMode.setThreadPolicy(policy);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700349 * </pre>
350 */
351 public static final class Builder {
352 private int mMask = 0;
353
354 /**
355 * Create a Builder that detects nothing and has no
356 * violations. (but note that {@link #build} will default
357 * to enabling {@link #penaltyLog} if no other penalties
358 * are specified)
359 */
360 public Builder() {
361 mMask = 0;
362 }
363
364 /**
365 * Initialize a Builder from an existing ThreadPolicy.
366 */
367 public Builder(ThreadPolicy policy) {
368 mMask = policy.mask;
369 }
370
371 /**
372 * Detect everything that's potentially suspect.
373 *
374 * <p>As of the Gingerbread release this includes network and
375 * disk operations but will likely expand in future releases.
376 */
377 public Builder detectAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800378 return enable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700379 }
380
381 /**
382 * Disable the detection of everything.
383 */
384 public Builder permitAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800385 return disable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700386 }
387
388 /**
389 * Enable detection of network operations.
390 */
391 public Builder detectNetwork() {
392 return enable(DETECT_NETWORK);
393 }
394
395 /**
396 * Disable detection of network operations.
397 */
398 public Builder permitNetwork() {
399 return disable(DETECT_NETWORK);
400 }
401
402 /**
403 * Enable detection of disk reads.
404 */
405 public Builder detectDiskReads() {
406 return enable(DETECT_DISK_READ);
407 }
408
409 /**
410 * Disable detection of disk reads.
411 */
412 public Builder permitDiskReads() {
413 return disable(DETECT_DISK_READ);
414 }
415
416 /**
Qi Wang097fbf22012-07-13 09:26:03 +0800417 * Enable detection of slow calls.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800418 */
419 public Builder detectCustomSlowCalls() {
420 return enable(DETECT_CUSTOM);
421 }
422
423 /**
Qi Wang097fbf22012-07-13 09:26:03 +0800424 * Disable detection of slow calls.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800425 */
426 public Builder permitCustomSlowCalls() {
Qi Wang097fbf22012-07-13 09:26:03 +0800427 return disable(DETECT_CUSTOM);
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800428 }
429
430 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700431 * Enable detection of disk writes.
432 */
433 public Builder detectDiskWrites() {
434 return enable(DETECT_DISK_WRITE);
435 }
436
437 /**
438 * Disable detection of disk writes.
439 */
440 public Builder permitDiskWrites() {
441 return disable(DETECT_DISK_WRITE);
442 }
443
444 /**
445 * Show an annoying dialog to the developer on detected
446 * violations, rate-limited to be only a little annoying.
447 */
448 public Builder penaltyDialog() {
449 return enable(PENALTY_DIALOG);
450 }
451
452 /**
453 * Crash the whole process on violation. This penalty runs at
454 * the end of all enabled penalties so you'll still get
455 * see logging or other violations before the process dies.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700456 *
457 * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies
458 * to disk reads, disk writes, and network usage if their
459 * corresponding detect flags are set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700460 */
461 public Builder penaltyDeath() {
462 return enable(PENALTY_DEATH);
463 }
464
465 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700466 * Crash the whole process on any network usage. Unlike
467 * {@link #penaltyDeath}, this penalty runs
468 * <em>before</em> anything else. You must still have
469 * called {@link #detectNetwork} to enable this.
470 *
471 * <p>In the Honeycomb or later SDKs, this is on by default.
472 */
473 public Builder penaltyDeathOnNetwork() {
474 return enable(PENALTY_DEATH_ON_NETWORK);
475 }
476
477 /**
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800478 * Flash the screen during a violation.
479 */
480 public Builder penaltyFlashScreen() {
481 return enable(PENALTY_FLASH);
482 }
483
484 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700485 * Log detected violations to the system log.
486 */
487 public Builder penaltyLog() {
488 return enable(PENALTY_LOG);
489 }
490
491 /**
492 * Enable detected violations log a stacktrace and timing data
493 * to the {@link android.os.DropBoxManager DropBox} on policy
494 * violation. Intended mostly for platform integrators doing
495 * beta user field data collection.
496 */
497 public Builder penaltyDropBox() {
498 return enable(PENALTY_DROPBOX);
499 }
500
501 private Builder enable(int bit) {
502 mMask |= bit;
503 return this;
504 }
505
506 private Builder disable(int bit) {
507 mMask &= ~bit;
508 return this;
509 }
510
511 /**
512 * Construct the ThreadPolicy instance.
513 *
514 * <p>Note: if no penalties are enabled before calling
515 * <code>build</code>, {@link #penaltyLog} is implicitly
516 * set.
517 */
518 public ThreadPolicy build() {
519 // If there are detection bits set but no violation bits
520 // set, enable simple logging.
521 if (mMask != 0 &&
522 (mMask & (PENALTY_DEATH | PENALTY_LOG |
523 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
524 penaltyLog();
525 }
526 return new ThreadPolicy(mMask);
527 }
528 }
529 }
530
531 /**
532 * {@link StrictMode} policy applied to all threads in the virtual machine's process.
533 *
534 * <p>The policy is enabled by {@link #setVmPolicy}.
535 */
536 public static final class VmPolicy {
537 /**
538 * The default, lax policy which doesn't catch anything.
539 */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800540 public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700541
542 final int mask;
543
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800544 // Map from class to max number of allowed instances in memory.
545 final HashMap<Class, Integer> classInstanceLimit;
546
547 private VmPolicy(int mask, HashMap<Class, Integer> classInstanceLimit) {
548 if (classInstanceLimit == null) {
549 throw new NullPointerException("classInstanceLimit == null");
550 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700551 this.mask = mask;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800552 this.classInstanceLimit = classInstanceLimit;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700553 }
554
555 @Override
556 public String toString() {
557 return "[StrictMode.VmPolicy; mask=" + mask + "]";
558 }
559
560 /**
561 * Creates {@link VmPolicy} instances. Methods whose names start
562 * with {@code detect} specify what problems we should look
563 * for. Methods whose names start with {@code penalty} specify what
564 * we should do when we detect a problem.
565 *
566 * <p>You can call as many {@code detect} and {@code penalty}
567 * methods as you like. Currently order is insignificant: all
568 * penalties apply to all detected problems.
569 *
570 * <p>For example, detect everything and log anything that's found:
571 * <pre>
572 * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
573 * .detectAll()
574 * .penaltyLog()
575 * .build();
576 * StrictMode.setVmPolicy(policy);
577 * </pre>
578 */
579 public static final class Builder {
580 private int mMask;
581
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800582 private HashMap<Class, Integer> mClassInstanceLimit; // null until needed
583 private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write
584
585 public Builder() {
586 mMask = 0;
587 }
588
589 /**
590 * Build upon an existing VmPolicy.
591 */
592 public Builder(VmPolicy base) {
593 mMask = base.mask;
594 mClassInstanceLimitNeedCow = true;
595 mClassInstanceLimit = base.classInstanceLimit;
596 }
597
598 /**
599 * Set an upper bound on how many instances of a class can be in memory
600 * at once. Helps to prevent object leaks.
601 */
602 public Builder setClassInstanceLimit(Class klass, int instanceLimit) {
603 if (klass == null) {
604 throw new NullPointerException("klass == null");
605 }
606 if (mClassInstanceLimitNeedCow) {
607 if (mClassInstanceLimit.containsKey(klass) &&
608 mClassInstanceLimit.get(klass) == instanceLimit) {
609 // no-op; don't break COW
610 return this;
611 }
612 mClassInstanceLimitNeedCow = false;
613 mClassInstanceLimit = (HashMap<Class, Integer>) mClassInstanceLimit.clone();
614 } else if (mClassInstanceLimit == null) {
615 mClassInstanceLimit = new HashMap<Class, Integer>();
616 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800617 mMask |= DETECT_VM_INSTANCE_LEAKS;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800618 mClassInstanceLimit.put(klass, instanceLimit);
619 return this;
620 }
621
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800622 /**
623 * Detect leaks of {@link android.app.Activity} subclasses.
624 */
625 public Builder detectActivityLeaks() {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800626 return enable(DETECT_VM_ACTIVITY_LEAKS);
627 }
628
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700629 /**
630 * Detect everything that's potentially suspect.
631 *
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700632 * <p>In the Honeycomb release this includes leaks of
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800633 * SQLite cursors, Activities, and other closable objects
634 * but will likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700635 */
636 public Builder detectAll() {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800637 return enable(DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700638 | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS
639 | DETECT_VM_FILE_URI_EXPOSURE);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700640 }
641
642 /**
643 * Detect when an
644 * {@link android.database.sqlite.SQLiteCursor} or other
645 * SQLite object is finalized without having been closed.
646 *
647 * <p>You always want to explicitly close your SQLite
648 * cursors to avoid unnecessary database contention and
649 * temporary memory leaks.
650 */
651 public Builder detectLeakedSqlLiteObjects() {
652 return enable(DETECT_VM_CURSOR_LEAKS);
653 }
654
655 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700656 * Detect when an {@link java.io.Closeable} or other
657 * object with a explict termination method is finalized
658 * without having been closed.
659 *
660 * <p>You always want to explicitly close such objects to
661 * avoid unnecessary resources leaks.
662 */
663 public Builder detectLeakedClosableObjects() {
664 return enable(DETECT_VM_CLOSABLE_LEAKS);
665 }
666
667 /**
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800668 * Detect when a {@link BroadcastReceiver} or
669 * {@link ServiceConnection} is leaked during {@link Context}
670 * teardown.
671 */
672 public Builder detectLeakedRegistrationObjects() {
673 return enable(DETECT_VM_REGISTRATION_LEAKS);
674 }
675
676 /**
Ying Wang0fa30372013-04-03 22:57:31 -0700677 * Detect when a {@code file://} {@link android.net.Uri} is exposed beyond this
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700678 * app. The receiving app may not have access to the sent path.
679 * Instead, when sharing files between apps, {@code content://}
680 * should be used with permission grants.
681 */
682 public Builder detectFileUriExposure() {
683 return enable(DETECT_VM_FILE_URI_EXPOSURE);
684 }
685
686 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700687 * Crashes the whole process on violation. This penalty runs at
688 * the end of all enabled penalties so yo you'll still get
689 * your logging or other violations before the process dies.
690 */
691 public Builder penaltyDeath() {
692 return enable(PENALTY_DEATH);
693 }
694
695 /**
696 * Log detected violations to the system log.
697 */
698 public Builder penaltyLog() {
699 return enable(PENALTY_LOG);
700 }
701
702 /**
703 * Enable detected violations log a stacktrace and timing data
704 * to the {@link android.os.DropBoxManager DropBox} on policy
705 * violation. Intended mostly for platform integrators doing
706 * beta user field data collection.
707 */
708 public Builder penaltyDropBox() {
709 return enable(PENALTY_DROPBOX);
710 }
711
712 private Builder enable(int bit) {
713 mMask |= bit;
714 return this;
715 }
716
717 /**
718 * Construct the VmPolicy instance.
719 *
720 * <p>Note: if no penalties are enabled before calling
721 * <code>build</code>, {@link #penaltyLog} is implicitly
722 * set.
723 */
724 public VmPolicy build() {
725 // If there are detection bits set but no violation bits
726 // set, enable simple logging.
727 if (mMask != 0 &&
728 (mMask & (PENALTY_DEATH | PENALTY_LOG |
729 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
730 penaltyLog();
731 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800732 return new VmPolicy(mMask,
733 mClassInstanceLimit != null ? mClassInstanceLimit : EMPTY_CLASS_LIMIT_MAP);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700734 }
735 }
736 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700737
738 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700739 * Log of strict mode violation stack traces that have occurred
740 * during a Binder call, to be serialized back later to the caller
741 * via Parcel.writeNoException() (amusingly) where the caller can
742 * choose how to react.
743 */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -0700744 private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
745 new ThreadLocal<ArrayList<ViolationInfo>>() {
746 @Override protected ArrayList<ViolationInfo> initialValue() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700747 // Starts null to avoid unnecessary allocations when
748 // checking whether there are any violations or not in
749 // hasGatheredViolations() below.
750 return null;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700751 }
752 };
753
754 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700755 * Sets the policy for what actions on the current thread should
756 * be detected, as well as the penalty if such actions occur.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700757 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700758 * <p>Internally this sets a thread-local variable which is
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700759 * propagated across cross-process IPC calls, meaning you can
760 * catch violations when a system service or another process
761 * accesses the disk or network on your behalf.
762 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700763 * @param policy the policy to put into place
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700764 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700765 public static void setThreadPolicy(final ThreadPolicy policy) {
766 setThreadPolicyMask(policy.mask);
767 }
768
769 private static void setThreadPolicyMask(final int policyMask) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700770 // In addition to the Java-level thread-local in Dalvik's
771 // BlockGuard, we also need to keep a native thread-local in
772 // Binder in order to propagate the value across Binder calls,
773 // even across native-only processes. The two are kept in
774 // sync via the callback to onStrictModePolicyChange, below.
775 setBlockGuardPolicy(policyMask);
776
777 // And set the Android native version...
778 Binder.setThreadStrictModePolicy(policyMask);
779 }
780
781 // Sets the policy in Dalvik/libcore (BlockGuard)
782 private static void setBlockGuardPolicy(final int policyMask) {
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700783 if (policyMask == 0) {
784 BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
785 return;
786 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -0700787 final BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
788 final AndroidBlockGuardPolicy androidPolicy;
789 if (policy instanceof AndroidBlockGuardPolicy) {
790 androidPolicy = (AndroidBlockGuardPolicy) policy;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700791 } else {
Jeff Sharkeya2934d52013-06-14 14:43:18 -0700792 androidPolicy = threadAndroidPolicy.get();
793 BlockGuard.setThreadPolicy(androidPolicy);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700794 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -0700795 androidPolicy.setPolicyMask(policyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700796 }
797
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -0800798 // Sets up CloseGuard in Dalvik/libcore
799 private static void setCloseGuardEnabled(boolean enabled) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -0800800 if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -0800801 CloseGuard.setReporter(new AndroidCloseGuardReporter());
802 }
803 CloseGuard.setEnabled(enabled);
804 }
805
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800806 /**
807 * @hide
808 */
809 public static class StrictModeViolation extends BlockGuard.BlockGuardPolicyException {
810 public StrictModeViolation(int policyState, int policyViolated, String message) {
811 super(policyState, policyViolated, message);
812 }
813 }
814
815 /**
816 * @hide
817 */
818 public static class StrictModeNetworkViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700819 public StrictModeNetworkViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800820 super(policyMask, DETECT_NETWORK, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700821 }
822 }
823
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800824 /**
825 * @hide
826 */
827 private static class StrictModeDiskReadViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700828 public StrictModeDiskReadViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800829 super(policyMask, DETECT_DISK_READ, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700830 }
831 }
832
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800833 /**
834 * @hide
835 */
836 private static class StrictModeDiskWriteViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700837 public StrictModeDiskWriteViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800838 super(policyMask, DETECT_DISK_WRITE, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700839 }
840 }
841
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800842 /**
843 * @hide
844 */
845 private static class StrictModeCustomViolation extends StrictModeViolation {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800846 public StrictModeCustomViolation(int policyMask, String name) {
847 super(policyMask, DETECT_CUSTOM, name);
848 }
849 }
850
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700851 /**
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700852 * Returns the bitmask of the current thread's policy.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700853 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700854 * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
855 *
856 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700857 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700858 public static int getThreadPolicyMask() {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700859 return BlockGuard.getThreadPolicy().getPolicyMask();
860 }
861
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700862 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700863 * Returns the current thread's policy.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700864 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700865 public static ThreadPolicy getThreadPolicy() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800866 // TODO: this was a last minute Gingerbread API change (to
867 // introduce VmPolicy cleanly) but this isn't particularly
868 // optimal for users who might call this method often. This
869 // should be in a thread-local and not allocate on each call.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700870 return new ThreadPolicy(getThreadPolicyMask());
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700871 }
872
873 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700874 * A convenience wrapper that takes the current
875 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
876 * to permit both disk reads &amp; writes, and sets the new policy
877 * with {@link #setThreadPolicy}, returning the old policy so you
878 * can restore it at the end of a block.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700879 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700880 * @return the old policy, to be passed to {@link #setThreadPolicy} to
881 * restore the policy at the end of a block
882 */
883 public static ThreadPolicy allowThreadDiskWrites() {
884 int oldPolicyMask = getThreadPolicyMask();
885 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
886 if (newPolicyMask != oldPolicyMask) {
887 setThreadPolicyMask(newPolicyMask);
888 }
889 return new ThreadPolicy(oldPolicyMask);
890 }
891
892 /**
893 * A convenience wrapper that takes the current
894 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
895 * to permit disk reads, and sets the new policy
896 * with {@link #setThreadPolicy}, returning the old policy so you
897 * can restore it at the end of a block.
898 *
899 * @return the old policy, to be passed to setThreadPolicy to
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700900 * restore the policy.
901 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700902 public static ThreadPolicy allowThreadDiskReads() {
903 int oldPolicyMask = getThreadPolicyMask();
904 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
905 if (newPolicyMask != oldPolicyMask) {
906 setThreadPolicyMask(newPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700907 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700908 return new ThreadPolicy(oldPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700909 }
910
Brad Fitzpatrickf5454592010-11-24 15:27:51 -0800911 // We don't want to flash the screen red in the system server
912 // process, nor do we want to modify all the call sites of
913 // conditionallyEnableDebugLogging() in the system server,
914 // so instead we use this to determine if we are the system server.
915 private static boolean amTheSystemServerProcess() {
916 // Fast path. Most apps don't have the system server's UID.
917 if (Process.myUid() != Process.SYSTEM_UID) {
918 return false;
919 }
920
921 // The settings app, though, has the system server's UID so
922 // look up our stack to see if we came from the system server.
923 Throwable stack = new Throwable();
924 stack.fillInStackTrace();
925 for (StackTraceElement ste : stack.getStackTrace()) {
926 String clsName = ste.getClassName();
927 if (clsName != null && clsName.startsWith("com.android.server.")) {
928 return true;
929 }
930 }
931 return false;
932 }
933
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700934 /**
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -0700935 * Enable DropBox logging for debug phone builds.
936 *
937 * @hide
938 */
939 public static boolean conditionallyEnableDebugLogging() {
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700940 boolean doFlashes = SystemProperties.getBoolean(VISUAL_PROPERTY, false)
941 && !amTheSystemServerProcess();
942 final boolean suppress = SystemProperties.getBoolean(DISABLE_PROPERTY, false);
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800943
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -0700944 // For debug builds, log event loop stalls to dropbox for analysis.
945 // Similar logic also appears in ActivityThread.java for system apps.
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700946 if (!doFlashes && (IS_USER_BUILD || suppress)) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -0800947 setCloseGuardEnabled(false);
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -0700948 return false;
949 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800950
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700951 // Eng builds have flashes on all the time. The suppression property
952 // overrides this, so we force the behavior only after the short-circuit
953 // check above.
954 if (IS_ENG_BUILD) {
955 doFlashes = true;
956 }
957
Jeff Brownbe7c29c2011-10-11 11:35:23 -0700958 // Thread policy controls BlockGuard.
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800959 int threadPolicyMask = StrictMode.DETECT_DISK_WRITE |
960 StrictMode.DETECT_DISK_READ |
961 StrictMode.DETECT_NETWORK;
962
963 if (!IS_USER_BUILD) {
964 threadPolicyMask |= StrictMode.PENALTY_DROPBOX;
965 }
966 if (doFlashes) {
967 threadPolicyMask |= StrictMode.PENALTY_FLASH;
968 }
969
970 StrictMode.setThreadPolicyMask(threadPolicyMask);
971
Jeff Brownbe7c29c2011-10-11 11:35:23 -0700972 // VM Policy controls CloseGuard, detection of Activity leaks,
973 // and instance counting.
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800974 if (IS_USER_BUILD) {
975 setCloseGuardEnabled(false);
976 } else {
Jeff Brownd5875d92011-10-09 14:59:37 -0700977 VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll().penaltyDropBox();
978 if (IS_ENG_BUILD) {
979 policyBuilder.penaltyLog();
980 }
981 setVmPolicy(policyBuilder.build());
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800982 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
983 }
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -0700984 return true;
985 }
986
987 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700988 * Used by the framework to make network usage on the main
989 * thread a fatal error.
990 *
991 * @hide
992 */
993 public static void enableDeathOnNetwork() {
994 int oldPolicy = getThreadPolicyMask();
995 int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
996 setThreadPolicyMask(newPolicy);
997 }
998
999 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001000 * Parses the BlockGuard policy mask out from the Exception's
1001 * getMessage() String value. Kinda gross, but least
1002 * invasive. :/
1003 *
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001004 * Input is of the following forms:
1005 * "policy=137 violation=64"
1006 * "policy=137 violation=64 msg=Arbitrary text"
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001007 *
1008 * Returns 0 on failure, which is a valid policy, but not a
1009 * valid policy during a violation (else there must've been
1010 * some policy in effect to violate).
1011 */
1012 private static int parsePolicyFromMessage(String message) {
1013 if (message == null || !message.startsWith("policy=")) {
1014 return 0;
1015 }
1016 int spaceIndex = message.indexOf(' ');
1017 if (spaceIndex == -1) {
1018 return 0;
1019 }
1020 String policyString = message.substring(7, spaceIndex);
1021 try {
1022 return Integer.valueOf(policyString).intValue();
1023 } catch (NumberFormatException e) {
1024 return 0;
1025 }
1026 }
1027
1028 /**
1029 * Like parsePolicyFromMessage(), but returns the violation.
1030 */
1031 private static int parseViolationFromMessage(String message) {
1032 if (message == null) {
1033 return 0;
1034 }
1035 int violationIndex = message.indexOf("violation=");
1036 if (violationIndex == -1) {
1037 return 0;
1038 }
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001039 int numberStartIndex = violationIndex + "violation=".length();
1040 int numberEndIndex = message.indexOf(' ', numberStartIndex);
1041 if (numberEndIndex == -1) {
1042 numberEndIndex = message.length();
1043 }
1044 String violationString = message.substring(numberStartIndex, numberEndIndex);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001045 try {
1046 return Integer.valueOf(violationString).intValue();
1047 } catch (NumberFormatException e) {
1048 return 0;
1049 }
1050 }
1051
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001052 private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
1053 new ThreadLocal<ArrayList<ViolationInfo>>() {
1054 @Override protected ArrayList<ViolationInfo> initialValue() {
1055 return new ArrayList<ViolationInfo>();
1056 }
1057 };
1058
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001059 // Note: only access this once verifying the thread has a Looper.
1060 private static final ThreadLocal<Handler> threadHandler = new ThreadLocal<Handler>() {
1061 @Override protected Handler initialValue() {
1062 return new Handler();
1063 }
1064 };
1065
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001066 private static final ThreadLocal<AndroidBlockGuardPolicy>
1067 threadAndroidPolicy = new ThreadLocal<AndroidBlockGuardPolicy>() {
1068 @Override
1069 protected AndroidBlockGuardPolicy initialValue() {
1070 return new AndroidBlockGuardPolicy(0);
1071 }
1072 };
1073
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001074 private static boolean tooManyViolationsThisLoop() {
1075 return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
1076 }
1077
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001078 private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
1079 private int mPolicyMask;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001080
1081 // Map from violation stacktrace hashcode -> uptimeMillis of
1082 // last violation. No locking needed, as this is only
1083 // accessed by the same thread.
Dianne Hackborn390517b2013-05-30 15:03:32 -07001084 private ArrayMap<Integer, Long> mLastViolationTime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001085
1086 public AndroidBlockGuardPolicy(final int policyMask) {
1087 mPolicyMask = policyMask;
1088 }
1089
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001090 @Override
1091 public String toString() {
1092 return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
1093 }
1094
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001095 // Part of BlockGuard.Policy interface:
1096 public int getPolicyMask() {
1097 return mPolicyMask;
1098 }
1099
1100 // Part of BlockGuard.Policy interface:
1101 public void onWriteToDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001102 if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001103 return;
1104 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001105 if (tooManyViolationsThisLoop()) {
1106 return;
1107 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001108 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
1109 e.fillInStackTrace();
1110 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001111 }
1112
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001113 // Not part of BlockGuard.Policy; just part of StrictMode:
1114 void onCustomSlowCall(String name) {
1115 if ((mPolicyMask & DETECT_CUSTOM) == 0) {
1116 return;
1117 }
1118 if (tooManyViolationsThisLoop()) {
1119 return;
1120 }
1121 BlockGuard.BlockGuardPolicyException e = new StrictModeCustomViolation(mPolicyMask, name);
1122 e.fillInStackTrace();
1123 startHandlingViolationException(e);
1124 }
1125
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001126 // Part of BlockGuard.Policy interface:
1127 public void onReadFromDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001128 if ((mPolicyMask & DETECT_DISK_READ) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001129 return;
1130 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001131 if (tooManyViolationsThisLoop()) {
1132 return;
1133 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001134 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
1135 e.fillInStackTrace();
1136 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001137 }
1138
1139 // Part of BlockGuard.Policy interface:
1140 public void onNetwork() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001141 if ((mPolicyMask & DETECT_NETWORK) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001142 return;
1143 }
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001144 if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
1145 throw new NetworkOnMainThreadException();
1146 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001147 if (tooManyViolationsThisLoop()) {
1148 return;
1149 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001150 BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
1151 e.fillInStackTrace();
1152 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001153 }
1154
1155 public void setPolicyMask(int policyMask) {
1156 mPolicyMask = policyMask;
1157 }
1158
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001159 // Start handling a violation that just started and hasn't
1160 // actually run yet (e.g. no disk write or network operation
1161 // has yet occurred). This sees if we're in an event loop
1162 // thread and, if so, uses it to roughly measure how long the
1163 // violation took.
1164 void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001165 final ViolationInfo info = new ViolationInfo(e, e.getPolicy());
1166 info.violationUptimeMillis = SystemClock.uptimeMillis();
1167 handleViolationWithTimingAttempt(info);
1168 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001169
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001170 // Attempts to fill in the provided ViolationInfo's
1171 // durationMillis field if this thread has a Looper we can use
1172 // to measure with. We measure from the time of violation
1173 // until the time the looper is idle again (right before
1174 // the next epoll_wait)
1175 void handleViolationWithTimingAttempt(final ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001176 Looper looper = Looper.myLooper();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001177
1178 // Without a Looper, we're unable to time how long the
1179 // violation takes place. This case should be rare, as
1180 // most users will care about timing violations that
1181 // happen on their main UI thread. Note that this case is
1182 // also hit when a violation takes place in a Binder
1183 // thread, in "gather" mode. In this case, the duration
1184 // of the violation is computed by the ultimate caller and
1185 // its Looper, if any.
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001186 //
1187 // Also, as a special short-cut case when the only penalty
1188 // bit is death, we die immediately, rather than timing
1189 // the violation's duration. This makes it convenient to
1190 // use in unit tests too, rather than waiting on a Looper.
1191 //
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001192 // TODO: if in gather mode, ignore Looper.myLooper() and always
1193 // go into this immediate mode?
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001194 if (looper == null ||
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001195 (info.policy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001196 info.durationMillis = -1; // unknown (redundant, already set)
1197 handleViolation(info);
1198 return;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001199 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001200
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001201 final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001202 if (records.size() >= MAX_OFFENSES_PER_LOOP) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001203 // Not worth measuring. Too many offenses in one loop.
1204 return;
1205 }
1206 records.add(info);
1207 if (records.size() > 1) {
1208 // There's already been a violation this loop, so we've already
1209 // registered an idle handler to process the list of violations
1210 // at the end of this Looper's loop.
1211 return;
1212 }
1213
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001214 final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ?
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08001215 sWindowManager.get() : null;
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001216 if (windowManager != null) {
1217 try {
1218 windowManager.showStrictModeViolation(true);
1219 } catch (RemoteException unused) {
1220 }
1221 }
1222
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001223 // We post a runnable to a Handler (== delay 0 ms) for
1224 // measuring the end time of a violation instead of using
1225 // an IdleHandler (as was previously used) because an
1226 // IdleHandler may not run for quite a long period of time
1227 // if an ongoing animation is happening and continually
1228 // posting ASAP (0 ms) animation steps. Animations are
1229 // throttled back to 60fps via SurfaceFlinger/View
1230 // invalidates, _not_ by posting frame updates every 16
1231 // milliseconds.
Jeff Sharkey3761f332012-03-16 15:46:46 -07001232 threadHandler.get().postAtFrontOfQueue(new Runnable() {
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001233 public void run() {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001234 long loopFinishTime = SystemClock.uptimeMillis();
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001235
1236 // Note: we do this early, before handling the
1237 // violation below, as handling the violation
1238 // may include PENALTY_DEATH and we don't want
1239 // to keep the red border on.
1240 if (windowManager != null) {
1241 try {
1242 windowManager.showStrictModeViolation(false);
1243 } catch (RemoteException unused) {
1244 }
1245 }
1246
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001247 for (int n = 0; n < records.size(); ++n) {
1248 ViolationInfo v = records.get(n);
1249 v.violationNumThisLoop = n + 1;
1250 v.durationMillis =
1251 (int) (loopFinishTime - v.violationUptimeMillis);
1252 handleViolation(v);
1253 }
1254 records.clear();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001255 }
1256 });
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001257 }
1258
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001259 // Note: It's possible (even quite likely) that the
1260 // thread-local policy mask has changed from the time the
1261 // violation fired and now (after the violating code ran) due
1262 // to people who push/pop temporary policy in regions of code,
1263 // hence the policy being passed around.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001264 void handleViolation(final ViolationInfo info) {
1265 if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) {
1266 Log.wtf(TAG, "unexpected null stacktrace");
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001267 return;
1268 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001269
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001270 if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001271
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001272 if ((info.policy & PENALTY_GATHER) != 0) {
1273 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001274 if (violations == null) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001275 violations = new ArrayList<ViolationInfo>(1);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001276 gatheredViolations.set(violations);
1277 } else if (violations.size() >= 5) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001278 // Too many. In a loop or something? Don't gather them all.
1279 return;
1280 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001281 for (ViolationInfo previous : violations) {
1282 if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001283 // Duplicate. Don't log.
1284 return;
1285 }
1286 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001287 violations.add(info);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001288 return;
1289 }
1290
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001291 // Not perfect, but fast and good enough for dup suppression.
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08001292 Integer crashFingerprint = info.hashCode();
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001293 long lastViolationTime = 0;
Dianne Hackborn390517b2013-05-30 15:03:32 -07001294 if (mLastViolationTime != null) {
1295 Long vtime = mLastViolationTime.get(crashFingerprint);
1296 if (vtime != null) {
1297 lastViolationTime = vtime;
1298 }
1299 } else {
1300 mLastViolationTime = new ArrayMap<Integer, Long>(1);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001301 }
1302 long now = SystemClock.uptimeMillis();
1303 mLastViolationTime.put(crashFingerprint, now);
1304 long timeSinceLastViolationMillis = lastViolationTime == 0 ?
1305 Long.MAX_VALUE : (now - lastViolationTime);
1306
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001307 if ((info.policy & PENALTY_LOG) != 0 &&
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001308 timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001309 if (info.durationMillis != -1) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001310 Log.d(TAG, "StrictMode policy violation; ~duration=" +
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001311 info.durationMillis + " ms: " + info.crashInfo.stackTrace);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001312 } else {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001313 Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001314 }
1315 }
1316
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001317 // The violationMaskSubset, passed to ActivityManager, is a
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001318 // subset of the original StrictMode policy bitmask, with
1319 // only the bit violated and penalty bits to be executed
1320 // by the ActivityManagerService remaining set.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001321 int violationMaskSubset = 0;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001322
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001323 if ((info.policy & PENALTY_DIALOG) != 0 &&
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001324 timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001325 violationMaskSubset |= PENALTY_DIALOG;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001326 }
1327
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001328 if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
1329 violationMaskSubset |= PENALTY_DROPBOX;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001330 }
1331
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001332 if (violationMaskSubset != 0) {
1333 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1334 violationMaskSubset |= violationBit;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001335 final int savedPolicyMask = getThreadPolicyMask();
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001336
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001337 final boolean justDropBox = (info.policy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001338 if (justDropBox) {
1339 // If all we're going to ask the activity manager
1340 // to do is dropbox it (the common case during
1341 // platform development), we can avoid doing this
1342 // call synchronously which Binder data suggests
1343 // isn't always super fast, despite the implementation
1344 // in the ActivityManager trying to be mostly async.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001345 dropboxViolationAsync(violationMaskSubset, info);
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001346 return;
1347 }
1348
1349 // Normal synchronous call to the ActivityManager.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001350 try {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001351 // First, remove any policy before we call into the Activity Manager,
1352 // otherwise we'll infinite recurse as we try to log policy violations
1353 // to disk, thus violating policy, thus requiring logging, etc...
1354 // We restore the current policy below, in the finally block.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001355 setThreadPolicyMask(0);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001356
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001357 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1358 RuntimeInit.getApplicationObject(),
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001359 violationMaskSubset,
1360 info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001361 } catch (RemoteException e) {
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001362 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001363 } finally {
1364 // Restore the policy.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001365 setThreadPolicyMask(savedPolicyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001366 }
1367 }
1368
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001369 if ((info.policy & PENALTY_DEATH) != 0) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001370 executeDeathPenalty(info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001371 }
1372 }
1373 }
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001374
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001375 private static void executeDeathPenalty(ViolationInfo info) {
1376 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1377 throw new StrictModeViolation(info.policy, violationBit, null);
1378 }
1379
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001380 /**
1381 * In the common case, as set by conditionallyEnableDebugLogging,
1382 * we're just dropboxing any violations but not showing a dialog,
1383 * not loggging, and not killing the process. In these cases we
1384 * don't need to do a synchronous call to the ActivityManager.
1385 * This is used by both per-thread and vm-wide violations when
1386 * applicable.
1387 */
1388 private static void dropboxViolationAsync(
1389 final int violationMaskSubset, final ViolationInfo info) {
1390 int outstanding = sDropboxCallsInFlight.incrementAndGet();
1391 if (outstanding > 20) {
1392 // What's going on? Let's not make make the situation
1393 // worse and just not log.
1394 sDropboxCallsInFlight.decrementAndGet();
1395 return;
1396 }
1397
1398 if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1399
1400 new Thread("callActivityManagerForStrictModeDropbox") {
1401 public void run() {
1402 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1403 try {
Brad Fitzpatrick10656852010-11-23 19:01:13 -08001404 IActivityManager am = ActivityManagerNative.getDefault();
1405 if (am == null) {
1406 Log.d(TAG, "No activity manager; failed to Dropbox violation.");
1407 } else {
1408 am.handleApplicationStrictModeViolation(
1409 RuntimeInit.getApplicationObject(),
1410 violationMaskSubset,
1411 info);
1412 }
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001413 } catch (RemoteException e) {
1414 Log.e(TAG, "RemoteException handling StrictMode violation", e);
1415 }
1416 int outstanding = sDropboxCallsInFlight.decrementAndGet();
1417 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
1418 }
1419 }.start();
1420 }
1421
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001422 private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
1423 public void report (String message, Throwable allocationSite) {
1424 onVmPolicyViolation(message, allocationSite);
1425 }
1426 }
1427
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001428 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001429 * Called from Parcel.writeNoException()
1430 */
1431 /* package */ static boolean hasGatheredViolations() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001432 return gatheredViolations.get() != null;
1433 }
1434
1435 /**
1436 * Called from Parcel.writeException(), so we drop this memory and
1437 * don't incorrectly attribute it to the wrong caller on the next
1438 * Binder call on this thread.
1439 */
1440 /* package */ static void clearGatheredViolations() {
1441 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001442 }
1443
1444 /**
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001445 * @hide
1446 */
1447 public static void conditionallyCheckInstanceCounts() {
1448 VmPolicy policy = getVmPolicy();
1449 if (policy.classInstanceLimit.size() == 0) {
1450 return;
1451 }
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08001452
1453 System.gc();
1454 System.runFinalization();
1455 System.gc();
1456
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001457 // Note: classInstanceLimit is immutable, so this is lock-free
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001458 for (Map.Entry<Class, Integer> entry : policy.classInstanceLimit.entrySet()) {
1459 Class klass = entry.getKey();
1460 int limit = entry.getValue();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001461 long instances = VMDebug.countInstancesOfClass(klass, false);
1462 if (instances <= limit) {
1463 continue;
1464 }
1465 Throwable tr = new InstanceCountViolation(klass, instances, limit);
1466 onVmPolicyViolation(tr.getMessage(), tr);
1467 }
1468 }
1469
1470 private static long sLastInstanceCountCheckMillis = 0;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001471 private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001472 private static final MessageQueue.IdleHandler sProcessIdleHandler =
1473 new MessageQueue.IdleHandler() {
1474 public boolean queueIdle() {
1475 long now = SystemClock.uptimeMillis();
1476 if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1477 sLastInstanceCountCheckMillis = now;
1478 conditionallyCheckInstanceCounts();
1479 }
1480 return true;
1481 }
1482 };
1483
1484 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001485 * Sets the policy for what actions in the VM process (on any
1486 * thread) should be detected, as well as the penalty if such
1487 * actions occur.
1488 *
1489 * @param policy the policy to put into place
1490 */
1491 public static void setVmPolicy(final VmPolicy policy) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001492 synchronized (StrictMode.class) {
1493 sVmPolicy = policy;
1494 sVmPolicyMask = policy.mask;
1495 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001496
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001497 Looper looper = Looper.getMainLooper();
1498 if (looper != null) {
1499 MessageQueue mq = looper.mQueue;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001500 if (policy.classInstanceLimit.size() == 0 ||
1501 (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001502 mq.removeIdleHandler(sProcessIdleHandler);
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001503 sIsIdlerRegistered = false;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001504 } else if (!sIsIdlerRegistered) {
1505 mq.addIdleHandler(sProcessIdleHandler);
1506 sIsIdlerRegistered = true;
1507 }
1508 }
1509 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001510 }
1511
1512 /**
1513 * Gets the current VM policy.
1514 */
1515 public static VmPolicy getVmPolicy() {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001516 synchronized (StrictMode.class) {
1517 return sVmPolicy;
1518 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001519 }
1520
1521 /**
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001522 * Enable the recommended StrictMode defaults, with violations just being logged.
1523 *
1524 * <p>This catches disk and network access on the main thread, as
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001525 * well as leaked SQLite cursors and unclosed resources. This is
1526 * simply a wrapper around {@link #setVmPolicy} and {@link
1527 * #setThreadPolicy}.
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001528 */
1529 public static void enableDefaults() {
1530 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
1531 .detectAll()
1532 .penaltyLog()
1533 .build());
1534 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001535 .detectAll()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001536 .penaltyLog()
1537 .build());
1538 }
1539
1540 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001541 * @hide
1542 */
1543 public static boolean vmSqliteObjectLeaksEnabled() {
1544 return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
1545 }
1546
1547 /**
1548 * @hide
1549 */
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001550 public static boolean vmClosableObjectLeaksEnabled() {
1551 return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
1552 }
1553
1554 /**
1555 * @hide
1556 */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001557 public static boolean vmRegistrationLeaksEnabled() {
1558 return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
1559 }
1560
1561 /**
1562 * @hide
1563 */
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001564 public static boolean vmFileUriExposureEnabled() {
1565 return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
1566 }
1567
1568 /**
1569 * @hide
1570 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001571 public static void onSqliteObjectLeaked(String message, Throwable originStack) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001572 onVmPolicyViolation(message, originStack);
1573 }
1574
Steve Block08d584c2011-05-17 19:05:03 +01001575 /**
1576 * @hide
1577 */
1578 public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
1579 onVmPolicyViolation(null, originStack);
1580 }
1581
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001582 /**
1583 * @hide
1584 */
1585 public static void onIntentReceiverLeaked(Throwable originStack) {
1586 onVmPolicyViolation(null, originStack);
1587 }
1588
1589 /**
1590 * @hide
1591 */
1592 public static void onServiceConnectionLeaked(Throwable originStack) {
1593 onVmPolicyViolation(null, originStack);
1594 }
1595
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001596 /**
1597 * @hide
1598 */
1599 public static void onFileUriExposed(String location) {
1600 final String message = "file:// Uri exposed through " + location;
1601 onVmPolicyViolation(message, new Throwable(message));
1602 }
1603
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001604 // Map from VM violation fingerprint to uptime millis.
1605 private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
1606
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001607 /**
1608 * @hide
1609 */
1610 public static void onVmPolicyViolation(String message, Throwable originStack) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001611 final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
1612 final boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0;
1613 final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
1614 final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
1615
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001616 // Erase stuff not relevant for process-wide violations
1617 info.numAnimationsRunning = 0;
1618 info.tags = null;
1619 info.broadcastIntentAction = null;
1620
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001621 final Integer fingerprint = info.hashCode();
1622 final long now = SystemClock.uptimeMillis();
1623 long lastViolationTime = 0;
1624 long timeSinceLastViolationMillis = Long.MAX_VALUE;
1625 synchronized (sLastVmViolationTime) {
1626 if (sLastVmViolationTime.containsKey(fingerprint)) {
1627 lastViolationTime = sLastVmViolationTime.get(fingerprint);
1628 timeSinceLastViolationMillis = now - lastViolationTime;
1629 }
1630 if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
1631 sLastVmViolationTime.put(fingerprint, now);
1632 }
1633 }
1634
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001635 if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001636 Log.e(TAG, message, originStack);
1637 }
1638
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001639 int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001640
1641 if (penaltyDropbox && !penaltyDeath) {
1642 // Common case for userdebug/eng builds. If no death and
1643 // just dropboxing, we can do the ActivityManager call
1644 // asynchronously.
1645 dropboxViolationAsync(violationMaskSubset, info);
1646 return;
1647 }
1648
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001649 if (penaltyDropbox && lastViolationTime == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001650 // The violationMask, passed to ActivityManager, is a
1651 // subset of the original StrictMode policy bitmask, with
1652 // only the bit violated and penalty bits to be executed
1653 // by the ActivityManagerService remaining set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001654 final int savedPolicyMask = getThreadPolicyMask();
1655 try {
1656 // First, remove any policy before we call into the Activity Manager,
1657 // otherwise we'll infinite recurse as we try to log policy violations
1658 // to disk, thus violating policy, thus requiring logging, etc...
1659 // We restore the current policy below, in the finally block.
1660 setThreadPolicyMask(0);
1661
1662 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1663 RuntimeInit.getApplicationObject(),
1664 violationMaskSubset,
1665 info);
1666 } catch (RemoteException e) {
1667 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1668 } finally {
1669 // Restore the policy.
1670 setThreadPolicyMask(savedPolicyMask);
1671 }
1672 }
1673
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001674 if (penaltyDeath) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001675 System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
1676 Process.killProcess(Process.myPid());
1677 System.exit(10);
1678 }
1679 }
1680
1681 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001682 * Called from Parcel.writeNoException()
1683 */
1684 /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001685 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001686 if (violations == null) {
1687 p.writeInt(0);
1688 } else {
1689 p.writeInt(violations.size());
1690 for (int i = 0; i < violations.size(); ++i) {
1691 violations.get(i).writeToParcel(p, 0 /* unused flags? */);
1692 }
1693 if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
1694 violations.clear(); // somewhat redundant, as we're about to null the threadlocal
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001695 }
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001696 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001697 }
1698
1699 private static class LogStackTrace extends Exception {}
1700
1701 /**
1702 * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
1703 * we here read back all the encoded violations.
1704 */
1705 /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
1706 // Our own stack trace to append
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001707 StringWriter sw = new StringWriter();
Dianne Hackborn8c841092013-06-24 13:46:13 -07001708 PrintWriter pw = new FastPrintWriter(sw, false, 256);
1709 new LogStackTrace().printStackTrace(pw);
1710 pw.flush();
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001711 String ourStack = sw.toString();
1712
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001713 int policyMask = getThreadPolicyMask();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001714 boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001715
1716 int numViolations = p.readInt();
1717 for (int i = 0; i < numViolations; ++i) {
1718 if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001719 ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
1720 info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001721 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1722 if (policy instanceof AndroidBlockGuardPolicy) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001723 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001724 }
1725 }
1726 }
1727
1728 /**
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001729 * Called from android_util_Binder.cpp's
1730 * android_os_Parcel_enforceInterface when an incoming Binder call
1731 * requires changing the StrictMode policy mask. The role of this
1732 * function is to ask Binder for its current (native) thread-local
1733 * policy value and synchronize it to libcore's (Java)
1734 * thread-local policy value.
1735 */
1736 private static void onBinderStrictModePolicyChange(int newPolicy) {
1737 setBlockGuardPolicy(newPolicy);
1738 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001739
1740 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001741 * A tracked, critical time span. (e.g. during an animation.)
1742 *
1743 * The object itself is a linked list node, to avoid any allocations
1744 * during rapid span entries and exits.
1745 *
1746 * @hide
1747 */
1748 public static class Span {
1749 private String mName;
1750 private long mCreateMillis;
1751 private Span mNext;
1752 private Span mPrev; // not used when in freeList, only active
1753 private final ThreadSpanState mContainerState;
1754
1755 Span(ThreadSpanState threadState) {
1756 mContainerState = threadState;
1757 }
1758
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08001759 // Empty constructor for the NO_OP_SPAN
1760 protected Span() {
1761 mContainerState = null;
1762 }
1763
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001764 /**
1765 * To be called when the critical span is complete (i.e. the
1766 * animation is done animating). This can be called on any
1767 * thread (even a different one from where the animation was
1768 * taking place), but that's only a defensive implementation
1769 * measure. It really makes no sense for you to call this on
1770 * thread other than that where you created it.
1771 *
1772 * @hide
1773 */
1774 public void finish() {
1775 ThreadSpanState state = mContainerState;
1776 synchronized (state) {
1777 if (mName == null) {
1778 // Duplicate finish call. Ignore.
1779 return;
1780 }
1781
1782 // Remove ourselves from the active list.
1783 if (mPrev != null) {
1784 mPrev.mNext = mNext;
1785 }
1786 if (mNext != null) {
1787 mNext.mPrev = mPrev;
1788 }
1789 if (state.mActiveHead == this) {
1790 state.mActiveHead = mNext;
1791 }
1792
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08001793 state.mActiveSize--;
1794
1795 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
1796
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001797 this.mCreateMillis = -1;
1798 this.mName = null;
1799 this.mPrev = null;
1800 this.mNext = null;
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001801
1802 // Add ourselves to the freeList, if it's not already
1803 // too big.
1804 if (state.mFreeListSize < 5) {
1805 this.mNext = state.mFreeListHead;
1806 state.mFreeListHead = this;
1807 state.mFreeListSize++;
1808 }
1809 }
1810 }
1811 }
1812
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08001813 // The no-op span that's used in user builds.
1814 private static final Span NO_OP_SPAN = new Span() {
1815 public void finish() {
1816 // Do nothing.
1817 }
1818 };
1819
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001820 /**
1821 * Linked lists of active spans and a freelist.
1822 *
1823 * Locking notes: there's one of these structures per thread and
1824 * all members of this structure (as well as the Span nodes under
1825 * it) are guarded by the ThreadSpanState object instance. While
1826 * in theory there'd be no locking required because it's all local
1827 * per-thread, the finish() method above is defensive against
1828 * people calling it on a different thread from where they created
1829 * the Span, hence the locking.
1830 */
1831 private static class ThreadSpanState {
1832 public Span mActiveHead; // doubly-linked list.
1833 public int mActiveSize;
1834 public Span mFreeListHead; // singly-linked list. only changes at head.
1835 public int mFreeListSize;
1836 }
1837
1838 private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
1839 new ThreadLocal<ThreadSpanState>() {
1840 @Override protected ThreadSpanState initialValue() {
1841 return new ThreadSpanState();
1842 }
1843 };
1844
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08001845 private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
1846 protected IWindowManager create() {
1847 return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
1848 }
1849 };
1850
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001851 /**
1852 * Enter a named critical span (e.g. an animation)
1853 *
1854 * <p>The name is an arbitary label (or tag) that will be applied
1855 * to any strictmode violation that happens while this span is
1856 * active. You must call finish() on the span when done.
1857 *
1858 * <p>This will never return null, but on devices without debugging
1859 * enabled, this may return a dummy object on which the finish()
1860 * method is a no-op.
1861 *
1862 * <p>TODO: add CloseGuard to this, verifying callers call finish.
1863 *
1864 * @hide
1865 */
1866 public static Span enterCriticalSpan(String name) {
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08001867 if (IS_USER_BUILD) {
1868 return NO_OP_SPAN;
1869 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001870 if (name == null || name.isEmpty()) {
1871 throw new IllegalArgumentException("name must be non-null and non-empty");
1872 }
1873 ThreadSpanState state = sThisThreadSpanState.get();
1874 Span span = null;
1875 synchronized (state) {
1876 if (state.mFreeListHead != null) {
1877 span = state.mFreeListHead;
1878 state.mFreeListHead = span.mNext;
1879 state.mFreeListSize--;
1880 } else {
1881 // Shouldn't have to do this often.
1882 span = new Span(state);
1883 }
1884 span.mName = name;
1885 span.mCreateMillis = SystemClock.uptimeMillis();
1886 span.mNext = state.mActiveHead;
1887 span.mPrev = null;
1888 state.mActiveHead = span;
1889 state.mActiveSize++;
1890 if (span.mNext != null) {
1891 span.mNext.mPrev = span;
1892 }
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08001893 if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001894 }
1895 return span;
1896 }
1897
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001898 /**
1899 * For code to note that it's slow. This is a no-op unless the
1900 * current thread's {@link android.os.StrictMode.ThreadPolicy} has
1901 * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls}
1902 * enabled.
1903 *
1904 * @param name a short string for the exception stack trace that's
1905 * built if when this fires.
1906 */
1907 public static void noteSlowCall(String name) {
1908 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1909 if (!(policy instanceof AndroidBlockGuardPolicy)) {
1910 // StrictMode not enabled.
1911 return;
1912 }
1913 ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
1914 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001915
1916 /**
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001917 * @hide
1918 */
1919 public static void noteDiskRead() {
1920 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001921 if (!(policy instanceof AndroidBlockGuardPolicy)) {
1922 // StrictMode not enabled.
1923 return;
1924 }
1925 ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
1926 }
1927
1928 /**
1929 * @hide
1930 */
1931 public static void noteDiskWrite() {
1932 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1933 if (!(policy instanceof AndroidBlockGuardPolicy)) {
1934 // StrictMode not enabled.
1935 return;
1936 }
1937 ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
1938 }
1939
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001940 // Guarded by StrictMode.class
1941 private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
1942 new HashMap<Class, Integer>();
1943
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001944 /**
Jeff Brown7e442832011-06-10 18:00:16 -07001945 * Returns an object that is used to track instances of activites.
1946 * The activity should store a reference to the tracker object in one of its fields.
1947 * @hide
1948 */
1949 public static Object trackActivity(Object instance) {
1950 return new InstanceTracker(instance);
1951 }
1952
1953 /**
Brad Fitzpatrick75803572011-01-13 14:21:03 -08001954 * @hide
1955 */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001956 public static void incrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07001957 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08001958 return;
1959 }
Jeff Brown7e442832011-06-10 18:00:16 -07001960
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001961 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07001962 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
1963 return;
1964 }
1965
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001966 Integer expected = sExpectedActivityInstanceCount.get(klass);
1967 Integer newExpected = expected == null ? 1 : expected + 1;
1968 sExpectedActivityInstanceCount.put(klass, newExpected);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001969 }
1970 }
1971
1972 /**
1973 * @hide
1974 */
1975 public static void decrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07001976 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08001977 return;
1978 }
Jeff Brown7e442832011-06-10 18:00:16 -07001979
1980 final int limit;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001981 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07001982 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
1983 return;
1984 }
1985
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001986 Integer expected = sExpectedActivityInstanceCount.get(klass);
Jeff Brown7e442832011-06-10 18:00:16 -07001987 int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001988 if (newExpected == 0) {
1989 sExpectedActivityInstanceCount.remove(klass);
1990 } else {
1991 sExpectedActivityInstanceCount.put(klass, newExpected);
1992 }
Jeff Brown7e442832011-06-10 18:00:16 -07001993
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001994 // Note: adding 1 here to give some breathing room during
1995 // orientation changes. (shouldn't be necessary, though?)
Jeff Brown7e442832011-06-10 18:00:16 -07001996 limit = newExpected + 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001997 }
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001998
Jeff Brown7e442832011-06-10 18:00:16 -07001999 // Quick check.
2000 int actual = InstanceTracker.getInstanceCount(klass);
2001 if (actual <= limit) {
2002 return;
2003 }
2004
2005 // Do a GC and explicit count to double-check.
2006 // This is the work that we are trying to avoid by tracking the object instances
2007 // explicity. Running an explicit GC can be expensive (80ms) and so can walking
2008 // the heap to count instance (30ms). This extra work can make the system feel
2009 // noticeably less responsive during orientation changes when activities are
2010 // being restarted. Granted, it is only a problem when StrictMode is enabled
2011 // but it is annoying.
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08002012
2013 System.gc();
2014 System.runFinalization();
2015 System.gc();
Jeff Brown7e442832011-06-10 18:00:16 -07002016
2017 long instances = VMDebug.countInstancesOfClass(klass, false);
2018 if (instances > limit) {
2019 Throwable tr = new InstanceCountViolation(klass, instances, limit);
2020 onVmPolicyViolation(tr.getMessage(), tr);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002021 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002022 }
2023
2024 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002025 * Parcelable that gets sent in Binder call headers back to callers
2026 * to report violations that happened during a cross-process call.
2027 *
2028 * @hide
2029 */
2030 public static class ViolationInfo {
2031 /**
2032 * Stack and other stuff info.
2033 */
2034 public final ApplicationErrorReport.CrashInfo crashInfo;
2035
2036 /**
2037 * The strict mode policy mask at the time of violation.
2038 */
2039 public final int policy;
2040
2041 /**
2042 * The wall time duration of the violation, when known. -1 when
2043 * not known.
2044 */
2045 public int durationMillis = -1;
2046
2047 /**
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002048 * The number of animations currently running.
2049 */
2050 public int numAnimationsRunning = 0;
2051
2052 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002053 * List of tags from active Span instances during this
2054 * violation, or null for none.
2055 */
2056 public String[] tags;
2057
2058 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002059 * Which violation number this was (1-based) since the last Looper loop,
2060 * from the perspective of the root caller (if it crossed any processes
2061 * via Binder calls). The value is 0 if the root caller wasn't on a Looper
2062 * thread.
2063 */
2064 public int violationNumThisLoop;
2065
2066 /**
2067 * The time (in terms of SystemClock.uptimeMillis()) that the
2068 * violation occurred.
2069 */
2070 public long violationUptimeMillis;
2071
2072 /**
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002073 * The action of the Intent being broadcast to somebody's onReceive
2074 * on this thread right now, or null.
2075 */
2076 public String broadcastIntentAction;
2077
2078 /**
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002079 * If this is a instance count violation, the number of instances in memory,
2080 * else -1.
2081 */
2082 public long numInstances = -1;
2083
2084 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002085 * Create an uninitialized instance of ViolationInfo
2086 */
2087 public ViolationInfo() {
2088 crashInfo = null;
2089 policy = 0;
2090 }
2091
2092 /**
2093 * Create an instance of ViolationInfo initialized from an exception.
2094 */
2095 public ViolationInfo(Throwable tr, int policy) {
2096 crashInfo = new ApplicationErrorReport.CrashInfo(tr);
2097 violationUptimeMillis = SystemClock.uptimeMillis();
2098 this.policy = policy;
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002099 this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002100 Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2101 if (broadcastIntent != null) {
2102 broadcastIntentAction = broadcastIntent.getAction();
2103 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002104 ThreadSpanState state = sThisThreadSpanState.get();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002105 if (tr instanceof InstanceCountViolation) {
2106 this.numInstances = ((InstanceCountViolation) tr).mInstances;
2107 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002108 synchronized (state) {
2109 int spanActiveCount = state.mActiveSize;
2110 if (spanActiveCount > MAX_SPAN_TAGS) {
2111 spanActiveCount = MAX_SPAN_TAGS;
2112 }
2113 if (spanActiveCount != 0) {
2114 this.tags = new String[spanActiveCount];
2115 Span iter = state.mActiveHead;
2116 int index = 0;
2117 while (iter != null && index < spanActiveCount) {
2118 this.tags[index] = iter.mName;
2119 index++;
2120 iter = iter.mNext;
2121 }
2122 }
2123 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002124 }
2125
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002126 @Override
2127 public int hashCode() {
2128 int result = 17;
2129 result = 37 * result + crashInfo.stackTrace.hashCode();
2130 if (numAnimationsRunning != 0) {
2131 result *= 37;
2132 }
2133 if (broadcastIntentAction != null) {
2134 result = 37 * result + broadcastIntentAction.hashCode();
2135 }
2136 if (tags != null) {
2137 for (String tag : tags) {
2138 result = 37 * result + tag.hashCode();
2139 }
2140 }
2141 return result;
2142 }
2143
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002144 /**
2145 * Create an instance of ViolationInfo initialized from a Parcel.
2146 */
2147 public ViolationInfo(Parcel in) {
2148 this(in, false);
2149 }
2150
2151 /**
2152 * Create an instance of ViolationInfo initialized from a Parcel.
2153 *
2154 * @param unsetGatheringBit if true, the caller is the root caller
2155 * and the gathering penalty should be removed.
2156 */
2157 public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
2158 crashInfo = new ApplicationErrorReport.CrashInfo(in);
2159 int rawPolicy = in.readInt();
2160 if (unsetGatheringBit) {
2161 policy = rawPolicy & ~PENALTY_GATHER;
2162 } else {
2163 policy = rawPolicy;
2164 }
2165 durationMillis = in.readInt();
2166 violationNumThisLoop = in.readInt();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002167 numAnimationsRunning = in.readInt();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002168 violationUptimeMillis = in.readLong();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002169 numInstances = in.readLong();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002170 broadcastIntentAction = in.readString();
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002171 tags = in.readStringArray();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002172 }
2173
2174 /**
2175 * Save a ViolationInfo instance to a parcel.
2176 */
2177 public void writeToParcel(Parcel dest, int flags) {
2178 crashInfo.writeToParcel(dest, flags);
2179 dest.writeInt(policy);
2180 dest.writeInt(durationMillis);
2181 dest.writeInt(violationNumThisLoop);
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002182 dest.writeInt(numAnimationsRunning);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002183 dest.writeLong(violationUptimeMillis);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002184 dest.writeLong(numInstances);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002185 dest.writeString(broadcastIntentAction);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002186 dest.writeStringArray(tags);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002187 }
2188
2189
2190 /**
2191 * Dump a ViolationInfo instance to a Printer.
2192 */
2193 public void dump(Printer pw, String prefix) {
2194 crashInfo.dump(pw, prefix);
2195 pw.println(prefix + "policy: " + policy);
2196 if (durationMillis != -1) {
2197 pw.println(prefix + "durationMillis: " + durationMillis);
2198 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002199 if (numInstances != -1) {
2200 pw.println(prefix + "numInstances: " + numInstances);
2201 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002202 if (violationNumThisLoop != 0) {
2203 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2204 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002205 if (numAnimationsRunning != 0) {
2206 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2207 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002208 pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002209 if (broadcastIntentAction != null) {
2210 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2211 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002212 if (tags != null) {
2213 int index = 0;
2214 for (String tag : tags) {
2215 pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2216 }
2217 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002218 }
2219
2220 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002221
2222 // Dummy throwable, for now, since we don't know when or where the
2223 // leaked instances came from. We might in the future, but for
2224 // now we suppress the stack trace because it's useless and/or
2225 // misleading.
2226 private static class InstanceCountViolation extends Throwable {
2227 final Class mClass;
2228 final long mInstances;
2229 final int mLimit;
2230
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002231 private static final StackTraceElement[] FAKE_STACK = {
2232 new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
2233 "StrictMode.java", 1)
2234 };
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002235
2236 public InstanceCountViolation(Class klass, long instances, int limit) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002237 super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002238 setStackTrace(FAKE_STACK);
2239 mClass = klass;
2240 mInstances = instances;
2241 mLimit = limit;
2242 }
2243 }
Jeff Brown7e442832011-06-10 18:00:16 -07002244
2245 private static final class InstanceTracker {
2246 private static final HashMap<Class<?>, Integer> sInstanceCounts =
2247 new HashMap<Class<?>, Integer>();
2248
2249 private final Class<?> mKlass;
2250
2251 public InstanceTracker(Object instance) {
2252 mKlass = instance.getClass();
2253
2254 synchronized (sInstanceCounts) {
2255 final Integer value = sInstanceCounts.get(mKlass);
2256 final int newValue = value != null ? value + 1 : 1;
2257 sInstanceCounts.put(mKlass, newValue);
2258 }
2259 }
2260
2261 @Override
2262 protected void finalize() throws Throwable {
2263 try {
2264 synchronized (sInstanceCounts) {
2265 final Integer value = sInstanceCounts.get(mKlass);
2266 if (value != null) {
2267 final int newValue = value - 1;
2268 if (newValue > 0) {
2269 sInstanceCounts.put(mKlass, newValue);
2270 } else {
2271 sInstanceCounts.remove(mKlass);
2272 }
2273 }
2274 }
2275 } finally {
2276 super.finalize();
2277 }
2278 }
2279
2280 public static int getInstanceCount(Class<?> klass) {
2281 synchronized (sInstanceCounts) {
2282 final Integer value = sInstanceCounts.get(klass);
2283 return value != null ? value : 0;
2284 }
2285 }
2286 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07002287}