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