blob: d794ca674d49a0ae91cbc58f05302db837afb1d0 [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 }
1452 Runtime.getRuntime().gc();
1453 // Note: classInstanceLimit is immutable, so this is lock-free
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001454 for (Map.Entry<Class, Integer> entry : policy.classInstanceLimit.entrySet()) {
1455 Class klass = entry.getKey();
1456 int limit = entry.getValue();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001457 long instances = VMDebug.countInstancesOfClass(klass, false);
1458 if (instances <= limit) {
1459 continue;
1460 }
1461 Throwable tr = new InstanceCountViolation(klass, instances, limit);
1462 onVmPolicyViolation(tr.getMessage(), tr);
1463 }
1464 }
1465
1466 private static long sLastInstanceCountCheckMillis = 0;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001467 private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001468 private static final MessageQueue.IdleHandler sProcessIdleHandler =
1469 new MessageQueue.IdleHandler() {
1470 public boolean queueIdle() {
1471 long now = SystemClock.uptimeMillis();
1472 if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1473 sLastInstanceCountCheckMillis = now;
1474 conditionallyCheckInstanceCounts();
1475 }
1476 return true;
1477 }
1478 };
1479
1480 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001481 * Sets the policy for what actions in the VM process (on any
1482 * thread) should be detected, as well as the penalty if such
1483 * actions occur.
1484 *
1485 * @param policy the policy to put into place
1486 */
1487 public static void setVmPolicy(final VmPolicy policy) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001488 synchronized (StrictMode.class) {
1489 sVmPolicy = policy;
1490 sVmPolicyMask = policy.mask;
1491 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001492
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001493 Looper looper = Looper.getMainLooper();
1494 if (looper != null) {
1495 MessageQueue mq = looper.mQueue;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001496 if (policy.classInstanceLimit.size() == 0 ||
1497 (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001498 mq.removeIdleHandler(sProcessIdleHandler);
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001499 sIsIdlerRegistered = false;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001500 } else if (!sIsIdlerRegistered) {
1501 mq.addIdleHandler(sProcessIdleHandler);
1502 sIsIdlerRegistered = true;
1503 }
1504 }
1505 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001506 }
1507
1508 /**
1509 * Gets the current VM policy.
1510 */
1511 public static VmPolicy getVmPolicy() {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001512 synchronized (StrictMode.class) {
1513 return sVmPolicy;
1514 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001515 }
1516
1517 /**
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001518 * Enable the recommended StrictMode defaults, with violations just being logged.
1519 *
1520 * <p>This catches disk and network access on the main thread, as
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001521 * well as leaked SQLite cursors and unclosed resources. This is
1522 * simply a wrapper around {@link #setVmPolicy} and {@link
1523 * #setThreadPolicy}.
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001524 */
1525 public static void enableDefaults() {
1526 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
1527 .detectAll()
1528 .penaltyLog()
1529 .build());
1530 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001531 .detectAll()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001532 .penaltyLog()
1533 .build());
1534 }
1535
1536 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001537 * @hide
1538 */
1539 public static boolean vmSqliteObjectLeaksEnabled() {
1540 return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
1541 }
1542
1543 /**
1544 * @hide
1545 */
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001546 public static boolean vmClosableObjectLeaksEnabled() {
1547 return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
1548 }
1549
1550 /**
1551 * @hide
1552 */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001553 public static boolean vmRegistrationLeaksEnabled() {
1554 return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
1555 }
1556
1557 /**
1558 * @hide
1559 */
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001560 public static boolean vmFileUriExposureEnabled() {
1561 return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
1562 }
1563
1564 /**
1565 * @hide
1566 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001567 public static void onSqliteObjectLeaked(String message, Throwable originStack) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001568 onVmPolicyViolation(message, originStack);
1569 }
1570
Steve Block08d584c2011-05-17 19:05:03 +01001571 /**
1572 * @hide
1573 */
1574 public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
1575 onVmPolicyViolation(null, originStack);
1576 }
1577
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001578 /**
1579 * @hide
1580 */
1581 public static void onIntentReceiverLeaked(Throwable originStack) {
1582 onVmPolicyViolation(null, originStack);
1583 }
1584
1585 /**
1586 * @hide
1587 */
1588 public static void onServiceConnectionLeaked(Throwable originStack) {
1589 onVmPolicyViolation(null, originStack);
1590 }
1591
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001592 /**
1593 * @hide
1594 */
1595 public static void onFileUriExposed(String location) {
1596 final String message = "file:// Uri exposed through " + location;
1597 onVmPolicyViolation(message, new Throwable(message));
1598 }
1599
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001600 // Map from VM violation fingerprint to uptime millis.
1601 private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
1602
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001603 /**
1604 * @hide
1605 */
1606 public static void onVmPolicyViolation(String message, Throwable originStack) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001607 final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
1608 final boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0;
1609 final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
1610 final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
1611
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001612 // Erase stuff not relevant for process-wide violations
1613 info.numAnimationsRunning = 0;
1614 info.tags = null;
1615 info.broadcastIntentAction = null;
1616
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001617 final Integer fingerprint = info.hashCode();
1618 final long now = SystemClock.uptimeMillis();
1619 long lastViolationTime = 0;
1620 long timeSinceLastViolationMillis = Long.MAX_VALUE;
1621 synchronized (sLastVmViolationTime) {
1622 if (sLastVmViolationTime.containsKey(fingerprint)) {
1623 lastViolationTime = sLastVmViolationTime.get(fingerprint);
1624 timeSinceLastViolationMillis = now - lastViolationTime;
1625 }
1626 if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
1627 sLastVmViolationTime.put(fingerprint, now);
1628 }
1629 }
1630
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001631 if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001632 Log.e(TAG, message, originStack);
1633 }
1634
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001635 int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001636
1637 if (penaltyDropbox && !penaltyDeath) {
1638 // Common case for userdebug/eng builds. If no death and
1639 // just dropboxing, we can do the ActivityManager call
1640 // asynchronously.
1641 dropboxViolationAsync(violationMaskSubset, info);
1642 return;
1643 }
1644
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001645 if (penaltyDropbox && lastViolationTime == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001646 // The violationMask, passed to ActivityManager, is a
1647 // subset of the original StrictMode policy bitmask, with
1648 // only the bit violated and penalty bits to be executed
1649 // by the ActivityManagerService remaining set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001650 final int savedPolicyMask = getThreadPolicyMask();
1651 try {
1652 // First, remove any policy before we call into the Activity Manager,
1653 // otherwise we'll infinite recurse as we try to log policy violations
1654 // to disk, thus violating policy, thus requiring logging, etc...
1655 // We restore the current policy below, in the finally block.
1656 setThreadPolicyMask(0);
1657
1658 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1659 RuntimeInit.getApplicationObject(),
1660 violationMaskSubset,
1661 info);
1662 } catch (RemoteException e) {
1663 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1664 } finally {
1665 // Restore the policy.
1666 setThreadPolicyMask(savedPolicyMask);
1667 }
1668 }
1669
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001670 if (penaltyDeath) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001671 System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
1672 Process.killProcess(Process.myPid());
1673 System.exit(10);
1674 }
1675 }
1676
1677 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001678 * Called from Parcel.writeNoException()
1679 */
1680 /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001681 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001682 if (violations == null) {
1683 p.writeInt(0);
1684 } else {
1685 p.writeInt(violations.size());
1686 for (int i = 0; i < violations.size(); ++i) {
1687 violations.get(i).writeToParcel(p, 0 /* unused flags? */);
1688 }
1689 if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
1690 violations.clear(); // somewhat redundant, as we're about to null the threadlocal
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001691 }
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001692 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001693 }
1694
1695 private static class LogStackTrace extends Exception {}
1696
1697 /**
1698 * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
1699 * we here read back all the encoded violations.
1700 */
1701 /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
1702 // Our own stack trace to append
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001703 StringWriter sw = new StringWriter();
Dianne Hackborn8c841092013-06-24 13:46:13 -07001704 PrintWriter pw = new FastPrintWriter(sw, false, 256);
1705 new LogStackTrace().printStackTrace(pw);
1706 pw.flush();
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001707 String ourStack = sw.toString();
1708
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001709 int policyMask = getThreadPolicyMask();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001710 boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001711
1712 int numViolations = p.readInt();
1713 for (int i = 0; i < numViolations; ++i) {
1714 if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001715 ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
1716 info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001717 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1718 if (policy instanceof AndroidBlockGuardPolicy) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001719 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001720 }
1721 }
1722 }
1723
1724 /**
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001725 * Called from android_util_Binder.cpp's
1726 * android_os_Parcel_enforceInterface when an incoming Binder call
1727 * requires changing the StrictMode policy mask. The role of this
1728 * function is to ask Binder for its current (native) thread-local
1729 * policy value and synchronize it to libcore's (Java)
1730 * thread-local policy value.
1731 */
1732 private static void onBinderStrictModePolicyChange(int newPolicy) {
1733 setBlockGuardPolicy(newPolicy);
1734 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001735
1736 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001737 * A tracked, critical time span. (e.g. during an animation.)
1738 *
1739 * The object itself is a linked list node, to avoid any allocations
1740 * during rapid span entries and exits.
1741 *
1742 * @hide
1743 */
1744 public static class Span {
1745 private String mName;
1746 private long mCreateMillis;
1747 private Span mNext;
1748 private Span mPrev; // not used when in freeList, only active
1749 private final ThreadSpanState mContainerState;
1750
1751 Span(ThreadSpanState threadState) {
1752 mContainerState = threadState;
1753 }
1754
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08001755 // Empty constructor for the NO_OP_SPAN
1756 protected Span() {
1757 mContainerState = null;
1758 }
1759
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001760 /**
1761 * To be called when the critical span is complete (i.e. the
1762 * animation is done animating). This can be called on any
1763 * thread (even a different one from where the animation was
1764 * taking place), but that's only a defensive implementation
1765 * measure. It really makes no sense for you to call this on
1766 * thread other than that where you created it.
1767 *
1768 * @hide
1769 */
1770 public void finish() {
1771 ThreadSpanState state = mContainerState;
1772 synchronized (state) {
1773 if (mName == null) {
1774 // Duplicate finish call. Ignore.
1775 return;
1776 }
1777
1778 // Remove ourselves from the active list.
1779 if (mPrev != null) {
1780 mPrev.mNext = mNext;
1781 }
1782 if (mNext != null) {
1783 mNext.mPrev = mPrev;
1784 }
1785 if (state.mActiveHead == this) {
1786 state.mActiveHead = mNext;
1787 }
1788
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08001789 state.mActiveSize--;
1790
1791 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
1792
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001793 this.mCreateMillis = -1;
1794 this.mName = null;
1795 this.mPrev = null;
1796 this.mNext = null;
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001797
1798 // Add ourselves to the freeList, if it's not already
1799 // too big.
1800 if (state.mFreeListSize < 5) {
1801 this.mNext = state.mFreeListHead;
1802 state.mFreeListHead = this;
1803 state.mFreeListSize++;
1804 }
1805 }
1806 }
1807 }
1808
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08001809 // The no-op span that's used in user builds.
1810 private static final Span NO_OP_SPAN = new Span() {
1811 public void finish() {
1812 // Do nothing.
1813 }
1814 };
1815
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001816 /**
1817 * Linked lists of active spans and a freelist.
1818 *
1819 * Locking notes: there's one of these structures per thread and
1820 * all members of this structure (as well as the Span nodes under
1821 * it) are guarded by the ThreadSpanState object instance. While
1822 * in theory there'd be no locking required because it's all local
1823 * per-thread, the finish() method above is defensive against
1824 * people calling it on a different thread from where they created
1825 * the Span, hence the locking.
1826 */
1827 private static class ThreadSpanState {
1828 public Span mActiveHead; // doubly-linked list.
1829 public int mActiveSize;
1830 public Span mFreeListHead; // singly-linked list. only changes at head.
1831 public int mFreeListSize;
1832 }
1833
1834 private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
1835 new ThreadLocal<ThreadSpanState>() {
1836 @Override protected ThreadSpanState initialValue() {
1837 return new ThreadSpanState();
1838 }
1839 };
1840
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08001841 private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
1842 protected IWindowManager create() {
1843 return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
1844 }
1845 };
1846
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001847 /**
1848 * Enter a named critical span (e.g. an animation)
1849 *
1850 * <p>The name is an arbitary label (or tag) that will be applied
1851 * to any strictmode violation that happens while this span is
1852 * active. You must call finish() on the span when done.
1853 *
1854 * <p>This will never return null, but on devices without debugging
1855 * enabled, this may return a dummy object on which the finish()
1856 * method is a no-op.
1857 *
1858 * <p>TODO: add CloseGuard to this, verifying callers call finish.
1859 *
1860 * @hide
1861 */
1862 public static Span enterCriticalSpan(String name) {
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08001863 if (IS_USER_BUILD) {
1864 return NO_OP_SPAN;
1865 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001866 if (name == null || name.isEmpty()) {
1867 throw new IllegalArgumentException("name must be non-null and non-empty");
1868 }
1869 ThreadSpanState state = sThisThreadSpanState.get();
1870 Span span = null;
1871 synchronized (state) {
1872 if (state.mFreeListHead != null) {
1873 span = state.mFreeListHead;
1874 state.mFreeListHead = span.mNext;
1875 state.mFreeListSize--;
1876 } else {
1877 // Shouldn't have to do this often.
1878 span = new Span(state);
1879 }
1880 span.mName = name;
1881 span.mCreateMillis = SystemClock.uptimeMillis();
1882 span.mNext = state.mActiveHead;
1883 span.mPrev = null;
1884 state.mActiveHead = span;
1885 state.mActiveSize++;
1886 if (span.mNext != null) {
1887 span.mNext.mPrev = span;
1888 }
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08001889 if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001890 }
1891 return span;
1892 }
1893
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001894 /**
1895 * For code to note that it's slow. This is a no-op unless the
1896 * current thread's {@link android.os.StrictMode.ThreadPolicy} has
1897 * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls}
1898 * enabled.
1899 *
1900 * @param name a short string for the exception stack trace that's
1901 * built if when this fires.
1902 */
1903 public static void noteSlowCall(String name) {
1904 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1905 if (!(policy instanceof AndroidBlockGuardPolicy)) {
1906 // StrictMode not enabled.
1907 return;
1908 }
1909 ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
1910 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001911
1912 /**
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001913 * @hide
1914 */
1915 public static void noteDiskRead() {
1916 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001917 if (!(policy instanceof AndroidBlockGuardPolicy)) {
1918 // StrictMode not enabled.
1919 return;
1920 }
1921 ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
1922 }
1923
1924 /**
1925 * @hide
1926 */
1927 public static void noteDiskWrite() {
1928 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1929 if (!(policy instanceof AndroidBlockGuardPolicy)) {
1930 // StrictMode not enabled.
1931 return;
1932 }
1933 ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
1934 }
1935
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001936 // Guarded by StrictMode.class
1937 private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
1938 new HashMap<Class, Integer>();
1939
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001940 /**
Jeff Brown7e442832011-06-10 18:00:16 -07001941 * Returns an object that is used to track instances of activites.
1942 * The activity should store a reference to the tracker object in one of its fields.
1943 * @hide
1944 */
1945 public static Object trackActivity(Object instance) {
1946 return new InstanceTracker(instance);
1947 }
1948
1949 /**
Brad Fitzpatrick75803572011-01-13 14:21:03 -08001950 * @hide
1951 */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001952 public static void incrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07001953 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08001954 return;
1955 }
Jeff Brown7e442832011-06-10 18:00:16 -07001956
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001957 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07001958 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
1959 return;
1960 }
1961
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001962 Integer expected = sExpectedActivityInstanceCount.get(klass);
1963 Integer newExpected = expected == null ? 1 : expected + 1;
1964 sExpectedActivityInstanceCount.put(klass, newExpected);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001965 }
1966 }
1967
1968 /**
1969 * @hide
1970 */
1971 public static void decrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07001972 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08001973 return;
1974 }
Jeff Brown7e442832011-06-10 18:00:16 -07001975
1976 final int limit;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001977 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07001978 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
1979 return;
1980 }
1981
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001982 Integer expected = sExpectedActivityInstanceCount.get(klass);
Jeff Brown7e442832011-06-10 18:00:16 -07001983 int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001984 if (newExpected == 0) {
1985 sExpectedActivityInstanceCount.remove(klass);
1986 } else {
1987 sExpectedActivityInstanceCount.put(klass, newExpected);
1988 }
Jeff Brown7e442832011-06-10 18:00:16 -07001989
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001990 // Note: adding 1 here to give some breathing room during
1991 // orientation changes. (shouldn't be necessary, though?)
Jeff Brown7e442832011-06-10 18:00:16 -07001992 limit = newExpected + 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001993 }
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001994
Jeff Brown7e442832011-06-10 18:00:16 -07001995 // Quick check.
1996 int actual = InstanceTracker.getInstanceCount(klass);
1997 if (actual <= limit) {
1998 return;
1999 }
2000
2001 // Do a GC and explicit count to double-check.
2002 // This is the work that we are trying to avoid by tracking the object instances
2003 // explicity. Running an explicit GC can be expensive (80ms) and so can walking
2004 // the heap to count instance (30ms). This extra work can make the system feel
2005 // noticeably less responsive during orientation changes when activities are
2006 // being restarted. Granted, it is only a problem when StrictMode is enabled
2007 // but it is annoying.
2008 Runtime.getRuntime().gc();
2009
2010 long instances = VMDebug.countInstancesOfClass(klass, false);
2011 if (instances > limit) {
2012 Throwable tr = new InstanceCountViolation(klass, instances, limit);
2013 onVmPolicyViolation(tr.getMessage(), tr);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002014 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002015 }
2016
2017 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002018 * Parcelable that gets sent in Binder call headers back to callers
2019 * to report violations that happened during a cross-process call.
2020 *
2021 * @hide
2022 */
2023 public static class ViolationInfo {
2024 /**
2025 * Stack and other stuff info.
2026 */
2027 public final ApplicationErrorReport.CrashInfo crashInfo;
2028
2029 /**
2030 * The strict mode policy mask at the time of violation.
2031 */
2032 public final int policy;
2033
2034 /**
2035 * The wall time duration of the violation, when known. -1 when
2036 * not known.
2037 */
2038 public int durationMillis = -1;
2039
2040 /**
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002041 * The number of animations currently running.
2042 */
2043 public int numAnimationsRunning = 0;
2044
2045 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002046 * List of tags from active Span instances during this
2047 * violation, or null for none.
2048 */
2049 public String[] tags;
2050
2051 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002052 * Which violation number this was (1-based) since the last Looper loop,
2053 * from the perspective of the root caller (if it crossed any processes
2054 * via Binder calls). The value is 0 if the root caller wasn't on a Looper
2055 * thread.
2056 */
2057 public int violationNumThisLoop;
2058
2059 /**
2060 * The time (in terms of SystemClock.uptimeMillis()) that the
2061 * violation occurred.
2062 */
2063 public long violationUptimeMillis;
2064
2065 /**
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002066 * The action of the Intent being broadcast to somebody's onReceive
2067 * on this thread right now, or null.
2068 */
2069 public String broadcastIntentAction;
2070
2071 /**
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002072 * If this is a instance count violation, the number of instances in memory,
2073 * else -1.
2074 */
2075 public long numInstances = -1;
2076
2077 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002078 * Create an uninitialized instance of ViolationInfo
2079 */
2080 public ViolationInfo() {
2081 crashInfo = null;
2082 policy = 0;
2083 }
2084
2085 /**
2086 * Create an instance of ViolationInfo initialized from an exception.
2087 */
2088 public ViolationInfo(Throwable tr, int policy) {
2089 crashInfo = new ApplicationErrorReport.CrashInfo(tr);
2090 violationUptimeMillis = SystemClock.uptimeMillis();
2091 this.policy = policy;
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002092 this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002093 Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2094 if (broadcastIntent != null) {
2095 broadcastIntentAction = broadcastIntent.getAction();
2096 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002097 ThreadSpanState state = sThisThreadSpanState.get();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002098 if (tr instanceof InstanceCountViolation) {
2099 this.numInstances = ((InstanceCountViolation) tr).mInstances;
2100 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002101 synchronized (state) {
2102 int spanActiveCount = state.mActiveSize;
2103 if (spanActiveCount > MAX_SPAN_TAGS) {
2104 spanActiveCount = MAX_SPAN_TAGS;
2105 }
2106 if (spanActiveCount != 0) {
2107 this.tags = new String[spanActiveCount];
2108 Span iter = state.mActiveHead;
2109 int index = 0;
2110 while (iter != null && index < spanActiveCount) {
2111 this.tags[index] = iter.mName;
2112 index++;
2113 iter = iter.mNext;
2114 }
2115 }
2116 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002117 }
2118
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002119 @Override
2120 public int hashCode() {
2121 int result = 17;
2122 result = 37 * result + crashInfo.stackTrace.hashCode();
2123 if (numAnimationsRunning != 0) {
2124 result *= 37;
2125 }
2126 if (broadcastIntentAction != null) {
2127 result = 37 * result + broadcastIntentAction.hashCode();
2128 }
2129 if (tags != null) {
2130 for (String tag : tags) {
2131 result = 37 * result + tag.hashCode();
2132 }
2133 }
2134 return result;
2135 }
2136
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002137 /**
2138 * Create an instance of ViolationInfo initialized from a Parcel.
2139 */
2140 public ViolationInfo(Parcel in) {
2141 this(in, false);
2142 }
2143
2144 /**
2145 * Create an instance of ViolationInfo initialized from a Parcel.
2146 *
2147 * @param unsetGatheringBit if true, the caller is the root caller
2148 * and the gathering penalty should be removed.
2149 */
2150 public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
2151 crashInfo = new ApplicationErrorReport.CrashInfo(in);
2152 int rawPolicy = in.readInt();
2153 if (unsetGatheringBit) {
2154 policy = rawPolicy & ~PENALTY_GATHER;
2155 } else {
2156 policy = rawPolicy;
2157 }
2158 durationMillis = in.readInt();
2159 violationNumThisLoop = in.readInt();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002160 numAnimationsRunning = in.readInt();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002161 violationUptimeMillis = in.readLong();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002162 numInstances = in.readLong();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002163 broadcastIntentAction = in.readString();
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002164 tags = in.readStringArray();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002165 }
2166
2167 /**
2168 * Save a ViolationInfo instance to a parcel.
2169 */
2170 public void writeToParcel(Parcel dest, int flags) {
2171 crashInfo.writeToParcel(dest, flags);
2172 dest.writeInt(policy);
2173 dest.writeInt(durationMillis);
2174 dest.writeInt(violationNumThisLoop);
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002175 dest.writeInt(numAnimationsRunning);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002176 dest.writeLong(violationUptimeMillis);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002177 dest.writeLong(numInstances);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002178 dest.writeString(broadcastIntentAction);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002179 dest.writeStringArray(tags);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002180 }
2181
2182
2183 /**
2184 * Dump a ViolationInfo instance to a Printer.
2185 */
2186 public void dump(Printer pw, String prefix) {
2187 crashInfo.dump(pw, prefix);
2188 pw.println(prefix + "policy: " + policy);
2189 if (durationMillis != -1) {
2190 pw.println(prefix + "durationMillis: " + durationMillis);
2191 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002192 if (numInstances != -1) {
2193 pw.println(prefix + "numInstances: " + numInstances);
2194 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002195 if (violationNumThisLoop != 0) {
2196 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2197 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002198 if (numAnimationsRunning != 0) {
2199 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2200 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002201 pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002202 if (broadcastIntentAction != null) {
2203 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2204 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002205 if (tags != null) {
2206 int index = 0;
2207 for (String tag : tags) {
2208 pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2209 }
2210 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002211 }
2212
2213 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002214
2215 // Dummy throwable, for now, since we don't know when or where the
2216 // leaked instances came from. We might in the future, but for
2217 // now we suppress the stack trace because it's useless and/or
2218 // misleading.
2219 private static class InstanceCountViolation extends Throwable {
2220 final Class mClass;
2221 final long mInstances;
2222 final int mLimit;
2223
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002224 private static final StackTraceElement[] FAKE_STACK = {
2225 new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
2226 "StrictMode.java", 1)
2227 };
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002228
2229 public InstanceCountViolation(Class klass, long instances, int limit) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002230 super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002231 setStackTrace(FAKE_STACK);
2232 mClass = klass;
2233 mInstances = instances;
2234 mLimit = limit;
2235 }
2236 }
Jeff Brown7e442832011-06-10 18:00:16 -07002237
2238 private static final class InstanceTracker {
2239 private static final HashMap<Class<?>, Integer> sInstanceCounts =
2240 new HashMap<Class<?>, Integer>();
2241
2242 private final Class<?> mKlass;
2243
2244 public InstanceTracker(Object instance) {
2245 mKlass = instance.getClass();
2246
2247 synchronized (sInstanceCounts) {
2248 final Integer value = sInstanceCounts.get(mKlass);
2249 final int newValue = value != null ? value + 1 : 1;
2250 sInstanceCounts.put(mKlass, newValue);
2251 }
2252 }
2253
2254 @Override
2255 protected void finalize() throws Throwable {
2256 try {
2257 synchronized (sInstanceCounts) {
2258 final Integer value = sInstanceCounts.get(mKlass);
2259 if (value != null) {
2260 final int newValue = value - 1;
2261 if (newValue > 0) {
2262 sInstanceCounts.put(mKlass, newValue);
2263 } else {
2264 sInstanceCounts.remove(mKlass);
2265 }
2266 }
2267 }
2268 } finally {
2269 super.finalize();
2270 }
2271 }
2272
2273 public static int getInstanceCount(Class<?> klass) {
2274 synchronized (sInstanceCounts) {
2275 final Integer value = sInstanceCounts.get(klass);
2276 return value != null ? value : 0;
2277 }
2278 }
2279 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07002280}