blob: 326793903a84a964fcabff7bd352ae046e005062 [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;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070027import android.util.Log;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070028import android.util.Printer;
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -080029import android.util.Singleton;
Brad Fitzpatrick68044332010-11-22 18:19:48 -080030import android.view.IWindowManager;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070031
32import com.android.internal.os.RuntimeInit;
33
34import dalvik.system.BlockGuard;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070035import dalvik.system.CloseGuard;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -080036import dalvik.system.VMDebug;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070037
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070038import java.io.PrintWriter;
39import java.io.StringWriter;
40import java.util.ArrayList;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070041import java.util.HashMap;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -080042import java.util.Map;
Brad Fitzpatrickbee24872010-11-20 12:09:10 -080043import java.util.concurrent.atomic.AtomicInteger;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070044
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070045/**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070046 * <p>StrictMode is a developer tool which detects things you might be
47 * doing by accident and brings them to your attention so you can fix
48 * them.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070049 *
50 * <p>StrictMode is most commonly used to catch accidental disk or
51 * network access on the application's main thread, where UI
52 * operations are received and animations take place. Keeping disk
53 * and network operations off the main thread makes for much smoother,
Brad Fitzpatrick9fc2fc52010-10-11 12:52:35 -070054 * more responsive applications. By keeping your application's main thread
55 * responsive, you also prevent
56 * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
57 * from being shown to users.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070058 *
59 * <p class="note">Note that even though an Android device's disk is
60 * often on flash memory, many devices run a filesystem on top of that
61 * memory with very limited concurrency. It's often the case that
62 * almost all disk accesses are fast, but may in individual cases be
63 * dramatically slower when certain I/O is happening in the background
64 * from other processes. If possible, it's best to assume that such
65 * things are not fast.</p>
66 *
67 * <p>Example code to enable from early in your
68 * {@link android.app.Application}, {@link android.app.Activity}, or
69 * other application component's
70 * {@link android.app.Application#onCreate} method:
71 *
72 * <pre>
73 * public void onCreate() {
74 * if (DEVELOPER_MODE) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070075 * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
76 * .detectDiskReads()
77 * .detectDiskWrites()
78 * .detectNetwork() // or .detectAll() for all detectable problems
79 * .penaltyLog()
80 * .build());
81 * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -070082 * .detectLeakedSqlLiteObjects()
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070083 * .detectLeakedClosableObjects()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070084 * .penaltyLog()
85 * .penaltyDeath()
86 * .build());
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070087 * }
88 * super.onCreate();
89 * }
90 * </pre>
91 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070092 * <p>You can decide what should happen when a violation is detected.
93 * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can
94 * watch the output of <code>adb logcat</code> while you use your
95 * application to see the violations as they happen.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070096 *
97 * <p>If you find violations that you feel are problematic, there are
98 * a variety of tools to help solve them: threads, {@link android.os.Handler},
99 * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
100 * But don't feel compelled to fix everything that StrictMode finds. In particular,
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700101 * many cases of disk access are often necessary during the normal activity lifecycle. Use
102 * StrictMode to find things you did by accident. Network requests on the UI thread
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700103 * are almost always a problem, though.
104 *
105 * <p class="note">StrictMode is not a security mechanism and is not
106 * guaranteed to find all disk or network accesses. While it does
107 * propagate its state across process boundaries when doing
108 * {@link android.os.Binder} calls, it's still ultimately a best
109 * effort mechanism. Notably, disk or network access from JNI calls
110 * won't necessarily trigger it. Future versions of Android may catch
111 * more (or fewer) operations, so you should never leave StrictMode
Dirk Dougherty4d7bc6552012-01-27 17:56:49 -0800112 * enabled in applications distributed on Google Play.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700113 */
114public final class StrictMode {
115 private static final String TAG = "StrictMode";
Brad Fitzpatrick82829ef2010-11-18 18:25:08 -0800116 private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700117
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -0800118 private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800119 private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE);
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -0800120
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800121 /**
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700122 * Boolean system property to disable strict mode checks outright.
123 * Set this to 'true' to force disable; 'false' has no effect on other
124 * enable/disable policy.
125 * @hide
126 */
127 public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
128
129 /**
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800130 * The boolean system property to control screen flashes on violations.
131 *
132 * @hide
133 */
134 public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
135
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700136 // Only log a duplicate stack trace to the logs every second.
137 private static final long MIN_LOG_INTERVAL_MS = 1000;
138
139 // Only show an annoying dialog at most every 30 seconds
140 private static final long MIN_DIALOG_INTERVAL_MS = 30000;
141
Brad Fitzpatricke7520d82010-11-10 18:08:36 -0800142 // How many Span tags (e.g. animations) to report.
143 private static final int MAX_SPAN_TAGS = 20;
144
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -0700145 // How many offending stacks to keep track of (and time) per loop
146 // of the Looper.
147 private static final int MAX_OFFENSES_PER_LOOP = 10;
148
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700149 // Thread-policy:
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700150
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700151 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700152 * @hide
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700153 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700154 public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700155
156 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700157 * @hide
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700158 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700159 public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700160
161 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700162 * @hide
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700163 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700164 public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700165
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800166 /**
167 * For StrictMode.noteSlowCall()
168 *
169 * @hide
170 */
171 public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy
172
173 private static final int ALL_THREAD_DETECT_BITS =
174 DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM;
175
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700176 // Process-policy:
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700177
178 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700179 * Note, a "VM_" bit, not thread.
180 * @hide
181 */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800182 public static final int DETECT_VM_CURSOR_LEAKS = 0x200; // for VmPolicy
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700183
184 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700185 * Note, a "VM_" bit, not thread.
186 * @hide
187 */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800188 public static final int DETECT_VM_CLOSABLE_LEAKS = 0x400; // for VmPolicy
189
190 /**
191 * Note, a "VM_" bit, not thread.
192 * @hide
193 */
194 public static final int DETECT_VM_ACTIVITY_LEAKS = 0x800; // for VmPolicy
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700195
196 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700197 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700198 */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800199 private static final int DETECT_VM_INSTANCE_LEAKS = 0x1000; // for VmPolicy
200
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800201 /**
202 * @hide
203 */
204 public static final int DETECT_VM_REGISTRATION_LEAKS = 0x2000; // for VmPolicy
205
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700206 /**
207 * @hide
208 */
209 private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x4000; // for VmPolicy
210
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800211 private static final int ALL_VM_DETECT_BITS =
212 DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800213 DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700214 DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800215
216 /**
217 * @hide
218 */
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700219 public static final int PENALTY_LOG = 0x10; // normal android.util.Log
220
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700221 // Used for both process and thread policy:
222
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700223 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700224 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700225 */
226 public static final int PENALTY_DIALOG = 0x20;
227
228 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700229 * Death on any detected violation.
230 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700231 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700232 */
233 public static final int PENALTY_DEATH = 0x40;
234
235 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700236 * Death just for detected network usage.
237 *
238 * @hide
239 */
240 public static final int PENALTY_DEATH_ON_NETWORK = 0x200;
241
242 /**
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800243 * Flash the screen during violations.
244 *
245 * @hide
246 */
247 public static final int PENALTY_FLASH = 0x800;
248
249 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700250 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700251 */
252 public static final int PENALTY_DROPBOX = 0x80;
253
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700254 /**
255 * Non-public penalty mode which overrides all the other penalty
256 * bits and signals that we're in a Binder call and we should
257 * ignore the other penalty bits and instead serialize back all
258 * our offending stack traces to the caller to ultimately handle
259 * in the originating process.
260 *
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700261 * This must be kept in sync with the constant in libs/binder/Parcel.cpp
262 *
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700263 * @hide
264 */
265 public static final int PENALTY_GATHER = 0x100;
266
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700267 /**
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800268 * Mask of all the penalty bits valid for thread policies.
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700269 */
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800270 private static final int THREAD_PENALTY_MASK =
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700271 PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800272 PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700273
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800274
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800275 /**
276 * Mask of all the penalty bits valid for VM policies.
277 */
278 private static final int VM_PENALTY_MASK =
279 PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX;
280
281
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800282 // TODO: wrap in some ImmutableHashMap thing.
283 // Note: must be before static initialization of sVmPolicy.
284 private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP = new HashMap<Class, Integer>();
285
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700286 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700287 * The current VmPolicy in effect.
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800288 *
289 * TODO: these are redundant (mask is in VmPolicy). Should remove sVmPolicyMask.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700290 */
291 private static volatile int sVmPolicyMask = 0;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800292 private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700293
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800294 /**
295 * The number of threads trying to do an async dropbox write.
296 * Just to limit ourselves out of paranoia.
297 */
298 private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
299
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700300 private StrictMode() {}
301
302 /**
303 * {@link StrictMode} policy applied to a certain thread.
304 *
305 * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy
306 * can be retrieved with {@link #getThreadPolicy}.
307 *
308 * <p>Note that multiple penalties may be provided and they're run
309 * in order from least to most severe (logging before process
310 * death, for example). There's currently no mechanism to choose
311 * different penalties for different detected actions.
312 */
313 public static final class ThreadPolicy {
314 /**
315 * The default, lax policy which doesn't catch anything.
316 */
317 public static final ThreadPolicy LAX = new ThreadPolicy(0);
318
319 final int mask;
320
321 private ThreadPolicy(int mask) {
322 this.mask = mask;
323 }
324
325 @Override
326 public String toString() {
327 return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
328 }
329
330 /**
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800331 * Creates {@link ThreadPolicy} instances. Methods whose names start
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700332 * with {@code detect} specify what problems we should look
333 * for. Methods whose names start with {@code penalty} specify what
334 * we should do when we detect a problem.
335 *
336 * <p>You can call as many {@code detect} and {@code penalty}
337 * methods as you like. Currently order is insignificant: all
338 * penalties apply to all detected problems.
339 *
340 * <p>For example, detect everything and log anything that's found:
341 * <pre>
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800342 * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700343 * .detectAll()
344 * .penaltyLog()
345 * .build();
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800346 * StrictMode.setThreadPolicy(policy);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700347 * </pre>
348 */
349 public static final class Builder {
350 private int mMask = 0;
351
352 /**
353 * Create a Builder that detects nothing and has no
354 * violations. (but note that {@link #build} will default
355 * to enabling {@link #penaltyLog} if no other penalties
356 * are specified)
357 */
358 public Builder() {
359 mMask = 0;
360 }
361
362 /**
363 * Initialize a Builder from an existing ThreadPolicy.
364 */
365 public Builder(ThreadPolicy policy) {
366 mMask = policy.mask;
367 }
368
369 /**
370 * Detect everything that's potentially suspect.
371 *
372 * <p>As of the Gingerbread release this includes network and
373 * disk operations but will likely expand in future releases.
374 */
375 public Builder detectAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800376 return enable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700377 }
378
379 /**
380 * Disable the detection of everything.
381 */
382 public Builder permitAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800383 return disable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700384 }
385
386 /**
387 * Enable detection of network operations.
388 */
389 public Builder detectNetwork() {
390 return enable(DETECT_NETWORK);
391 }
392
393 /**
394 * Disable detection of network operations.
395 */
396 public Builder permitNetwork() {
397 return disable(DETECT_NETWORK);
398 }
399
400 /**
401 * Enable detection of disk reads.
402 */
403 public Builder detectDiskReads() {
404 return enable(DETECT_DISK_READ);
405 }
406
407 /**
408 * Disable detection of disk reads.
409 */
410 public Builder permitDiskReads() {
411 return disable(DETECT_DISK_READ);
412 }
413
414 /**
Qi Wang097fbf22012-07-13 09:26:03 +0800415 * Enable detection of slow calls.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800416 */
417 public Builder detectCustomSlowCalls() {
418 return enable(DETECT_CUSTOM);
419 }
420
421 /**
Qi Wang097fbf22012-07-13 09:26:03 +0800422 * Disable detection of slow calls.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800423 */
424 public Builder permitCustomSlowCalls() {
Qi Wang097fbf22012-07-13 09:26:03 +0800425 return disable(DETECT_CUSTOM);
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800426 }
427
428 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700429 * Enable detection of disk writes.
430 */
431 public Builder detectDiskWrites() {
432 return enable(DETECT_DISK_WRITE);
433 }
434
435 /**
436 * Disable detection of disk writes.
437 */
438 public Builder permitDiskWrites() {
439 return disable(DETECT_DISK_WRITE);
440 }
441
442 /**
443 * Show an annoying dialog to the developer on detected
444 * violations, rate-limited to be only a little annoying.
445 */
446 public Builder penaltyDialog() {
447 return enable(PENALTY_DIALOG);
448 }
449
450 /**
451 * Crash the whole process on violation. This penalty runs at
452 * the end of all enabled penalties so you'll still get
453 * see logging or other violations before the process dies.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700454 *
455 * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies
456 * to disk reads, disk writes, and network usage if their
457 * corresponding detect flags are set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700458 */
459 public Builder penaltyDeath() {
460 return enable(PENALTY_DEATH);
461 }
462
463 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700464 * Crash the whole process on any network usage. Unlike
465 * {@link #penaltyDeath}, this penalty runs
466 * <em>before</em> anything else. You must still have
467 * called {@link #detectNetwork} to enable this.
468 *
469 * <p>In the Honeycomb or later SDKs, this is on by default.
470 */
471 public Builder penaltyDeathOnNetwork() {
472 return enable(PENALTY_DEATH_ON_NETWORK);
473 }
474
475 /**
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800476 * Flash the screen during a violation.
477 */
478 public Builder penaltyFlashScreen() {
479 return enable(PENALTY_FLASH);
480 }
481
482 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700483 * Log detected violations to the system log.
484 */
485 public Builder penaltyLog() {
486 return enable(PENALTY_LOG);
487 }
488
489 /**
490 * Enable detected violations log a stacktrace and timing data
491 * to the {@link android.os.DropBoxManager DropBox} on policy
492 * violation. Intended mostly for platform integrators doing
493 * beta user field data collection.
494 */
495 public Builder penaltyDropBox() {
496 return enable(PENALTY_DROPBOX);
497 }
498
499 private Builder enable(int bit) {
500 mMask |= bit;
501 return this;
502 }
503
504 private Builder disable(int bit) {
505 mMask &= ~bit;
506 return this;
507 }
508
509 /**
510 * Construct the ThreadPolicy instance.
511 *
512 * <p>Note: if no penalties are enabled before calling
513 * <code>build</code>, {@link #penaltyLog} is implicitly
514 * set.
515 */
516 public ThreadPolicy build() {
517 // If there are detection bits set but no violation bits
518 // set, enable simple logging.
519 if (mMask != 0 &&
520 (mMask & (PENALTY_DEATH | PENALTY_LOG |
521 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
522 penaltyLog();
523 }
524 return new ThreadPolicy(mMask);
525 }
526 }
527 }
528
529 /**
530 * {@link StrictMode} policy applied to all threads in the virtual machine's process.
531 *
532 * <p>The policy is enabled by {@link #setVmPolicy}.
533 */
534 public static final class VmPolicy {
535 /**
536 * The default, lax policy which doesn't catch anything.
537 */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800538 public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700539
540 final int mask;
541
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800542 // Map from class to max number of allowed instances in memory.
543 final HashMap<Class, Integer> classInstanceLimit;
544
545 private VmPolicy(int mask, HashMap<Class, Integer> classInstanceLimit) {
546 if (classInstanceLimit == null) {
547 throw new NullPointerException("classInstanceLimit == null");
548 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700549 this.mask = mask;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800550 this.classInstanceLimit = classInstanceLimit;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700551 }
552
553 @Override
554 public String toString() {
555 return "[StrictMode.VmPolicy; mask=" + mask + "]";
556 }
557
558 /**
559 * Creates {@link VmPolicy} instances. Methods whose names start
560 * with {@code detect} specify what problems we should look
561 * for. Methods whose names start with {@code penalty} specify what
562 * we should do when we detect a problem.
563 *
564 * <p>You can call as many {@code detect} and {@code penalty}
565 * methods as you like. Currently order is insignificant: all
566 * penalties apply to all detected problems.
567 *
568 * <p>For example, detect everything and log anything that's found:
569 * <pre>
570 * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
571 * .detectAll()
572 * .penaltyLog()
573 * .build();
574 * StrictMode.setVmPolicy(policy);
575 * </pre>
576 */
577 public static final class Builder {
578 private int mMask;
579
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800580 private HashMap<Class, Integer> mClassInstanceLimit; // null until needed
581 private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write
582
583 public Builder() {
584 mMask = 0;
585 }
586
587 /**
588 * Build upon an existing VmPolicy.
589 */
590 public Builder(VmPolicy base) {
591 mMask = base.mask;
592 mClassInstanceLimitNeedCow = true;
593 mClassInstanceLimit = base.classInstanceLimit;
594 }
595
596 /**
597 * Set an upper bound on how many instances of a class can be in memory
598 * at once. Helps to prevent object leaks.
599 */
600 public Builder setClassInstanceLimit(Class klass, int instanceLimit) {
601 if (klass == null) {
602 throw new NullPointerException("klass == null");
603 }
604 if (mClassInstanceLimitNeedCow) {
605 if (mClassInstanceLimit.containsKey(klass) &&
606 mClassInstanceLimit.get(klass) == instanceLimit) {
607 // no-op; don't break COW
608 return this;
609 }
610 mClassInstanceLimitNeedCow = false;
611 mClassInstanceLimit = (HashMap<Class, Integer>) mClassInstanceLimit.clone();
612 } else if (mClassInstanceLimit == null) {
613 mClassInstanceLimit = new HashMap<Class, Integer>();
614 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800615 mMask |= DETECT_VM_INSTANCE_LEAKS;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800616 mClassInstanceLimit.put(klass, instanceLimit);
617 return this;
618 }
619
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800620 /**
621 * Detect leaks of {@link android.app.Activity} subclasses.
622 */
623 public Builder detectActivityLeaks() {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800624 return enable(DETECT_VM_ACTIVITY_LEAKS);
625 }
626
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700627 /**
628 * Detect everything that's potentially suspect.
629 *
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700630 * <p>In the Honeycomb release this includes leaks of
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800631 * SQLite cursors, Activities, and other closable objects
632 * but will likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700633 */
634 public Builder detectAll() {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800635 return enable(DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700636 | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS
637 | DETECT_VM_FILE_URI_EXPOSURE);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700638 }
639
640 /**
641 * Detect when an
642 * {@link android.database.sqlite.SQLiteCursor} or other
643 * SQLite object is finalized without having been closed.
644 *
645 * <p>You always want to explicitly close your SQLite
646 * cursors to avoid unnecessary database contention and
647 * temporary memory leaks.
648 */
649 public Builder detectLeakedSqlLiteObjects() {
650 return enable(DETECT_VM_CURSOR_LEAKS);
651 }
652
653 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700654 * Detect when an {@link java.io.Closeable} or other
655 * object with a explict termination method is finalized
656 * without having been closed.
657 *
658 * <p>You always want to explicitly close such objects to
659 * avoid unnecessary resources leaks.
660 */
661 public Builder detectLeakedClosableObjects() {
662 return enable(DETECT_VM_CLOSABLE_LEAKS);
663 }
664
665 /**
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800666 * Detect when a {@link BroadcastReceiver} or
667 * {@link ServiceConnection} is leaked during {@link Context}
668 * teardown.
669 */
670 public Builder detectLeakedRegistrationObjects() {
671 return enable(DETECT_VM_REGISTRATION_LEAKS);
672 }
673
674 /**
Ying Wang0fa30372013-04-03 22:57:31 -0700675 * Detect when a {@code file://} {@link android.net.Uri} is exposed beyond this
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700676 * app. The receiving app may not have access to the sent path.
677 * Instead, when sharing files between apps, {@code content://}
678 * should be used with permission grants.
679 */
680 public Builder detectFileUriExposure() {
681 return enable(DETECT_VM_FILE_URI_EXPOSURE);
682 }
683
684 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700685 * Crashes the whole process on violation. This penalty runs at
686 * the end of all enabled penalties so yo you'll still get
687 * your logging or other violations before the process dies.
688 */
689 public Builder penaltyDeath() {
690 return enable(PENALTY_DEATH);
691 }
692
693 /**
694 * Log detected violations to the system log.
695 */
696 public Builder penaltyLog() {
697 return enable(PENALTY_LOG);
698 }
699
700 /**
701 * Enable detected violations log a stacktrace and timing data
702 * to the {@link android.os.DropBoxManager DropBox} on policy
703 * violation. Intended mostly for platform integrators doing
704 * beta user field data collection.
705 */
706 public Builder penaltyDropBox() {
707 return enable(PENALTY_DROPBOX);
708 }
709
710 private Builder enable(int bit) {
711 mMask |= bit;
712 return this;
713 }
714
715 /**
716 * Construct the VmPolicy instance.
717 *
718 * <p>Note: if no penalties are enabled before calling
719 * <code>build</code>, {@link #penaltyLog} is implicitly
720 * set.
721 */
722 public VmPolicy build() {
723 // If there are detection bits set but no violation bits
724 // set, enable simple logging.
725 if (mMask != 0 &&
726 (mMask & (PENALTY_DEATH | PENALTY_LOG |
727 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
728 penaltyLog();
729 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800730 return new VmPolicy(mMask,
731 mClassInstanceLimit != null ? mClassInstanceLimit : EMPTY_CLASS_LIMIT_MAP);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700732 }
733 }
734 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700735
736 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700737 * Log of strict mode violation stack traces that have occurred
738 * during a Binder call, to be serialized back later to the caller
739 * via Parcel.writeNoException() (amusingly) where the caller can
740 * choose how to react.
741 */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -0700742 private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
743 new ThreadLocal<ArrayList<ViolationInfo>>() {
744 @Override protected ArrayList<ViolationInfo> initialValue() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700745 // Starts null to avoid unnecessary allocations when
746 // checking whether there are any violations or not in
747 // hasGatheredViolations() below.
748 return null;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700749 }
750 };
751
752 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700753 * Sets the policy for what actions on the current thread should
754 * be detected, as well as the penalty if such actions occur.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700755 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700756 * <p>Internally this sets a thread-local variable which is
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700757 * propagated across cross-process IPC calls, meaning you can
758 * catch violations when a system service or another process
759 * accesses the disk or network on your behalf.
760 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700761 * @param policy the policy to put into place
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700762 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700763 public static void setThreadPolicy(final ThreadPolicy policy) {
764 setThreadPolicyMask(policy.mask);
765 }
766
767 private static void setThreadPolicyMask(final int policyMask) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700768 // In addition to the Java-level thread-local in Dalvik's
769 // BlockGuard, we also need to keep a native thread-local in
770 // Binder in order to propagate the value across Binder calls,
771 // even across native-only processes. The two are kept in
772 // sync via the callback to onStrictModePolicyChange, below.
773 setBlockGuardPolicy(policyMask);
774
775 // And set the Android native version...
776 Binder.setThreadStrictModePolicy(policyMask);
777 }
778
779 // Sets the policy in Dalvik/libcore (BlockGuard)
780 private static void setBlockGuardPolicy(final int policyMask) {
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700781 if (policyMask == 0) {
782 BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
783 return;
784 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700785 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
786 if (!(policy instanceof AndroidBlockGuardPolicy)) {
787 BlockGuard.setThreadPolicy(new AndroidBlockGuardPolicy(policyMask));
788 } else {
789 AndroidBlockGuardPolicy androidPolicy = (AndroidBlockGuardPolicy) policy;
790 androidPolicy.setPolicyMask(policyMask);
791 }
792 }
793
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -0800794 // Sets up CloseGuard in Dalvik/libcore
795 private static void setCloseGuardEnabled(boolean enabled) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -0800796 if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -0800797 CloseGuard.setReporter(new AndroidCloseGuardReporter());
798 }
799 CloseGuard.setEnabled(enabled);
800 }
801
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800802 /**
803 * @hide
804 */
805 public static class StrictModeViolation extends BlockGuard.BlockGuardPolicyException {
806 public StrictModeViolation(int policyState, int policyViolated, String message) {
807 super(policyState, policyViolated, message);
808 }
809 }
810
811 /**
812 * @hide
813 */
814 public static class StrictModeNetworkViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700815 public StrictModeNetworkViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800816 super(policyMask, DETECT_NETWORK, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700817 }
818 }
819
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800820 /**
821 * @hide
822 */
823 private static class StrictModeDiskReadViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700824 public StrictModeDiskReadViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800825 super(policyMask, DETECT_DISK_READ, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700826 }
827 }
828
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800829 /**
830 * @hide
831 */
832 private static class StrictModeDiskWriteViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700833 public StrictModeDiskWriteViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800834 super(policyMask, DETECT_DISK_WRITE, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700835 }
836 }
837
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -0800838 /**
839 * @hide
840 */
841 private static class StrictModeCustomViolation extends StrictModeViolation {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800842 public StrictModeCustomViolation(int policyMask, String name) {
843 super(policyMask, DETECT_CUSTOM, name);
844 }
845 }
846
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700847 /**
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700848 * Returns the bitmask of the current thread's policy.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700849 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700850 * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
851 *
852 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700853 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700854 public static int getThreadPolicyMask() {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700855 return BlockGuard.getThreadPolicy().getPolicyMask();
856 }
857
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700858 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700859 * Returns the current thread's policy.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700860 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700861 public static ThreadPolicy getThreadPolicy() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800862 // TODO: this was a last minute Gingerbread API change (to
863 // introduce VmPolicy cleanly) but this isn't particularly
864 // optimal for users who might call this method often. This
865 // should be in a thread-local and not allocate on each call.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700866 return new ThreadPolicy(getThreadPolicyMask());
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700867 }
868
869 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700870 * A convenience wrapper that takes the current
871 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
872 * to permit both disk reads &amp; writes, and sets the new policy
873 * with {@link #setThreadPolicy}, returning the old policy so you
874 * can restore it at the end of a block.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700875 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700876 * @return the old policy, to be passed to {@link #setThreadPolicy} to
877 * restore the policy at the end of a block
878 */
879 public static ThreadPolicy allowThreadDiskWrites() {
880 int oldPolicyMask = getThreadPolicyMask();
881 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
882 if (newPolicyMask != oldPolicyMask) {
883 setThreadPolicyMask(newPolicyMask);
884 }
885 return new ThreadPolicy(oldPolicyMask);
886 }
887
888 /**
889 * A convenience wrapper that takes the current
890 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
891 * to permit disk reads, and sets the new policy
892 * with {@link #setThreadPolicy}, returning the old policy so you
893 * can restore it at the end of a block.
894 *
895 * @return the old policy, to be passed to setThreadPolicy to
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700896 * restore the policy.
897 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700898 public static ThreadPolicy allowThreadDiskReads() {
899 int oldPolicyMask = getThreadPolicyMask();
900 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
901 if (newPolicyMask != oldPolicyMask) {
902 setThreadPolicyMask(newPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700903 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700904 return new ThreadPolicy(oldPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700905 }
906
Brad Fitzpatrickf5454592010-11-24 15:27:51 -0800907 // We don't want to flash the screen red in the system server
908 // process, nor do we want to modify all the call sites of
909 // conditionallyEnableDebugLogging() in the system server,
910 // so instead we use this to determine if we are the system server.
911 private static boolean amTheSystemServerProcess() {
912 // Fast path. Most apps don't have the system server's UID.
913 if (Process.myUid() != Process.SYSTEM_UID) {
914 return false;
915 }
916
917 // The settings app, though, has the system server's UID so
918 // look up our stack to see if we came from the system server.
919 Throwable stack = new Throwable();
920 stack.fillInStackTrace();
921 for (StackTraceElement ste : stack.getStackTrace()) {
922 String clsName = ste.getClassName();
923 if (clsName != null && clsName.startsWith("com.android.server.")) {
924 return true;
925 }
926 }
927 return false;
928 }
929
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -0700930 /**
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -0700931 * Enable DropBox logging for debug phone builds.
932 *
933 * @hide
934 */
935 public static boolean conditionallyEnableDebugLogging() {
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700936 boolean doFlashes = SystemProperties.getBoolean(VISUAL_PROPERTY, false)
937 && !amTheSystemServerProcess();
938 final boolean suppress = SystemProperties.getBoolean(DISABLE_PROPERTY, false);
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800939
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -0700940 // For debug builds, log event loop stalls to dropbox for analysis.
941 // Similar logic also appears in ActivityThread.java for system apps.
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700942 if (!doFlashes && (IS_USER_BUILD || suppress)) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -0800943 setCloseGuardEnabled(false);
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -0700944 return false;
945 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800946
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700947 // Eng builds have flashes on all the time. The suppression property
948 // overrides this, so we force the behavior only after the short-circuit
949 // check above.
950 if (IS_ENG_BUILD) {
951 doFlashes = true;
952 }
953
Jeff Brownbe7c29c2011-10-11 11:35:23 -0700954 // Thread policy controls BlockGuard.
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800955 int threadPolicyMask = StrictMode.DETECT_DISK_WRITE |
956 StrictMode.DETECT_DISK_READ |
957 StrictMode.DETECT_NETWORK;
958
959 if (!IS_USER_BUILD) {
960 threadPolicyMask |= StrictMode.PENALTY_DROPBOX;
961 }
962 if (doFlashes) {
963 threadPolicyMask |= StrictMode.PENALTY_FLASH;
964 }
965
966 StrictMode.setThreadPolicyMask(threadPolicyMask);
967
Jeff Brownbe7c29c2011-10-11 11:35:23 -0700968 // VM Policy controls CloseGuard, detection of Activity leaks,
969 // and instance counting.
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800970 if (IS_USER_BUILD) {
971 setCloseGuardEnabled(false);
972 } else {
Jeff Brownd5875d92011-10-09 14:59:37 -0700973 VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll().penaltyDropBox();
974 if (IS_ENG_BUILD) {
975 policyBuilder.penaltyLog();
976 }
977 setVmPolicy(policyBuilder.build());
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800978 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
979 }
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -0700980 return true;
981 }
982
983 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700984 * Used by the framework to make network usage on the main
985 * thread a fatal error.
986 *
987 * @hide
988 */
989 public static void enableDeathOnNetwork() {
990 int oldPolicy = getThreadPolicyMask();
991 int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
992 setThreadPolicyMask(newPolicy);
993 }
994
995 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700996 * Parses the BlockGuard policy mask out from the Exception's
997 * getMessage() String value. Kinda gross, but least
998 * invasive. :/
999 *
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001000 * Input is of the following forms:
1001 * "policy=137 violation=64"
1002 * "policy=137 violation=64 msg=Arbitrary text"
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001003 *
1004 * Returns 0 on failure, which is a valid policy, but not a
1005 * valid policy during a violation (else there must've been
1006 * some policy in effect to violate).
1007 */
1008 private static int parsePolicyFromMessage(String message) {
1009 if (message == null || !message.startsWith("policy=")) {
1010 return 0;
1011 }
1012 int spaceIndex = message.indexOf(' ');
1013 if (spaceIndex == -1) {
1014 return 0;
1015 }
1016 String policyString = message.substring(7, spaceIndex);
1017 try {
1018 return Integer.valueOf(policyString).intValue();
1019 } catch (NumberFormatException e) {
1020 return 0;
1021 }
1022 }
1023
1024 /**
1025 * Like parsePolicyFromMessage(), but returns the violation.
1026 */
1027 private static int parseViolationFromMessage(String message) {
1028 if (message == null) {
1029 return 0;
1030 }
1031 int violationIndex = message.indexOf("violation=");
1032 if (violationIndex == -1) {
1033 return 0;
1034 }
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001035 int numberStartIndex = violationIndex + "violation=".length();
1036 int numberEndIndex = message.indexOf(' ', numberStartIndex);
1037 if (numberEndIndex == -1) {
1038 numberEndIndex = message.length();
1039 }
1040 String violationString = message.substring(numberStartIndex, numberEndIndex);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001041 try {
1042 return Integer.valueOf(violationString).intValue();
1043 } catch (NumberFormatException e) {
1044 return 0;
1045 }
1046 }
1047
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001048 private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
1049 new ThreadLocal<ArrayList<ViolationInfo>>() {
1050 @Override protected ArrayList<ViolationInfo> initialValue() {
1051 return new ArrayList<ViolationInfo>();
1052 }
1053 };
1054
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001055 // Note: only access this once verifying the thread has a Looper.
1056 private static final ThreadLocal<Handler> threadHandler = new ThreadLocal<Handler>() {
1057 @Override protected Handler initialValue() {
1058 return new Handler();
1059 }
1060 };
1061
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001062 private static boolean tooManyViolationsThisLoop() {
1063 return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
1064 }
1065
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001066 private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
1067 private int mPolicyMask;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001068
1069 // Map from violation stacktrace hashcode -> uptimeMillis of
1070 // last violation. No locking needed, as this is only
1071 // accessed by the same thread.
1072 private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>();
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001073
1074 public AndroidBlockGuardPolicy(final int policyMask) {
1075 mPolicyMask = policyMask;
1076 }
1077
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001078 @Override
1079 public String toString() {
1080 return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
1081 }
1082
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001083 // Part of BlockGuard.Policy interface:
1084 public int getPolicyMask() {
1085 return mPolicyMask;
1086 }
1087
1088 // Part of BlockGuard.Policy interface:
1089 public void onWriteToDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001090 if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001091 return;
1092 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001093 if (tooManyViolationsThisLoop()) {
1094 return;
1095 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001096 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
1097 e.fillInStackTrace();
1098 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001099 }
1100
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001101 // Not part of BlockGuard.Policy; just part of StrictMode:
1102 void onCustomSlowCall(String name) {
1103 if ((mPolicyMask & DETECT_CUSTOM) == 0) {
1104 return;
1105 }
1106 if (tooManyViolationsThisLoop()) {
1107 return;
1108 }
1109 BlockGuard.BlockGuardPolicyException e = new StrictModeCustomViolation(mPolicyMask, name);
1110 e.fillInStackTrace();
1111 startHandlingViolationException(e);
1112 }
1113
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001114 // Part of BlockGuard.Policy interface:
1115 public void onReadFromDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001116 if ((mPolicyMask & DETECT_DISK_READ) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001117 return;
1118 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001119 if (tooManyViolationsThisLoop()) {
1120 return;
1121 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001122 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
1123 e.fillInStackTrace();
1124 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001125 }
1126
1127 // Part of BlockGuard.Policy interface:
1128 public void onNetwork() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001129 if ((mPolicyMask & DETECT_NETWORK) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001130 return;
1131 }
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001132 if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
1133 throw new NetworkOnMainThreadException();
1134 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001135 if (tooManyViolationsThisLoop()) {
1136 return;
1137 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001138 BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
1139 e.fillInStackTrace();
1140 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001141 }
1142
1143 public void setPolicyMask(int policyMask) {
1144 mPolicyMask = policyMask;
1145 }
1146
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001147 // Start handling a violation that just started and hasn't
1148 // actually run yet (e.g. no disk write or network operation
1149 // has yet occurred). This sees if we're in an event loop
1150 // thread and, if so, uses it to roughly measure how long the
1151 // violation took.
1152 void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001153 final ViolationInfo info = new ViolationInfo(e, e.getPolicy());
1154 info.violationUptimeMillis = SystemClock.uptimeMillis();
1155 handleViolationWithTimingAttempt(info);
1156 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001157
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001158 // Attempts to fill in the provided ViolationInfo's
1159 // durationMillis field if this thread has a Looper we can use
1160 // to measure with. We measure from the time of violation
1161 // until the time the looper is idle again (right before
1162 // the next epoll_wait)
1163 void handleViolationWithTimingAttempt(final ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001164 Looper looper = Looper.myLooper();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001165
1166 // Without a Looper, we're unable to time how long the
1167 // violation takes place. This case should be rare, as
1168 // most users will care about timing violations that
1169 // happen on their main UI thread. Note that this case is
1170 // also hit when a violation takes place in a Binder
1171 // thread, in "gather" mode. In this case, the duration
1172 // of the violation is computed by the ultimate caller and
1173 // its Looper, if any.
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001174 //
1175 // Also, as a special short-cut case when the only penalty
1176 // bit is death, we die immediately, rather than timing
1177 // the violation's duration. This makes it convenient to
1178 // use in unit tests too, rather than waiting on a Looper.
1179 //
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001180 // TODO: if in gather mode, ignore Looper.myLooper() and always
1181 // go into this immediate mode?
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001182 if (looper == null ||
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001183 (info.policy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001184 info.durationMillis = -1; // unknown (redundant, already set)
1185 handleViolation(info);
1186 return;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001187 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001188
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001189 final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001190 if (records.size() >= MAX_OFFENSES_PER_LOOP) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001191 // Not worth measuring. Too many offenses in one loop.
1192 return;
1193 }
1194 records.add(info);
1195 if (records.size() > 1) {
1196 // There's already been a violation this loop, so we've already
1197 // registered an idle handler to process the list of violations
1198 // at the end of this Looper's loop.
1199 return;
1200 }
1201
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001202 final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ?
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08001203 sWindowManager.get() : null;
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001204 if (windowManager != null) {
1205 try {
1206 windowManager.showStrictModeViolation(true);
1207 } catch (RemoteException unused) {
1208 }
1209 }
1210
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001211 // We post a runnable to a Handler (== delay 0 ms) for
1212 // measuring the end time of a violation instead of using
1213 // an IdleHandler (as was previously used) because an
1214 // IdleHandler may not run for quite a long period of time
1215 // if an ongoing animation is happening and continually
1216 // posting ASAP (0 ms) animation steps. Animations are
1217 // throttled back to 60fps via SurfaceFlinger/View
1218 // invalidates, _not_ by posting frame updates every 16
1219 // milliseconds.
Jeff Sharkey3761f332012-03-16 15:46:46 -07001220 threadHandler.get().postAtFrontOfQueue(new Runnable() {
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001221 public void run() {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001222 long loopFinishTime = SystemClock.uptimeMillis();
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001223
1224 // Note: we do this early, before handling the
1225 // violation below, as handling the violation
1226 // may include PENALTY_DEATH and we don't want
1227 // to keep the red border on.
1228 if (windowManager != null) {
1229 try {
1230 windowManager.showStrictModeViolation(false);
1231 } catch (RemoteException unused) {
1232 }
1233 }
1234
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001235 for (int n = 0; n < records.size(); ++n) {
1236 ViolationInfo v = records.get(n);
1237 v.violationNumThisLoop = n + 1;
1238 v.durationMillis =
1239 (int) (loopFinishTime - v.violationUptimeMillis);
1240 handleViolation(v);
1241 }
1242 records.clear();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001243 }
1244 });
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001245 }
1246
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001247 // Note: It's possible (even quite likely) that the
1248 // thread-local policy mask has changed from the time the
1249 // violation fired and now (after the violating code ran) due
1250 // to people who push/pop temporary policy in regions of code,
1251 // hence the policy being passed around.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001252 void handleViolation(final ViolationInfo info) {
1253 if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) {
1254 Log.wtf(TAG, "unexpected null stacktrace");
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001255 return;
1256 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001257
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001258 if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001259
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001260 if ((info.policy & PENALTY_GATHER) != 0) {
1261 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001262 if (violations == null) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001263 violations = new ArrayList<ViolationInfo>(1);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001264 gatheredViolations.set(violations);
1265 } else if (violations.size() >= 5) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001266 // Too many. In a loop or something? Don't gather them all.
1267 return;
1268 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001269 for (ViolationInfo previous : violations) {
1270 if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001271 // Duplicate. Don't log.
1272 return;
1273 }
1274 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001275 violations.add(info);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001276 return;
1277 }
1278
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001279 // Not perfect, but fast and good enough for dup suppression.
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08001280 Integer crashFingerprint = info.hashCode();
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001281 long lastViolationTime = 0;
1282 if (mLastViolationTime.containsKey(crashFingerprint)) {
1283 lastViolationTime = mLastViolationTime.get(crashFingerprint);
1284 }
1285 long now = SystemClock.uptimeMillis();
1286 mLastViolationTime.put(crashFingerprint, now);
1287 long timeSinceLastViolationMillis = lastViolationTime == 0 ?
1288 Long.MAX_VALUE : (now - lastViolationTime);
1289
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001290 if ((info.policy & PENALTY_LOG) != 0 &&
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001291 timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001292 if (info.durationMillis != -1) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001293 Log.d(TAG, "StrictMode policy violation; ~duration=" +
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001294 info.durationMillis + " ms: " + info.crashInfo.stackTrace);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001295 } else {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001296 Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001297 }
1298 }
1299
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001300 // The violationMaskSubset, passed to ActivityManager, is a
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001301 // subset of the original StrictMode policy bitmask, with
1302 // only the bit violated and penalty bits to be executed
1303 // by the ActivityManagerService remaining set.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001304 int violationMaskSubset = 0;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001305
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001306 if ((info.policy & PENALTY_DIALOG) != 0 &&
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001307 timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001308 violationMaskSubset |= PENALTY_DIALOG;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001309 }
1310
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001311 if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
1312 violationMaskSubset |= PENALTY_DROPBOX;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001313 }
1314
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001315 if (violationMaskSubset != 0) {
1316 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1317 violationMaskSubset |= violationBit;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001318 final int savedPolicyMask = getThreadPolicyMask();
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001319
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001320 final boolean justDropBox = (info.policy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001321 if (justDropBox) {
1322 // If all we're going to ask the activity manager
1323 // to do is dropbox it (the common case during
1324 // platform development), we can avoid doing this
1325 // call synchronously which Binder data suggests
1326 // isn't always super fast, despite the implementation
1327 // in the ActivityManager trying to be mostly async.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001328 dropboxViolationAsync(violationMaskSubset, info);
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001329 return;
1330 }
1331
1332 // Normal synchronous call to the ActivityManager.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001333 try {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001334 // First, remove any policy before we call into the Activity Manager,
1335 // otherwise we'll infinite recurse as we try to log policy violations
1336 // to disk, thus violating policy, thus requiring logging, etc...
1337 // We restore the current policy below, in the finally block.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001338 setThreadPolicyMask(0);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001339
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001340 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1341 RuntimeInit.getApplicationObject(),
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001342 violationMaskSubset,
1343 info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001344 } catch (RemoteException e) {
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001345 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001346 } finally {
1347 // Restore the policy.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001348 setThreadPolicyMask(savedPolicyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001349 }
1350 }
1351
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001352 if ((info.policy & PENALTY_DEATH) != 0) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001353 executeDeathPenalty(info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001354 }
1355 }
1356 }
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001357
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001358 private static void executeDeathPenalty(ViolationInfo info) {
1359 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1360 throw new StrictModeViolation(info.policy, violationBit, null);
1361 }
1362
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001363 /**
1364 * In the common case, as set by conditionallyEnableDebugLogging,
1365 * we're just dropboxing any violations but not showing a dialog,
1366 * not loggging, and not killing the process. In these cases we
1367 * don't need to do a synchronous call to the ActivityManager.
1368 * This is used by both per-thread and vm-wide violations when
1369 * applicable.
1370 */
1371 private static void dropboxViolationAsync(
1372 final int violationMaskSubset, final ViolationInfo info) {
1373 int outstanding = sDropboxCallsInFlight.incrementAndGet();
1374 if (outstanding > 20) {
1375 // What's going on? Let's not make make the situation
1376 // worse and just not log.
1377 sDropboxCallsInFlight.decrementAndGet();
1378 return;
1379 }
1380
1381 if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1382
1383 new Thread("callActivityManagerForStrictModeDropbox") {
1384 public void run() {
1385 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1386 try {
Brad Fitzpatrick10656852010-11-23 19:01:13 -08001387 IActivityManager am = ActivityManagerNative.getDefault();
1388 if (am == null) {
1389 Log.d(TAG, "No activity manager; failed to Dropbox violation.");
1390 } else {
1391 am.handleApplicationStrictModeViolation(
1392 RuntimeInit.getApplicationObject(),
1393 violationMaskSubset,
1394 info);
1395 }
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001396 } catch (RemoteException e) {
1397 Log.e(TAG, "RemoteException handling StrictMode violation", e);
1398 }
1399 int outstanding = sDropboxCallsInFlight.decrementAndGet();
1400 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
1401 }
1402 }.start();
1403 }
1404
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001405 private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
1406 public void report (String message, Throwable allocationSite) {
1407 onVmPolicyViolation(message, allocationSite);
1408 }
1409 }
1410
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001411 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001412 * Called from Parcel.writeNoException()
1413 */
1414 /* package */ static boolean hasGatheredViolations() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001415 return gatheredViolations.get() != null;
1416 }
1417
1418 /**
1419 * Called from Parcel.writeException(), so we drop this memory and
1420 * don't incorrectly attribute it to the wrong caller on the next
1421 * Binder call on this thread.
1422 */
1423 /* package */ static void clearGatheredViolations() {
1424 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001425 }
1426
1427 /**
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001428 * @hide
1429 */
1430 public static void conditionallyCheckInstanceCounts() {
1431 VmPolicy policy = getVmPolicy();
1432 if (policy.classInstanceLimit.size() == 0) {
1433 return;
1434 }
1435 Runtime.getRuntime().gc();
1436 // Note: classInstanceLimit is immutable, so this is lock-free
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001437 for (Map.Entry<Class, Integer> entry : policy.classInstanceLimit.entrySet()) {
1438 Class klass = entry.getKey();
1439 int limit = entry.getValue();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001440 long instances = VMDebug.countInstancesOfClass(klass, false);
1441 if (instances <= limit) {
1442 continue;
1443 }
1444 Throwable tr = new InstanceCountViolation(klass, instances, limit);
1445 onVmPolicyViolation(tr.getMessage(), tr);
1446 }
1447 }
1448
1449 private static long sLastInstanceCountCheckMillis = 0;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001450 private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001451 private static final MessageQueue.IdleHandler sProcessIdleHandler =
1452 new MessageQueue.IdleHandler() {
1453 public boolean queueIdle() {
1454 long now = SystemClock.uptimeMillis();
1455 if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1456 sLastInstanceCountCheckMillis = now;
1457 conditionallyCheckInstanceCounts();
1458 }
1459 return true;
1460 }
1461 };
1462
1463 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001464 * Sets the policy for what actions in the VM process (on any
1465 * thread) should be detected, as well as the penalty if such
1466 * actions occur.
1467 *
1468 * @param policy the policy to put into place
1469 */
1470 public static void setVmPolicy(final VmPolicy policy) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001471 synchronized (StrictMode.class) {
1472 sVmPolicy = policy;
1473 sVmPolicyMask = policy.mask;
1474 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001475
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001476 Looper looper = Looper.getMainLooper();
1477 if (looper != null) {
1478 MessageQueue mq = looper.mQueue;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001479 if (policy.classInstanceLimit.size() == 0 ||
1480 (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001481 mq.removeIdleHandler(sProcessIdleHandler);
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001482 sIsIdlerRegistered = false;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001483 } else if (!sIsIdlerRegistered) {
1484 mq.addIdleHandler(sProcessIdleHandler);
1485 sIsIdlerRegistered = true;
1486 }
1487 }
1488 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001489 }
1490
1491 /**
1492 * Gets the current VM policy.
1493 */
1494 public static VmPolicy getVmPolicy() {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001495 synchronized (StrictMode.class) {
1496 return sVmPolicy;
1497 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001498 }
1499
1500 /**
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001501 * Enable the recommended StrictMode defaults, with violations just being logged.
1502 *
1503 * <p>This catches disk and network access on the main thread, as
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001504 * well as leaked SQLite cursors and unclosed resources. This is
1505 * simply a wrapper around {@link #setVmPolicy} and {@link
1506 * #setThreadPolicy}.
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001507 */
1508 public static void enableDefaults() {
1509 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
1510 .detectAll()
1511 .penaltyLog()
1512 .build());
1513 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001514 .detectAll()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001515 .penaltyLog()
1516 .build());
1517 }
1518
1519 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001520 * @hide
1521 */
1522 public static boolean vmSqliteObjectLeaksEnabled() {
1523 return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
1524 }
1525
1526 /**
1527 * @hide
1528 */
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001529 public static boolean vmClosableObjectLeaksEnabled() {
1530 return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
1531 }
1532
1533 /**
1534 * @hide
1535 */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001536 public static boolean vmRegistrationLeaksEnabled() {
1537 return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
1538 }
1539
1540 /**
1541 * @hide
1542 */
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001543 public static boolean vmFileUriExposureEnabled() {
1544 return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
1545 }
1546
1547 /**
1548 * @hide
1549 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001550 public static void onSqliteObjectLeaked(String message, Throwable originStack) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001551 onVmPolicyViolation(message, originStack);
1552 }
1553
Steve Block08d584c2011-05-17 19:05:03 +01001554 /**
1555 * @hide
1556 */
1557 public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
1558 onVmPolicyViolation(null, originStack);
1559 }
1560
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001561 /**
1562 * @hide
1563 */
1564 public static void onIntentReceiverLeaked(Throwable originStack) {
1565 onVmPolicyViolation(null, originStack);
1566 }
1567
1568 /**
1569 * @hide
1570 */
1571 public static void onServiceConnectionLeaked(Throwable originStack) {
1572 onVmPolicyViolation(null, originStack);
1573 }
1574
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001575 /**
1576 * @hide
1577 */
1578 public static void onFileUriExposed(String location) {
1579 final String message = "file:// Uri exposed through " + location;
1580 onVmPolicyViolation(message, new Throwable(message));
1581 }
1582
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001583 // Map from VM violation fingerprint to uptime millis.
1584 private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
1585
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001586 /**
1587 * @hide
1588 */
1589 public static void onVmPolicyViolation(String message, Throwable originStack) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001590 final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
1591 final boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0;
1592 final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
1593 final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
1594
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001595 // Erase stuff not relevant for process-wide violations
1596 info.numAnimationsRunning = 0;
1597 info.tags = null;
1598 info.broadcastIntentAction = null;
1599
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001600 final Integer fingerprint = info.hashCode();
1601 final long now = SystemClock.uptimeMillis();
1602 long lastViolationTime = 0;
1603 long timeSinceLastViolationMillis = Long.MAX_VALUE;
1604 synchronized (sLastVmViolationTime) {
1605 if (sLastVmViolationTime.containsKey(fingerprint)) {
1606 lastViolationTime = sLastVmViolationTime.get(fingerprint);
1607 timeSinceLastViolationMillis = now - lastViolationTime;
1608 }
1609 if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
1610 sLastVmViolationTime.put(fingerprint, now);
1611 }
1612 }
1613
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001614 if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001615 Log.e(TAG, message, originStack);
1616 }
1617
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001618 int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001619
1620 if (penaltyDropbox && !penaltyDeath) {
1621 // Common case for userdebug/eng builds. If no death and
1622 // just dropboxing, we can do the ActivityManager call
1623 // asynchronously.
1624 dropboxViolationAsync(violationMaskSubset, info);
1625 return;
1626 }
1627
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001628 if (penaltyDropbox && lastViolationTime == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001629 // The violationMask, passed to ActivityManager, is a
1630 // subset of the original StrictMode policy bitmask, with
1631 // only the bit violated and penalty bits to be executed
1632 // by the ActivityManagerService remaining set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001633 final int savedPolicyMask = getThreadPolicyMask();
1634 try {
1635 // First, remove any policy before we call into the Activity Manager,
1636 // otherwise we'll infinite recurse as we try to log policy violations
1637 // to disk, thus violating policy, thus requiring logging, etc...
1638 // We restore the current policy below, in the finally block.
1639 setThreadPolicyMask(0);
1640
1641 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
1642 RuntimeInit.getApplicationObject(),
1643 violationMaskSubset,
1644 info);
1645 } catch (RemoteException e) {
1646 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1647 } finally {
1648 // Restore the policy.
1649 setThreadPolicyMask(savedPolicyMask);
1650 }
1651 }
1652
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001653 if (penaltyDeath) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001654 System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
1655 Process.killProcess(Process.myPid());
1656 System.exit(10);
1657 }
1658 }
1659
1660 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001661 * Called from Parcel.writeNoException()
1662 */
1663 /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001664 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001665 if (violations == null) {
1666 p.writeInt(0);
1667 } else {
1668 p.writeInt(violations.size());
1669 for (int i = 0; i < violations.size(); ++i) {
1670 violations.get(i).writeToParcel(p, 0 /* unused flags? */);
1671 }
1672 if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
1673 violations.clear(); // somewhat redundant, as we're about to null the threadlocal
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001674 }
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001675 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001676 }
1677
1678 private static class LogStackTrace extends Exception {}
1679
1680 /**
1681 * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
1682 * we here read back all the encoded violations.
1683 */
1684 /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
1685 // Our own stack trace to append
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001686 StringWriter sw = new StringWriter();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001687 new LogStackTrace().printStackTrace(new PrintWriter(sw));
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001688 String ourStack = sw.toString();
1689
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001690 int policyMask = getThreadPolicyMask();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001691 boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001692
1693 int numViolations = p.readInt();
1694 for (int i = 0; i < numViolations; ++i) {
1695 if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001696 ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
1697 info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001698 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1699 if (policy instanceof AndroidBlockGuardPolicy) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001700 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001701 }
1702 }
1703 }
1704
1705 /**
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001706 * Called from android_util_Binder.cpp's
1707 * android_os_Parcel_enforceInterface when an incoming Binder call
1708 * requires changing the StrictMode policy mask. The role of this
1709 * function is to ask Binder for its current (native) thread-local
1710 * policy value and synchronize it to libcore's (Java)
1711 * thread-local policy value.
1712 */
1713 private static void onBinderStrictModePolicyChange(int newPolicy) {
1714 setBlockGuardPolicy(newPolicy);
1715 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001716
1717 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001718 * A tracked, critical time span. (e.g. during an animation.)
1719 *
1720 * The object itself is a linked list node, to avoid any allocations
1721 * during rapid span entries and exits.
1722 *
1723 * @hide
1724 */
1725 public static class Span {
1726 private String mName;
1727 private long mCreateMillis;
1728 private Span mNext;
1729 private Span mPrev; // not used when in freeList, only active
1730 private final ThreadSpanState mContainerState;
1731
1732 Span(ThreadSpanState threadState) {
1733 mContainerState = threadState;
1734 }
1735
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08001736 // Empty constructor for the NO_OP_SPAN
1737 protected Span() {
1738 mContainerState = null;
1739 }
1740
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001741 /**
1742 * To be called when the critical span is complete (i.e. the
1743 * animation is done animating). This can be called on any
1744 * thread (even a different one from where the animation was
1745 * taking place), but that's only a defensive implementation
1746 * measure. It really makes no sense for you to call this on
1747 * thread other than that where you created it.
1748 *
1749 * @hide
1750 */
1751 public void finish() {
1752 ThreadSpanState state = mContainerState;
1753 synchronized (state) {
1754 if (mName == null) {
1755 // Duplicate finish call. Ignore.
1756 return;
1757 }
1758
1759 // Remove ourselves from the active list.
1760 if (mPrev != null) {
1761 mPrev.mNext = mNext;
1762 }
1763 if (mNext != null) {
1764 mNext.mPrev = mPrev;
1765 }
1766 if (state.mActiveHead == this) {
1767 state.mActiveHead = mNext;
1768 }
1769
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08001770 state.mActiveSize--;
1771
1772 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
1773
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001774 this.mCreateMillis = -1;
1775 this.mName = null;
1776 this.mPrev = null;
1777 this.mNext = null;
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001778
1779 // Add ourselves to the freeList, if it's not already
1780 // too big.
1781 if (state.mFreeListSize < 5) {
1782 this.mNext = state.mFreeListHead;
1783 state.mFreeListHead = this;
1784 state.mFreeListSize++;
1785 }
1786 }
1787 }
1788 }
1789
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08001790 // The no-op span that's used in user builds.
1791 private static final Span NO_OP_SPAN = new Span() {
1792 public void finish() {
1793 // Do nothing.
1794 }
1795 };
1796
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001797 /**
1798 * Linked lists of active spans and a freelist.
1799 *
1800 * Locking notes: there's one of these structures per thread and
1801 * all members of this structure (as well as the Span nodes under
1802 * it) are guarded by the ThreadSpanState object instance. While
1803 * in theory there'd be no locking required because it's all local
1804 * per-thread, the finish() method above is defensive against
1805 * people calling it on a different thread from where they created
1806 * the Span, hence the locking.
1807 */
1808 private static class ThreadSpanState {
1809 public Span mActiveHead; // doubly-linked list.
1810 public int mActiveSize;
1811 public Span mFreeListHead; // singly-linked list. only changes at head.
1812 public int mFreeListSize;
1813 }
1814
1815 private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
1816 new ThreadLocal<ThreadSpanState>() {
1817 @Override protected ThreadSpanState initialValue() {
1818 return new ThreadSpanState();
1819 }
1820 };
1821
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08001822 private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
1823 protected IWindowManager create() {
1824 return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
1825 }
1826 };
1827
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001828 /**
1829 * Enter a named critical span (e.g. an animation)
1830 *
1831 * <p>The name is an arbitary label (or tag) that will be applied
1832 * to any strictmode violation that happens while this span is
1833 * active. You must call finish() on the span when done.
1834 *
1835 * <p>This will never return null, but on devices without debugging
1836 * enabled, this may return a dummy object on which the finish()
1837 * method is a no-op.
1838 *
1839 * <p>TODO: add CloseGuard to this, verifying callers call finish.
1840 *
1841 * @hide
1842 */
1843 public static Span enterCriticalSpan(String name) {
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08001844 if (IS_USER_BUILD) {
1845 return NO_OP_SPAN;
1846 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001847 if (name == null || name.isEmpty()) {
1848 throw new IllegalArgumentException("name must be non-null and non-empty");
1849 }
1850 ThreadSpanState state = sThisThreadSpanState.get();
1851 Span span = null;
1852 synchronized (state) {
1853 if (state.mFreeListHead != null) {
1854 span = state.mFreeListHead;
1855 state.mFreeListHead = span.mNext;
1856 state.mFreeListSize--;
1857 } else {
1858 // Shouldn't have to do this often.
1859 span = new Span(state);
1860 }
1861 span.mName = name;
1862 span.mCreateMillis = SystemClock.uptimeMillis();
1863 span.mNext = state.mActiveHead;
1864 span.mPrev = null;
1865 state.mActiveHead = span;
1866 state.mActiveSize++;
1867 if (span.mNext != null) {
1868 span.mNext.mPrev = span;
1869 }
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08001870 if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001871 }
1872 return span;
1873 }
1874
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001875 /**
1876 * For code to note that it's slow. This is a no-op unless the
1877 * current thread's {@link android.os.StrictMode.ThreadPolicy} has
1878 * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls}
1879 * enabled.
1880 *
1881 * @param name a short string for the exception stack trace that's
1882 * built if when this fires.
1883 */
1884 public static void noteSlowCall(String name) {
1885 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1886 if (!(policy instanceof AndroidBlockGuardPolicy)) {
1887 // StrictMode not enabled.
1888 return;
1889 }
1890 ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
1891 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08001892
1893 /**
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001894 * @hide
1895 */
1896 public static void noteDiskRead() {
1897 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001898 if (!(policy instanceof AndroidBlockGuardPolicy)) {
1899 // StrictMode not enabled.
1900 return;
1901 }
1902 ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
1903 }
1904
1905 /**
1906 * @hide
1907 */
1908 public static void noteDiskWrite() {
1909 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1910 if (!(policy instanceof AndroidBlockGuardPolicy)) {
1911 // StrictMode not enabled.
1912 return;
1913 }
1914 ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
1915 }
1916
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001917 // Guarded by StrictMode.class
1918 private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
1919 new HashMap<Class, Integer>();
1920
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001921 /**
Jeff Brown7e442832011-06-10 18:00:16 -07001922 * Returns an object that is used to track instances of activites.
1923 * The activity should store a reference to the tracker object in one of its fields.
1924 * @hide
1925 */
1926 public static Object trackActivity(Object instance) {
1927 return new InstanceTracker(instance);
1928 }
1929
1930 /**
Brad Fitzpatrick75803572011-01-13 14:21:03 -08001931 * @hide
1932 */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001933 public static void incrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07001934 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08001935 return;
1936 }
Jeff Brown7e442832011-06-10 18:00:16 -07001937
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001938 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07001939 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
1940 return;
1941 }
1942
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001943 Integer expected = sExpectedActivityInstanceCount.get(klass);
1944 Integer newExpected = expected == null ? 1 : expected + 1;
1945 sExpectedActivityInstanceCount.put(klass, newExpected);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001946 }
1947 }
1948
1949 /**
1950 * @hide
1951 */
1952 public static void decrementExpectedActivityCount(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
1957 final int limit;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001958 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07001959 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
1960 return;
1961 }
1962
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001963 Integer expected = sExpectedActivityInstanceCount.get(klass);
Jeff Brown7e442832011-06-10 18:00:16 -07001964 int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001965 if (newExpected == 0) {
1966 sExpectedActivityInstanceCount.remove(klass);
1967 } else {
1968 sExpectedActivityInstanceCount.put(klass, newExpected);
1969 }
Jeff Brown7e442832011-06-10 18:00:16 -07001970
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001971 // Note: adding 1 here to give some breathing room during
1972 // orientation changes. (shouldn't be necessary, though?)
Jeff Brown7e442832011-06-10 18:00:16 -07001973 limit = newExpected + 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001974 }
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001975
Jeff Brown7e442832011-06-10 18:00:16 -07001976 // Quick check.
1977 int actual = InstanceTracker.getInstanceCount(klass);
1978 if (actual <= limit) {
1979 return;
1980 }
1981
1982 // Do a GC and explicit count to double-check.
1983 // This is the work that we are trying to avoid by tracking the object instances
1984 // explicity. Running an explicit GC can be expensive (80ms) and so can walking
1985 // the heap to count instance (30ms). This extra work can make the system feel
1986 // noticeably less responsive during orientation changes when activities are
1987 // being restarted. Granted, it is only a problem when StrictMode is enabled
1988 // but it is annoying.
1989 Runtime.getRuntime().gc();
1990
1991 long instances = VMDebug.countInstancesOfClass(klass, false);
1992 if (instances > limit) {
1993 Throwable tr = new InstanceCountViolation(klass, instances, limit);
1994 onVmPolicyViolation(tr.getMessage(), tr);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001995 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -08001996 }
1997
1998 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001999 * Parcelable that gets sent in Binder call headers back to callers
2000 * to report violations that happened during a cross-process call.
2001 *
2002 * @hide
2003 */
2004 public static class ViolationInfo {
2005 /**
2006 * Stack and other stuff info.
2007 */
2008 public final ApplicationErrorReport.CrashInfo crashInfo;
2009
2010 /**
2011 * The strict mode policy mask at the time of violation.
2012 */
2013 public final int policy;
2014
2015 /**
2016 * The wall time duration of the violation, when known. -1 when
2017 * not known.
2018 */
2019 public int durationMillis = -1;
2020
2021 /**
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002022 * The number of animations currently running.
2023 */
2024 public int numAnimationsRunning = 0;
2025
2026 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002027 * List of tags from active Span instances during this
2028 * violation, or null for none.
2029 */
2030 public String[] tags;
2031
2032 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002033 * Which violation number this was (1-based) since the last Looper loop,
2034 * from the perspective of the root caller (if it crossed any processes
2035 * via Binder calls). The value is 0 if the root caller wasn't on a Looper
2036 * thread.
2037 */
2038 public int violationNumThisLoop;
2039
2040 /**
2041 * The time (in terms of SystemClock.uptimeMillis()) that the
2042 * violation occurred.
2043 */
2044 public long violationUptimeMillis;
2045
2046 /**
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002047 * The action of the Intent being broadcast to somebody's onReceive
2048 * on this thread right now, or null.
2049 */
2050 public String broadcastIntentAction;
2051
2052 /**
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002053 * If this is a instance count violation, the number of instances in memory,
2054 * else -1.
2055 */
2056 public long numInstances = -1;
2057
2058 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002059 * Create an uninitialized instance of ViolationInfo
2060 */
2061 public ViolationInfo() {
2062 crashInfo = null;
2063 policy = 0;
2064 }
2065
2066 /**
2067 * Create an instance of ViolationInfo initialized from an exception.
2068 */
2069 public ViolationInfo(Throwable tr, int policy) {
2070 crashInfo = new ApplicationErrorReport.CrashInfo(tr);
2071 violationUptimeMillis = SystemClock.uptimeMillis();
2072 this.policy = policy;
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002073 this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002074 Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2075 if (broadcastIntent != null) {
2076 broadcastIntentAction = broadcastIntent.getAction();
2077 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002078 ThreadSpanState state = sThisThreadSpanState.get();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002079 if (tr instanceof InstanceCountViolation) {
2080 this.numInstances = ((InstanceCountViolation) tr).mInstances;
2081 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002082 synchronized (state) {
2083 int spanActiveCount = state.mActiveSize;
2084 if (spanActiveCount > MAX_SPAN_TAGS) {
2085 spanActiveCount = MAX_SPAN_TAGS;
2086 }
2087 if (spanActiveCount != 0) {
2088 this.tags = new String[spanActiveCount];
2089 Span iter = state.mActiveHead;
2090 int index = 0;
2091 while (iter != null && index < spanActiveCount) {
2092 this.tags[index] = iter.mName;
2093 index++;
2094 iter = iter.mNext;
2095 }
2096 }
2097 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002098 }
2099
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002100 @Override
2101 public int hashCode() {
2102 int result = 17;
2103 result = 37 * result + crashInfo.stackTrace.hashCode();
2104 if (numAnimationsRunning != 0) {
2105 result *= 37;
2106 }
2107 if (broadcastIntentAction != null) {
2108 result = 37 * result + broadcastIntentAction.hashCode();
2109 }
2110 if (tags != null) {
2111 for (String tag : tags) {
2112 result = 37 * result + tag.hashCode();
2113 }
2114 }
2115 return result;
2116 }
2117
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002118 /**
2119 * Create an instance of ViolationInfo initialized from a Parcel.
2120 */
2121 public ViolationInfo(Parcel in) {
2122 this(in, false);
2123 }
2124
2125 /**
2126 * Create an instance of ViolationInfo initialized from a Parcel.
2127 *
2128 * @param unsetGatheringBit if true, the caller is the root caller
2129 * and the gathering penalty should be removed.
2130 */
2131 public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
2132 crashInfo = new ApplicationErrorReport.CrashInfo(in);
2133 int rawPolicy = in.readInt();
2134 if (unsetGatheringBit) {
2135 policy = rawPolicy & ~PENALTY_GATHER;
2136 } else {
2137 policy = rawPolicy;
2138 }
2139 durationMillis = in.readInt();
2140 violationNumThisLoop = in.readInt();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002141 numAnimationsRunning = in.readInt();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002142 violationUptimeMillis = in.readLong();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002143 numInstances = in.readLong();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002144 broadcastIntentAction = in.readString();
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002145 tags = in.readStringArray();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002146 }
2147
2148 /**
2149 * Save a ViolationInfo instance to a parcel.
2150 */
2151 public void writeToParcel(Parcel dest, int flags) {
2152 crashInfo.writeToParcel(dest, flags);
2153 dest.writeInt(policy);
2154 dest.writeInt(durationMillis);
2155 dest.writeInt(violationNumThisLoop);
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002156 dest.writeInt(numAnimationsRunning);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002157 dest.writeLong(violationUptimeMillis);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002158 dest.writeLong(numInstances);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002159 dest.writeString(broadcastIntentAction);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002160 dest.writeStringArray(tags);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002161 }
2162
2163
2164 /**
2165 * Dump a ViolationInfo instance to a Printer.
2166 */
2167 public void dump(Printer pw, String prefix) {
2168 crashInfo.dump(pw, prefix);
2169 pw.println(prefix + "policy: " + policy);
2170 if (durationMillis != -1) {
2171 pw.println(prefix + "durationMillis: " + durationMillis);
2172 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002173 if (numInstances != -1) {
2174 pw.println(prefix + "numInstances: " + numInstances);
2175 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002176 if (violationNumThisLoop != 0) {
2177 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2178 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002179 if (numAnimationsRunning != 0) {
2180 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2181 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002182 pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002183 if (broadcastIntentAction != null) {
2184 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2185 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002186 if (tags != null) {
2187 int index = 0;
2188 for (String tag : tags) {
2189 pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2190 }
2191 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002192 }
2193
2194 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002195
2196 // Dummy throwable, for now, since we don't know when or where the
2197 // leaked instances came from. We might in the future, but for
2198 // now we suppress the stack trace because it's useless and/or
2199 // misleading.
2200 private static class InstanceCountViolation extends Throwable {
2201 final Class mClass;
2202 final long mInstances;
2203 final int mLimit;
2204
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002205 private static final StackTraceElement[] FAKE_STACK = {
2206 new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
2207 "StrictMode.java", 1)
2208 };
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002209
2210 public InstanceCountViolation(Class klass, long instances, int limit) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002211 super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002212 setStackTrace(FAKE_STACK);
2213 mClass = klass;
2214 mInstances = instances;
2215 mLimit = limit;
2216 }
2217 }
Jeff Brown7e442832011-06-10 18:00:16 -07002218
2219 private static final class InstanceTracker {
2220 private static final HashMap<Class<?>, Integer> sInstanceCounts =
2221 new HashMap<Class<?>, Integer>();
2222
2223 private final Class<?> mKlass;
2224
2225 public InstanceTracker(Object instance) {
2226 mKlass = instance.getClass();
2227
2228 synchronized (sInstanceCounts) {
2229 final Integer value = sInstanceCounts.get(mKlass);
2230 final int newValue = value != null ? value + 1 : 1;
2231 sInstanceCounts.put(mKlass, newValue);
2232 }
2233 }
2234
2235 @Override
2236 protected void finalize() throws Throwable {
2237 try {
2238 synchronized (sInstanceCounts) {
2239 final Integer value = sInstanceCounts.get(mKlass);
2240 if (value != null) {
2241 final int newValue = value - 1;
2242 if (newValue > 0) {
2243 sInstanceCounts.put(mKlass, newValue);
2244 } else {
2245 sInstanceCounts.remove(mKlass);
2246 }
2247 }
2248 }
2249 } finally {
2250 super.finalize();
2251 }
2252 }
2253
2254 public static int getInstanceCount(Class<?> klass) {
2255 synchronized (sInstanceCounts) {
2256 final Integer value = sInstanceCounts.get(klass);
2257 return value != null ? value : 0;
2258 }
2259 }
2260 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07002261}