blob: 3b6df5df13aa8f1b505c5fe177f7573f45b31e8c [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;
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -060019import android.annotation.TestApi;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070020import android.app.ActivityManager;
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -070021import android.app.ActivityThread;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070022import android.app.ApplicationErrorReport;
Brad Fitzpatrick10656852010-11-23 19:01:13 -080023import android.app.IActivityManager;
Jeff Sharkeyd7026f12012-03-01 20:50:32 -080024import android.content.BroadcastReceiver;
25import android.content.Context;
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -070026import android.content.Intent;
Jeff Sharkeyd7026f12012-03-01 20:50:32 -080027import android.content.ServiceConnection;
Jeff Sharkey619a5112017-01-19 11:55:54 -070028import android.net.TrafficStats;
Jeff Sharkey344744b2016-01-28 19:03:30 -070029import android.net.Uri;
Dianne Hackborn390517b2013-05-30 15:03:32 -070030import android.util.ArrayMap;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070031import android.util.Log;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070032import android.util.Printer;
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -080033import android.util.Singleton;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070034import android.util.Slog;
Brad Fitzpatrick68044332010-11-22 18:19:48 -080035import android.view.IWindowManager;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070036
37import com.android.internal.os.RuntimeInit;
Dianne Hackborn8c841092013-06-24 13:46:13 -070038import com.android.internal.util.FastPrintWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080039import com.android.internal.util.HexDump;
40
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070041import dalvik.system.BlockGuard;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070042import dalvik.system.CloseGuard;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -080043import dalvik.system.VMDebug;
Jeff Sharkey0b558702017-01-26 16:48:01 -070044import dalvik.system.VMRuntime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070045
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070046import java.io.PrintWriter;
47import java.io.StringWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080048import java.net.InetAddress;
49import java.net.UnknownHostException;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070050import java.util.ArrayList;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070051import java.util.Arrays;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070052import java.util.HashMap;
Brad Fitzpatrickbee24872010-11-20 12:09:10 -080053import java.util.concurrent.atomic.AtomicInteger;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070054
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070055/**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070056 * <p>StrictMode is a developer tool which detects things you might be
57 * doing by accident and brings them to your attention so you can fix
58 * them.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070059 *
60 * <p>StrictMode is most commonly used to catch accidental disk or
61 * network access on the application's main thread, where UI
62 * operations are received and animations take place. Keeping disk
63 * and network operations off the main thread makes for much smoother,
Brad Fitzpatrick9fc2fc52010-10-11 12:52:35 -070064 * more responsive applications. By keeping your application's main thread
65 * responsive, you also prevent
66 * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
67 * from being shown to users.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070068 *
69 * <p class="note">Note that even though an Android device's disk is
70 * often on flash memory, many devices run a filesystem on top of that
71 * memory with very limited concurrency. It's often the case that
72 * almost all disk accesses are fast, but may in individual cases be
73 * dramatically slower when certain I/O is happening in the background
74 * from other processes. If possible, it's best to assume that such
75 * things are not fast.</p>
76 *
77 * <p>Example code to enable from early in your
78 * {@link android.app.Application}, {@link android.app.Activity}, or
79 * other application component's
80 * {@link android.app.Application#onCreate} method:
81 *
82 * <pre>
83 * public void onCreate() {
84 * if (DEVELOPER_MODE) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070085 * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
86 * .detectDiskReads()
87 * .detectDiskWrites()
88 * .detectNetwork() // or .detectAll() for all detectable problems
89 * .penaltyLog()
90 * .build());
91 * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -070092 * .detectLeakedSqlLiteObjects()
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070093 * .detectLeakedClosableObjects()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -070094 * .penaltyLog()
95 * .penaltyDeath()
96 * .build());
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070097 * }
98 * super.onCreate();
99 * }
100 * </pre>
101 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700102 * <p>You can decide what should happen when a violation is detected.
103 * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can
104 * watch the output of <code>adb logcat</code> while you use your
105 * application to see the violations as they happen.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700106 *
107 * <p>If you find violations that you feel are problematic, there are
108 * a variety of tools to help solve them: threads, {@link android.os.Handler},
109 * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
110 * But don't feel compelled to fix everything that StrictMode finds. In particular,
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700111 * many cases of disk access are often necessary during the normal activity lifecycle. Use
112 * StrictMode to find things you did by accident. Network requests on the UI thread
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700113 * are almost always a problem, though.
114 *
115 * <p class="note">StrictMode is not a security mechanism and is not
116 * guaranteed to find all disk or network accesses. While it does
117 * propagate its state across process boundaries when doing
118 * {@link android.os.Binder} calls, it's still ultimately a best
119 * effort mechanism. Notably, disk or network access from JNI calls
120 * won't necessarily trigger it. Future versions of Android may catch
121 * more (or fewer) operations, so you should never leave StrictMode
Dirk Dougherty4d7bc6552012-01-27 17:56:49 -0800122 * enabled in applications distributed on Google Play.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700123 */
124public final class StrictMode {
125 private static final String TAG = "StrictMode";
Brad Fitzpatrick82829ef2010-11-18 18:25:08 -0800126 private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700127
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
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -0700243 /**
244 * @hide
245 */
246 private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy
247
Jeff Sharkey619a5112017-01-19 11:55:54 -0700248 /**
249 * @hide
250 */
251 private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy
252
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800253 private static final int ALL_VM_DETECT_BITS =
254 DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800255 DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
Jeff Sharkey605eb792014-11-04 13:34:06 -0800256 DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE |
Jeff Sharkey619a5112017-01-19 11:55:54 -0700257 DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION |
258 DETECT_VM_UNTAGGED_SOCKET;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800259
260 // Byte 3: Penalty
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800261
Jeff Sharkey344744b2016-01-28 19:03:30 -0700262 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800263 public static final int PENALTY_LOG = 0x01 << 16; // normal android.util.Log
Jeff Sharkey344744b2016-01-28 19:03:30 -0700264 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800265 public static final int PENALTY_DIALOG = 0x02 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700266 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800267 public static final int PENALTY_DEATH = 0x04 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700268 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800269 public static final int PENALTY_FLASH = 0x10 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700270 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800271 public static final int PENALTY_DROPBOX = 0x20 << 16;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700272
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700273 /**
274 * Non-public penalty mode which overrides all the other penalty
275 * bits and signals that we're in a Binder call and we should
276 * ignore the other penalty bits and instead serialize back all
277 * our offending stack traces to the caller to ultimately handle
278 * in the originating process.
279 *
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700280 * This must be kept in sync with the constant in libs/binder/Parcel.cpp
281 *
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700282 * @hide
283 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800284 public static final int PENALTY_GATHER = 0x40 << 16;
285
Jeff Sharkey344744b2016-01-28 19:03:30 -0700286 // Byte 4: Special cases
287
288 /**
289 * Death when network traffic is detected on main thread.
290 *
291 * @hide
292 */
293 public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
294
Jeff Sharkey605eb792014-11-04 13:34:06 -0800295 /**
296 * Death when cleartext network traffic is detected.
297 *
298 * @hide
299 */
Jeff Sharkey344744b2016-01-28 19:03:30 -0700300 public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
301
302 /**
303 * Death when file exposure is detected.
304 *
305 * @hide
306 */
307 public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700308
Jeff Sharkey619a5112017-01-19 11:55:54 -0700309 // CAUTION: we started stealing the top bits of Byte 4 for VM above
310
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700311 /**
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800312 * Mask of all the penalty bits valid for thread policies.
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700313 */
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800314 private static final int THREAD_PENALTY_MASK =
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700315 PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800316 PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700317
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800318 /**
319 * Mask of all the penalty bits valid for VM policies.
320 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800321 private static final int VM_PENALTY_MASK = PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX
Jeff Sharkey344744b2016-01-28 19:03:30 -0700322 | PENALTY_DEATH_ON_CLEARTEXT_NETWORK | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800323
Jeff Sharkey605eb792014-11-04 13:34:06 -0800324 /** {@hide} */
325 public static final int NETWORK_POLICY_ACCEPT = 0;
326 /** {@hide} */
327 public static final int NETWORK_POLICY_LOG = 1;
328 /** {@hide} */
329 public static final int NETWORK_POLICY_REJECT = 2;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800330
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800331 // TODO: wrap in some ImmutableHashMap thing.
332 // Note: must be before static initialization of sVmPolicy.
333 private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP = new HashMap<Class, Integer>();
334
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700335 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700336 * The current VmPolicy in effect.
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800337 *
338 * TODO: these are redundant (mask is in VmPolicy). Should remove sVmPolicyMask.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700339 */
340 private static volatile int sVmPolicyMask = 0;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800341 private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700342
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600343 /** {@hide} */
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -0600344 @TestApi
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600345 public interface ViolationListener {
346 public void onViolation(String message);
347 }
348
349 private static volatile ViolationListener sListener;
350
351 /** {@hide} */
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -0600352 @TestApi
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600353 public static void setViolationListener(ViolationListener listener) {
354 sListener = listener;
355 }
356
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800357 /**
358 * The number of threads trying to do an async dropbox write.
359 * Just to limit ourselves out of paranoia.
360 */
361 private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
362
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700363 private StrictMode() {}
364
365 /**
366 * {@link StrictMode} policy applied to a certain thread.
367 *
368 * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy
369 * can be retrieved with {@link #getThreadPolicy}.
370 *
371 * <p>Note that multiple penalties may be provided and they're run
372 * in order from least to most severe (logging before process
373 * death, for example). There's currently no mechanism to choose
374 * different penalties for different detected actions.
375 */
376 public static final class ThreadPolicy {
377 /**
378 * The default, lax policy which doesn't catch anything.
379 */
380 public static final ThreadPolicy LAX = new ThreadPolicy(0);
381
382 final int mask;
383
384 private ThreadPolicy(int mask) {
385 this.mask = mask;
386 }
387
388 @Override
389 public String toString() {
390 return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
391 }
392
393 /**
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800394 * Creates {@link ThreadPolicy} instances. Methods whose names start
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700395 * with {@code detect} specify what problems we should look
396 * for. Methods whose names start with {@code penalty} specify what
397 * we should do when we detect a problem.
398 *
399 * <p>You can call as many {@code detect} and {@code penalty}
400 * methods as you like. Currently order is insignificant: all
401 * penalties apply to all detected problems.
402 *
403 * <p>For example, detect everything and log anything that's found:
404 * <pre>
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800405 * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700406 * .detectAll()
407 * .penaltyLog()
408 * .build();
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800409 * StrictMode.setThreadPolicy(policy);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700410 * </pre>
411 */
412 public static final class Builder {
413 private int mMask = 0;
414
415 /**
416 * Create a Builder that detects nothing and has no
417 * violations. (but note that {@link #build} will default
418 * to enabling {@link #penaltyLog} if no other penalties
419 * are specified)
420 */
421 public Builder() {
422 mMask = 0;
423 }
424
425 /**
426 * Initialize a Builder from an existing ThreadPolicy.
427 */
428 public Builder(ThreadPolicy policy) {
429 mMask = policy.mask;
430 }
431
432 /**
433 * Detect everything that's potentially suspect.
434 *
435 * <p>As of the Gingerbread release this includes network and
436 * disk operations but will likely expand in future releases.
437 */
438 public Builder detectAll() {
Jeff Sharkey0b558702017-01-26 16:48:01 -0700439 detectDiskReads();
440 detectDiskWrites();
441 detectNetwork();
442
443 final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
444 if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
445 detectCustomSlowCalls();
446 }
447 if (targetSdk >= Build.VERSION_CODES.M) {
448 detectResourceMismatches();
449 }
450 if (targetSdk >= Build.VERSION_CODES.O) {
451 detectUnbufferedIo();
452 }
453 return this;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700454 }
455
456 /**
457 * Disable the detection of everything.
458 */
459 public Builder permitAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800460 return disable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700461 }
462
463 /**
464 * Enable detection of network operations.
465 */
466 public Builder detectNetwork() {
467 return enable(DETECT_NETWORK);
468 }
469
470 /**
471 * Disable detection of network operations.
472 */
473 public Builder permitNetwork() {
474 return disable(DETECT_NETWORK);
475 }
476
477 /**
478 * Enable detection of disk reads.
479 */
480 public Builder detectDiskReads() {
481 return enable(DETECT_DISK_READ);
482 }
483
484 /**
485 * Disable detection of disk reads.
486 */
487 public Builder permitDiskReads() {
488 return disable(DETECT_DISK_READ);
489 }
490
491 /**
Qi Wang097fbf22012-07-13 09:26:03 +0800492 * Enable detection of slow calls.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800493 */
494 public Builder detectCustomSlowCalls() {
495 return enable(DETECT_CUSTOM);
496 }
497
498 /**
Qi Wang097fbf22012-07-13 09:26:03 +0800499 * Disable detection of slow calls.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800500 */
501 public Builder permitCustomSlowCalls() {
Qi Wang097fbf22012-07-13 09:26:03 +0800502 return disable(DETECT_CUSTOM);
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800503 }
504
505 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800506 * Disable detection of mismatches between defined resource types
507 * and getter calls.
508 */
509 public Builder permitResourceMismatches() {
510 return disable(DETECT_RESOURCE_MISMATCH);
511 }
512
513 /**
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100514 * Detect unbuffered input/output operations.
515 */
516 public Builder detectUnbufferedIo() {
517 return enable(DETECT_UNBUFFERED_IO);
518 }
519
520 /**
Shubham Ajmeraade21172017-03-01 09:26:41 -0800521 * Disable detection of unbuffered input/output operations.
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100522 */
523 public Builder permitUnbufferedIo() {
524 return disable(DETECT_UNBUFFERED_IO);
525 }
526
527 /**
Alan Viverette39bf9a12015-05-13 17:22:34 -0700528 * Enables detection of mismatches between defined resource types
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800529 * and getter calls.
Alan Viverette39bf9a12015-05-13 17:22:34 -0700530 * <p>
531 * This helps detect accidental type mismatches and potentially
532 * expensive type conversions when obtaining typed resources.
533 * <p>
534 * For example, a strict mode violation would be thrown when
535 * calling {@link android.content.res.TypedArray#getInt(int, int)}
536 * on an index that contains a String-type resource. If the string
537 * value can be parsed as an integer, this method call will return
538 * a value without crashing; however, the developer should format
539 * the resource as an integer to avoid unnecessary type conversion.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800540 */
541 public Builder detectResourceMismatches() {
542 return enable(DETECT_RESOURCE_MISMATCH);
543 }
544
545 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700546 * Enable detection of disk writes.
547 */
548 public Builder detectDiskWrites() {
549 return enable(DETECT_DISK_WRITE);
550 }
551
552 /**
553 * Disable detection of disk writes.
554 */
555 public Builder permitDiskWrites() {
556 return disable(DETECT_DISK_WRITE);
557 }
558
559 /**
560 * Show an annoying dialog to the developer on detected
561 * violations, rate-limited to be only a little annoying.
562 */
563 public Builder penaltyDialog() {
564 return enable(PENALTY_DIALOG);
565 }
566
567 /**
568 * Crash the whole process on violation. This penalty runs at
569 * the end of all enabled penalties so you'll still get
570 * see logging or other violations before the process dies.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700571 *
572 * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies
573 * to disk reads, disk writes, and network usage if their
574 * corresponding detect flags are set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700575 */
576 public Builder penaltyDeath() {
577 return enable(PENALTY_DEATH);
578 }
579
580 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700581 * Crash the whole process on any network usage. Unlike
582 * {@link #penaltyDeath}, this penalty runs
583 * <em>before</em> anything else. You must still have
584 * called {@link #detectNetwork} to enable this.
585 *
586 * <p>In the Honeycomb or later SDKs, this is on by default.
587 */
588 public Builder penaltyDeathOnNetwork() {
589 return enable(PENALTY_DEATH_ON_NETWORK);
590 }
591
592 /**
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800593 * Flash the screen during a violation.
594 */
595 public Builder penaltyFlashScreen() {
596 return enable(PENALTY_FLASH);
597 }
598
599 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700600 * Log detected violations to the system log.
601 */
602 public Builder penaltyLog() {
603 return enable(PENALTY_LOG);
604 }
605
606 /**
607 * Enable detected violations log a stacktrace and timing data
608 * to the {@link android.os.DropBoxManager DropBox} on policy
609 * violation. Intended mostly for platform integrators doing
610 * beta user field data collection.
611 */
612 public Builder penaltyDropBox() {
613 return enable(PENALTY_DROPBOX);
614 }
615
616 private Builder enable(int bit) {
617 mMask |= bit;
618 return this;
619 }
620
621 private Builder disable(int bit) {
622 mMask &= ~bit;
623 return this;
624 }
625
626 /**
627 * Construct the ThreadPolicy instance.
628 *
629 * <p>Note: if no penalties are enabled before calling
630 * <code>build</code>, {@link #penaltyLog} is implicitly
631 * set.
632 */
633 public ThreadPolicy build() {
634 // If there are detection bits set but no violation bits
635 // set, enable simple logging.
636 if (mMask != 0 &&
637 (mMask & (PENALTY_DEATH | PENALTY_LOG |
638 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
639 penaltyLog();
640 }
641 return new ThreadPolicy(mMask);
642 }
643 }
644 }
645
646 /**
647 * {@link StrictMode} policy applied to all threads in the virtual machine's process.
648 *
649 * <p>The policy is enabled by {@link #setVmPolicy}.
650 */
651 public static final class VmPolicy {
652 /**
653 * The default, lax policy which doesn't catch anything.
654 */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800655 public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700656
657 final int mask;
658
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800659 // Map from class to max number of allowed instances in memory.
660 final HashMap<Class, Integer> classInstanceLimit;
661
662 private VmPolicy(int mask, HashMap<Class, Integer> classInstanceLimit) {
663 if (classInstanceLimit == null) {
664 throw new NullPointerException("classInstanceLimit == null");
665 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700666 this.mask = mask;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800667 this.classInstanceLimit = classInstanceLimit;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700668 }
669
670 @Override
671 public String toString() {
672 return "[StrictMode.VmPolicy; mask=" + mask + "]";
673 }
674
675 /**
676 * Creates {@link VmPolicy} instances. Methods whose names start
677 * with {@code detect} specify what problems we should look
678 * for. Methods whose names start with {@code penalty} specify what
679 * we should do when we detect a problem.
680 *
681 * <p>You can call as many {@code detect} and {@code penalty}
682 * methods as you like. Currently order is insignificant: all
683 * penalties apply to all detected problems.
684 *
685 * <p>For example, detect everything and log anything that's found:
686 * <pre>
687 * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
688 * .detectAll()
689 * .penaltyLog()
690 * .build();
691 * StrictMode.setVmPolicy(policy);
692 * </pre>
693 */
694 public static final class Builder {
695 private int mMask;
696
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800697 private HashMap<Class, Integer> mClassInstanceLimit; // null until needed
698 private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write
699
700 public Builder() {
701 mMask = 0;
702 }
703
704 /**
705 * Build upon an existing VmPolicy.
706 */
707 public Builder(VmPolicy base) {
708 mMask = base.mask;
709 mClassInstanceLimitNeedCow = true;
710 mClassInstanceLimit = base.classInstanceLimit;
711 }
712
713 /**
714 * Set an upper bound on how many instances of a class can be in memory
715 * at once. Helps to prevent object leaks.
716 */
717 public Builder setClassInstanceLimit(Class klass, int instanceLimit) {
718 if (klass == null) {
719 throw new NullPointerException("klass == null");
720 }
721 if (mClassInstanceLimitNeedCow) {
722 if (mClassInstanceLimit.containsKey(klass) &&
723 mClassInstanceLimit.get(klass) == instanceLimit) {
724 // no-op; don't break COW
725 return this;
726 }
727 mClassInstanceLimitNeedCow = false;
728 mClassInstanceLimit = (HashMap<Class, Integer>) mClassInstanceLimit.clone();
729 } else if (mClassInstanceLimit == null) {
730 mClassInstanceLimit = new HashMap<Class, Integer>();
731 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800732 mMask |= DETECT_VM_INSTANCE_LEAKS;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800733 mClassInstanceLimit.put(klass, instanceLimit);
734 return this;
735 }
736
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800737 /**
738 * Detect leaks of {@link android.app.Activity} subclasses.
739 */
740 public Builder detectActivityLeaks() {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800741 return enable(DETECT_VM_ACTIVITY_LEAKS);
742 }
743
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700744 /**
745 * Detect everything that's potentially suspect.
746 *
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700747 * <p>In the Honeycomb release this includes leaks of
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800748 * SQLite cursors, Activities, and other closable objects
749 * but will likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700750 */
751 public Builder detectAll() {
Jeff Sharkey0b558702017-01-26 16:48:01 -0700752 detectLeakedSqlLiteObjects();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800753
Jeff Sharkey0b558702017-01-26 16:48:01 -0700754 final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
755 if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
756 detectActivityLeaks();
757 detectLeakedClosableObjects();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800758 }
Jeff Sharkey0b558702017-01-26 16:48:01 -0700759 if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) {
760 detectLeakedRegistrationObjects();
761 }
762 if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
763 detectFileUriExposure();
764 }
765 if (targetSdk >= Build.VERSION_CODES.M) {
766 // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have
767 // facility for apps to mark sockets that should be ignored
768 if (SystemProperties.getBoolean(CLEARTEXT_PROPERTY, false)) {
769 detectCleartextNetwork();
770 }
771 }
772 if (targetSdk >= Build.VERSION_CODES.O) {
773 detectContentUriWithoutPermission();
774 detectUntaggedSockets();
775 }
776 return this;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700777 }
778
779 /**
780 * Detect when an
781 * {@link android.database.sqlite.SQLiteCursor} or other
782 * SQLite object is finalized without having been closed.
783 *
784 * <p>You always want to explicitly close your SQLite
785 * cursors to avoid unnecessary database contention and
786 * temporary memory leaks.
787 */
788 public Builder detectLeakedSqlLiteObjects() {
789 return enable(DETECT_VM_CURSOR_LEAKS);
790 }
791
792 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700793 * Detect when an {@link java.io.Closeable} or other
Kurt Nelson27616132017-09-12 15:40:23 -0700794 * object with an explicit termination method is finalized
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700795 * without having been closed.
796 *
797 * <p>You always want to explicitly close such objects to
798 * avoid unnecessary resources leaks.
799 */
800 public Builder detectLeakedClosableObjects() {
801 return enable(DETECT_VM_CLOSABLE_LEAKS);
802 }
803
804 /**
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800805 * Detect when a {@link BroadcastReceiver} or
806 * {@link ServiceConnection} is leaked during {@link Context}
807 * teardown.
808 */
809 public Builder detectLeakedRegistrationObjects() {
810 return enable(DETECT_VM_REGISTRATION_LEAKS);
811 }
812
813 /**
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -0700814 * Detect when the calling application exposes a {@code file://}
Jeff Sharkey344744b2016-01-28 19:03:30 -0700815 * {@link android.net.Uri} to another app.
816 * <p>
817 * This exposure is discouraged since the receiving app may not have
818 * access to the shared path. For example, the receiving app may not
819 * have requested the
820 * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime
821 * permission, or the platform may be sharing the
822 * {@link android.net.Uri} across user profile boundaries.
823 * <p>
824 * Instead, apps should use {@code content://} Uris so the platform
825 * can extend temporary permission for the receiving app to access
826 * the resource.
827 *
828 * @see android.support.v4.content.FileProvider
829 * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700830 */
831 public Builder detectFileUriExposure() {
832 return enable(DETECT_VM_FILE_URI_EXPOSURE);
833 }
834
835 /**
Jeff Sharkey605eb792014-11-04 13:34:06 -0800836 * Detect any network traffic from the calling app which is not
837 * wrapped in SSL/TLS. This can help you detect places that your app
838 * is inadvertently sending cleartext data across the network.
839 * <p>
840 * Using {@link #penaltyDeath()} or
841 * {@link #penaltyDeathOnCleartextNetwork()} will block further
842 * traffic on that socket to prevent accidental data leakage, in
843 * addition to crashing your process.
844 * <p>
845 * Using {@link #penaltyDropBox()} will log the raw contents of the
846 * packet that triggered the violation.
847 * <p>
848 * This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it
849 * may be subject to false positives, such as when STARTTLS
850 * protocols or HTTP proxies are used.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800851 */
852 public Builder detectCleartextNetwork() {
853 return enable(DETECT_VM_CLEARTEXT_NETWORK);
854 }
855
856 /**
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -0700857 * Detect when the calling application sends a {@code content://}
858 * {@link android.net.Uri} to another app without setting
859 * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} or
860 * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
861 * <p>
862 * Forgetting to include one or more of these flags when sending an
863 * intent is typically an app bug.
864 *
865 * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
866 * @see Intent#FLAG_GRANT_WRITE_URI_PERMISSION
867 */
868 public Builder detectContentUriWithoutPermission() {
869 return enable(DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION);
870 }
871
872 /**
Jeff Sharkey619a5112017-01-19 11:55:54 -0700873 * Detect any sockets in the calling app which have not been tagged
874 * using {@link TrafficStats}. Tagging sockets can help you
875 * investigate network usage inside your app, such as a narrowing
876 * down heavy usage to a specific library or component.
877 * <p>
878 * This currently does not detect sockets created in native code.
879 *
880 * @see TrafficStats#setThreadStatsTag(int)
881 * @see TrafficStats#tagSocket(java.net.Socket)
882 * @see TrafficStats#tagDatagramSocket(java.net.DatagramSocket)
883 */
884 public Builder detectUntaggedSockets() {
885 return enable(DETECT_VM_UNTAGGED_SOCKET);
886 }
887
888 /**
Jeff Sharkey605eb792014-11-04 13:34:06 -0800889 * Crashes the whole process on violation. This penalty runs at the
890 * end of all enabled penalties so you'll still get your logging or
891 * other violations before the process dies.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700892 */
893 public Builder penaltyDeath() {
894 return enable(PENALTY_DEATH);
895 }
896
897 /**
Jeff Sharkey605eb792014-11-04 13:34:06 -0800898 * Crashes the whole process when cleartext network traffic is
899 * detected.
900 *
901 * @see #detectCleartextNetwork()
Jeff Sharkey605eb792014-11-04 13:34:06 -0800902 */
903 public Builder penaltyDeathOnCleartextNetwork() {
904 return enable(PENALTY_DEATH_ON_CLEARTEXT_NETWORK);
905 }
906
907 /**
Jeff Sharkey344744b2016-01-28 19:03:30 -0700908 * Crashes the whole process when a {@code file://}
909 * {@link android.net.Uri} is exposed beyond this app.
910 *
911 * @see #detectFileUriExposure()
912 */
913 public Builder penaltyDeathOnFileUriExposure() {
914 return enable(PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
915 }
916
917 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700918 * Log detected violations to the system log.
919 */
920 public Builder penaltyLog() {
921 return enable(PENALTY_LOG);
922 }
923
924 /**
925 * Enable detected violations log a stacktrace and timing data
926 * to the {@link android.os.DropBoxManager DropBox} on policy
927 * violation. Intended mostly for platform integrators doing
928 * beta user field data collection.
929 */
930 public Builder penaltyDropBox() {
931 return enable(PENALTY_DROPBOX);
932 }
933
934 private Builder enable(int bit) {
935 mMask |= bit;
936 return this;
937 }
938
Mathieu Chartierca8c1052017-06-19 18:42:57 -0700939 Builder disable(int bit) {
940 mMask &= ~bit;
941 return this;
942 }
943
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700944 /**
945 * Construct the VmPolicy instance.
946 *
947 * <p>Note: if no penalties are enabled before calling
948 * <code>build</code>, {@link #penaltyLog} is implicitly
949 * set.
950 */
951 public VmPolicy build() {
952 // If there are detection bits set but no violation bits
953 // set, enable simple logging.
954 if (mMask != 0 &&
955 (mMask & (PENALTY_DEATH | PENALTY_LOG |
956 PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
957 penaltyLog();
958 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800959 return new VmPolicy(mMask,
960 mClassInstanceLimit != null ? mClassInstanceLimit : EMPTY_CLASS_LIMIT_MAP);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700961 }
962 }
963 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700964
965 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700966 * Log of strict mode violation stack traces that have occurred
967 * during a Binder call, to be serialized back later to the caller
968 * via Parcel.writeNoException() (amusingly) where the caller can
969 * choose how to react.
970 */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -0700971 private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
972 new ThreadLocal<ArrayList<ViolationInfo>>() {
973 @Override protected ArrayList<ViolationInfo> initialValue() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700974 // Starts null to avoid unnecessary allocations when
975 // checking whether there are any violations or not in
976 // hasGatheredViolations() below.
977 return null;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -0700978 }
979 };
980
981 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700982 * Sets the policy for what actions on the current thread should
983 * be detected, as well as the penalty if such actions occur.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700984 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700985 * <p>Internally this sets a thread-local variable which is
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700986 * propagated across cross-process IPC calls, meaning you can
987 * catch violations when a system service or another process
988 * accesses the disk or network on your behalf.
989 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700990 * @param policy the policy to put into place
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700991 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700992 public static void setThreadPolicy(final ThreadPolicy policy) {
993 setThreadPolicyMask(policy.mask);
994 }
995
996 private static void setThreadPolicyMask(final int policyMask) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700997 // In addition to the Java-level thread-local in Dalvik's
998 // BlockGuard, we also need to keep a native thread-local in
999 // Binder in order to propagate the value across Binder calls,
1000 // even across native-only processes. The two are kept in
1001 // sync via the callback to onStrictModePolicyChange, below.
1002 setBlockGuardPolicy(policyMask);
1003
1004 // And set the Android native version...
1005 Binder.setThreadStrictModePolicy(policyMask);
1006 }
1007
1008 // Sets the policy in Dalvik/libcore (BlockGuard)
1009 private static void setBlockGuardPolicy(final int policyMask) {
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001010 if (policyMask == 0) {
1011 BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
1012 return;
1013 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001014 final BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1015 final AndroidBlockGuardPolicy androidPolicy;
1016 if (policy instanceof AndroidBlockGuardPolicy) {
1017 androidPolicy = (AndroidBlockGuardPolicy) policy;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001018 } else {
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001019 androidPolicy = threadAndroidPolicy.get();
1020 BlockGuard.setThreadPolicy(androidPolicy);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001021 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001022 androidPolicy.setPolicyMask(policyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001023 }
1024
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001025 // Sets up CloseGuard in Dalvik/libcore
1026 private static void setCloseGuardEnabled(boolean enabled) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -08001027 if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001028 CloseGuard.setReporter(new AndroidCloseGuardReporter());
1029 }
1030 CloseGuard.setEnabled(enabled);
1031 }
1032
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001033 /**
1034 * @hide
1035 */
1036 public static class StrictModeViolation extends BlockGuard.BlockGuardPolicyException {
1037 public StrictModeViolation(int policyState, int policyViolated, String message) {
1038 super(policyState, policyViolated, message);
1039 }
1040 }
1041
1042 /**
1043 * @hide
1044 */
1045 public static class StrictModeNetworkViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001046 public StrictModeNetworkViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001047 super(policyMask, DETECT_NETWORK, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001048 }
1049 }
1050
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001051 /**
1052 * @hide
1053 */
1054 private static class StrictModeDiskReadViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001055 public StrictModeDiskReadViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001056 super(policyMask, DETECT_DISK_READ, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001057 }
1058 }
1059
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001060 /**
1061 * @hide
1062 */
1063 private static class StrictModeDiskWriteViolation extends StrictModeViolation {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001064 public StrictModeDiskWriteViolation(int policyMask) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001065 super(policyMask, DETECT_DISK_WRITE, null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001066 }
1067 }
1068
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001069 /**
1070 * @hide
1071 */
1072 private static class StrictModeCustomViolation extends StrictModeViolation {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001073 public StrictModeCustomViolation(int policyMask, String name) {
1074 super(policyMask, DETECT_CUSTOM, name);
1075 }
1076 }
1077
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001078 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001079 * @hide
1080 */
1081 private static class StrictModeResourceMismatchViolation extends StrictModeViolation {
1082 public StrictModeResourceMismatchViolation(int policyMask, Object tag) {
1083 super(policyMask, DETECT_RESOURCE_MISMATCH, tag != null ? tag.toString() : null);
1084 }
1085 }
1086
1087 /**
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001088 * @hide
1089 */
1090 private static class StrictModeUnbufferedIOViolation extends StrictModeViolation {
1091 public StrictModeUnbufferedIOViolation(int policyMask) {
1092 super(policyMask, DETECT_UNBUFFERED_IO, null);
1093 }
1094 }
1095
1096 /**
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -07001097 * Returns the bitmask of the current thread's policy.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001098 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001099 * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
1100 *
1101 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001102 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001103 public static int getThreadPolicyMask() {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001104 return BlockGuard.getThreadPolicy().getPolicyMask();
1105 }
1106
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001107 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001108 * Returns the current thread's policy.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001109 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001110 public static ThreadPolicy getThreadPolicy() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001111 // TODO: this was a last minute Gingerbread API change (to
1112 // introduce VmPolicy cleanly) but this isn't particularly
1113 // optimal for users who might call this method often. This
1114 // should be in a thread-local and not allocate on each call.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001115 return new ThreadPolicy(getThreadPolicyMask());
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001116 }
1117
1118 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001119 * A convenience wrapper that takes the current
1120 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
1121 * to permit both disk reads &amp; writes, and sets the new policy
1122 * with {@link #setThreadPolicy}, returning the old policy so you
1123 * can restore it at the end of a block.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001124 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001125 * @return the old policy, to be passed to {@link #setThreadPolicy} to
1126 * restore the policy at the end of a block
1127 */
1128 public static ThreadPolicy allowThreadDiskWrites() {
1129 int oldPolicyMask = getThreadPolicyMask();
1130 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
1131 if (newPolicyMask != oldPolicyMask) {
1132 setThreadPolicyMask(newPolicyMask);
1133 }
1134 return new ThreadPolicy(oldPolicyMask);
1135 }
1136
1137 /**
1138 * A convenience wrapper that takes the current
1139 * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
1140 * to permit disk reads, and sets the new policy
1141 * with {@link #setThreadPolicy}, returning the old policy so you
1142 * can restore it at the end of a block.
1143 *
1144 * @return the old policy, to be passed to setThreadPolicy to
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001145 * restore the policy.
1146 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001147 public static ThreadPolicy allowThreadDiskReads() {
1148 int oldPolicyMask = getThreadPolicyMask();
1149 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
1150 if (newPolicyMask != oldPolicyMask) {
1151 setThreadPolicyMask(newPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001152 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001153 return new ThreadPolicy(oldPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001154 }
1155
Brad Fitzpatrickf5454592010-11-24 15:27:51 -08001156 // We don't want to flash the screen red in the system server
1157 // process, nor do we want to modify all the call sites of
1158 // conditionallyEnableDebugLogging() in the system server,
1159 // so instead we use this to determine if we are the system server.
1160 private static boolean amTheSystemServerProcess() {
1161 // Fast path. Most apps don't have the system server's UID.
1162 if (Process.myUid() != Process.SYSTEM_UID) {
1163 return false;
1164 }
1165
1166 // The settings app, though, has the system server's UID so
1167 // look up our stack to see if we came from the system server.
1168 Throwable stack = new Throwable();
1169 stack.fillInStackTrace();
1170 for (StackTraceElement ste : stack.getStackTrace()) {
1171 String clsName = ste.getClassName();
1172 if (clsName != null && clsName.startsWith("com.android.server.")) {
1173 return true;
1174 }
1175 }
1176 return false;
1177 }
1178
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001179 /**
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001180 * Enable DropBox logging for debug phone builds.
1181 *
1182 * @hide
1183 */
1184 public static boolean conditionallyEnableDebugLogging() {
Christopher Tatebc6f0ce2011-11-03 12:18:43 -07001185 boolean doFlashes = SystemProperties.getBoolean(VISUAL_PROPERTY, false)
1186 && !amTheSystemServerProcess();
1187 final boolean suppress = SystemProperties.getBoolean(DISABLE_PROPERTY, false);
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001188
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001189 // For debug builds, log event loop stalls to dropbox for analysis.
1190 // Similar logic also appears in ActivityThread.java for system apps.
Jeff Sharkey5ab02432017-06-27 11:01:36 -06001191 if (!doFlashes && (Build.IS_USER || suppress)) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -08001192 setCloseGuardEnabled(false);
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001193 return false;
1194 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001195
Christopher Tatebc6f0ce2011-11-03 12:18:43 -07001196 // Eng builds have flashes on all the time. The suppression property
1197 // overrides this, so we force the behavior only after the short-circuit
1198 // check above.
Jeff Sharkey5ab02432017-06-27 11:01:36 -06001199 if (Build.IS_ENG) {
Christopher Tatebc6f0ce2011-11-03 12:18:43 -07001200 doFlashes = true;
1201 }
1202
Jeff Brownbe7c29c2011-10-11 11:35:23 -07001203 // Thread policy controls BlockGuard.
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001204 int threadPolicyMask = StrictMode.DETECT_DISK_WRITE |
1205 StrictMode.DETECT_DISK_READ |
1206 StrictMode.DETECT_NETWORK;
1207
Jeff Sharkey5ab02432017-06-27 11:01:36 -06001208 if (!Build.IS_USER) {
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001209 threadPolicyMask |= StrictMode.PENALTY_DROPBOX;
1210 }
1211 if (doFlashes) {
1212 threadPolicyMask |= StrictMode.PENALTY_FLASH;
1213 }
1214
1215 StrictMode.setThreadPolicyMask(threadPolicyMask);
1216
Jeff Brownbe7c29c2011-10-11 11:35:23 -07001217 // VM Policy controls CloseGuard, detection of Activity leaks,
1218 // and instance counting.
Jeff Sharkey5ab02432017-06-27 11:01:36 -06001219 if (Build.IS_USER) {
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001220 setCloseGuardEnabled(false);
1221 } else {
Mathieu Chartierca8c1052017-06-19 18:42:57 -07001222 VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll();
Jeff Sharkey5ab02432017-06-27 11:01:36 -06001223 if (!Build.IS_ENG) {
Mathieu Chartierca8c1052017-06-19 18:42:57 -07001224 // Activity leak detection causes too much slowdown for userdebug because of the
1225 // GCs.
1226 policyBuilder = policyBuilder.disable(DETECT_VM_ACTIVITY_LEAKS);
1227 }
1228 policyBuilder = policyBuilder.penaltyDropBox();
Jeff Sharkey5ab02432017-06-27 11:01:36 -06001229 if (Build.IS_ENG) {
Jeff Brownd5875d92011-10-09 14:59:37 -07001230 policyBuilder.penaltyLog();
1231 }
Jeff Sharkey619a5112017-01-19 11:55:54 -07001232 // All core system components need to tag their sockets to aid
1233 // system health investigations
1234 if (android.os.Process.myUid() < android.os.Process.FIRST_APPLICATION_UID) {
Jeff Sharkey5ab02432017-06-27 11:01:36 -06001235 policyBuilder.enable(DETECT_VM_UNTAGGED_SOCKET);
1236 } else {
1237 policyBuilder.disable(DETECT_VM_UNTAGGED_SOCKET);
Jeff Sharkey619a5112017-01-19 11:55:54 -07001238 }
Jeff Brownd5875d92011-10-09 14:59:37 -07001239 setVmPolicy(policyBuilder.build());
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001240 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
1241 }
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001242 return true;
1243 }
1244
1245 /**
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001246 * Used by the framework to make network usage on the main
1247 * thread a fatal error.
1248 *
1249 * @hide
1250 */
1251 public static void enableDeathOnNetwork() {
1252 int oldPolicy = getThreadPolicyMask();
1253 int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
1254 setThreadPolicyMask(newPolicy);
1255 }
1256
1257 /**
Jeff Sharkey344744b2016-01-28 19:03:30 -07001258 * Used by the framework to make file usage a fatal error.
1259 *
1260 * @hide
1261 */
1262 public static void enableDeathOnFileUriExposure() {
1263 sVmPolicyMask |= DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
1264 }
1265
1266 /**
1267 * Used by lame internal apps that haven't done the hard work to get
1268 * themselves off file:// Uris yet.
1269 *
1270 * @hide
1271 */
1272 public static void disableDeathOnFileUriExposure() {
1273 sVmPolicyMask &= ~(DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
1274 }
1275
1276 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001277 * Parses the BlockGuard policy mask out from the Exception's
1278 * getMessage() String value. Kinda gross, but least
1279 * invasive. :/
1280 *
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001281 * Input is of the following forms:
1282 * "policy=137 violation=64"
1283 * "policy=137 violation=64 msg=Arbitrary text"
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001284 *
1285 * Returns 0 on failure, which is a valid policy, but not a
1286 * valid policy during a violation (else there must've been
1287 * some policy in effect to violate).
1288 */
1289 private static int parsePolicyFromMessage(String message) {
1290 if (message == null || !message.startsWith("policy=")) {
1291 return 0;
1292 }
1293 int spaceIndex = message.indexOf(' ');
1294 if (spaceIndex == -1) {
1295 return 0;
1296 }
1297 String policyString = message.substring(7, spaceIndex);
1298 try {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001299 return Integer.parseInt(policyString);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001300 } catch (NumberFormatException e) {
1301 return 0;
1302 }
1303 }
1304
1305 /**
1306 * Like parsePolicyFromMessage(), but returns the violation.
1307 */
1308 private static int parseViolationFromMessage(String message) {
1309 if (message == null) {
1310 return 0;
1311 }
1312 int violationIndex = message.indexOf("violation=");
1313 if (violationIndex == -1) {
1314 return 0;
1315 }
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001316 int numberStartIndex = violationIndex + "violation=".length();
1317 int numberEndIndex = message.indexOf(' ', numberStartIndex);
1318 if (numberEndIndex == -1) {
1319 numberEndIndex = message.length();
1320 }
1321 String violationString = message.substring(numberStartIndex, numberEndIndex);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001322 try {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001323 return Integer.parseInt(violationString);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001324 } catch (NumberFormatException e) {
1325 return 0;
1326 }
1327 }
1328
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001329 private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
1330 new ThreadLocal<ArrayList<ViolationInfo>>() {
1331 @Override protected ArrayList<ViolationInfo> initialValue() {
1332 return new ArrayList<ViolationInfo>();
1333 }
1334 };
1335
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001336 // Note: only access this once verifying the thread has a Looper.
1337 private static final ThreadLocal<Handler> threadHandler = new ThreadLocal<Handler>() {
1338 @Override protected Handler initialValue() {
1339 return new Handler();
1340 }
1341 };
1342
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001343 private static final ThreadLocal<AndroidBlockGuardPolicy>
1344 threadAndroidPolicy = new ThreadLocal<AndroidBlockGuardPolicy>() {
1345 @Override
1346 protected AndroidBlockGuardPolicy initialValue() {
1347 return new AndroidBlockGuardPolicy(0);
1348 }
1349 };
1350
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001351 private static boolean tooManyViolationsThisLoop() {
1352 return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
1353 }
1354
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001355 private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
1356 private int mPolicyMask;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001357
1358 // Map from violation stacktrace hashcode -> uptimeMillis of
1359 // last violation. No locking needed, as this is only
1360 // accessed by the same thread.
Dianne Hackborn390517b2013-05-30 15:03:32 -07001361 private ArrayMap<Integer, Long> mLastViolationTime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001362
1363 public AndroidBlockGuardPolicy(final int policyMask) {
1364 mPolicyMask = policyMask;
1365 }
1366
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001367 @Override
1368 public String toString() {
1369 return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
1370 }
1371
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001372 // Part of BlockGuard.Policy interface:
1373 public int getPolicyMask() {
1374 return mPolicyMask;
1375 }
1376
1377 // Part of BlockGuard.Policy interface:
1378 public void onWriteToDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001379 if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001380 return;
1381 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001382 if (tooManyViolationsThisLoop()) {
1383 return;
1384 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001385 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
1386 e.fillInStackTrace();
1387 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001388 }
1389
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001390 // Not part of BlockGuard.Policy; just part of StrictMode:
1391 void onCustomSlowCall(String name) {
1392 if ((mPolicyMask & DETECT_CUSTOM) == 0) {
1393 return;
1394 }
1395 if (tooManyViolationsThisLoop()) {
1396 return;
1397 }
1398 BlockGuard.BlockGuardPolicyException e = new StrictModeCustomViolation(mPolicyMask, name);
1399 e.fillInStackTrace();
1400 startHandlingViolationException(e);
1401 }
1402
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001403 // Not part of BlockGuard.Policy; just part of StrictMode:
1404 void onResourceMismatch(Object tag) {
1405 if ((mPolicyMask & DETECT_RESOURCE_MISMATCH) == 0) {
1406 return;
1407 }
1408 if (tooManyViolationsThisLoop()) {
1409 return;
1410 }
1411 BlockGuard.BlockGuardPolicyException e =
1412 new StrictModeResourceMismatchViolation(mPolicyMask, tag);
1413 e.fillInStackTrace();
1414 startHandlingViolationException(e);
1415 }
1416
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001417 // Part of BlockGuard.Policy; just part of StrictMode:
1418 public void onUnbufferedIO() {
1419 if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
1420 return;
1421 }
1422 if (tooManyViolationsThisLoop()) {
1423 return;
1424 }
1425 BlockGuard.BlockGuardPolicyException e =
1426 new StrictModeUnbufferedIOViolation(mPolicyMask);
1427 e.fillInStackTrace();
1428 startHandlingViolationException(e);
1429 }
1430
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001431 // Part of BlockGuard.Policy interface:
1432 public void onReadFromDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001433 if ((mPolicyMask & DETECT_DISK_READ) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001434 return;
1435 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001436 if (tooManyViolationsThisLoop()) {
1437 return;
1438 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001439 BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
1440 e.fillInStackTrace();
1441 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001442 }
1443
1444 // Part of BlockGuard.Policy interface:
1445 public void onNetwork() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001446 if ((mPolicyMask & DETECT_NETWORK) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001447 return;
1448 }
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001449 if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
1450 throw new NetworkOnMainThreadException();
1451 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001452 if (tooManyViolationsThisLoop()) {
1453 return;
1454 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001455 BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
1456 e.fillInStackTrace();
1457 startHandlingViolationException(e);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001458 }
1459
1460 public void setPolicyMask(int policyMask) {
1461 mPolicyMask = policyMask;
1462 }
1463
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001464 // Start handling a violation that just started and hasn't
1465 // actually run yet (e.g. no disk write or network operation
1466 // has yet occurred). This sees if we're in an event loop
1467 // thread and, if so, uses it to roughly measure how long the
1468 // violation took.
1469 void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001470 final ViolationInfo info = new ViolationInfo(e, e.getPolicy());
1471 info.violationUptimeMillis = SystemClock.uptimeMillis();
1472 handleViolationWithTimingAttempt(info);
1473 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001474
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001475 // Attempts to fill in the provided ViolationInfo's
1476 // durationMillis field if this thread has a Looper we can use
1477 // to measure with. We measure from the time of violation
1478 // until the time the looper is idle again (right before
1479 // the next epoll_wait)
1480 void handleViolationWithTimingAttempt(final ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001481 Looper looper = Looper.myLooper();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001482
1483 // Without a Looper, we're unable to time how long the
1484 // violation takes place. This case should be rare, as
1485 // most users will care about timing violations that
1486 // happen on their main UI thread. Note that this case is
1487 // also hit when a violation takes place in a Binder
1488 // thread, in "gather" mode. In this case, the duration
1489 // of the violation is computed by the ultimate caller and
1490 // its Looper, if any.
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001491 //
1492 // Also, as a special short-cut case when the only penalty
1493 // bit is death, we die immediately, rather than timing
1494 // the violation's duration. This makes it convenient to
1495 // use in unit tests too, rather than waiting on a Looper.
1496 //
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001497 // TODO: if in gather mode, ignore Looper.myLooper() and always
1498 // go into this immediate mode?
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001499 if (looper == null ||
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001500 (info.policy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001501 info.durationMillis = -1; // unknown (redundant, already set)
1502 handleViolation(info);
1503 return;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001504 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001505
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001506 final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001507 if (records.size() >= MAX_OFFENSES_PER_LOOP) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001508 // Not worth measuring. Too many offenses in one loop.
1509 return;
1510 }
1511 records.add(info);
1512 if (records.size() > 1) {
1513 // There's already been a violation this loop, so we've already
1514 // registered an idle handler to process the list of violations
1515 // at the end of this Looper's loop.
1516 return;
1517 }
1518
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001519 final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ?
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08001520 sWindowManager.get() : null;
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001521 if (windowManager != null) {
1522 try {
1523 windowManager.showStrictModeViolation(true);
1524 } catch (RemoteException unused) {
1525 }
1526 }
1527
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001528 // We post a runnable to a Handler (== delay 0 ms) for
1529 // measuring the end time of a violation instead of using
1530 // an IdleHandler (as was previously used) because an
1531 // IdleHandler may not run for quite a long period of time
1532 // if an ongoing animation is happening and continually
1533 // posting ASAP (0 ms) animation steps. Animations are
1534 // throttled back to 60fps via SurfaceFlinger/View
1535 // invalidates, _not_ by posting frame updates every 16
1536 // milliseconds.
Jeff Sharkey3761f332012-03-16 15:46:46 -07001537 threadHandler.get().postAtFrontOfQueue(new Runnable() {
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001538 public void run() {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001539 long loopFinishTime = SystemClock.uptimeMillis();
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001540
1541 // Note: we do this early, before handling the
1542 // violation below, as handling the violation
1543 // may include PENALTY_DEATH and we don't want
1544 // to keep the red border on.
1545 if (windowManager != null) {
1546 try {
1547 windowManager.showStrictModeViolation(false);
1548 } catch (RemoteException unused) {
1549 }
1550 }
1551
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001552 for (int n = 0; n < records.size(); ++n) {
1553 ViolationInfo v = records.get(n);
1554 v.violationNumThisLoop = n + 1;
1555 v.durationMillis =
1556 (int) (loopFinishTime - v.violationUptimeMillis);
1557 handleViolation(v);
1558 }
1559 records.clear();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001560 }
1561 });
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001562 }
1563
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001564 // Note: It's possible (even quite likely) that the
1565 // thread-local policy mask has changed from the time the
1566 // violation fired and now (after the violating code ran) due
1567 // to people who push/pop temporary policy in regions of code,
1568 // hence the policy being passed around.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001569 void handleViolation(final ViolationInfo info) {
1570 if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) {
1571 Log.wtf(TAG, "unexpected null stacktrace");
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001572 return;
1573 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001574
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001575 if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001576
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001577 if ((info.policy & PENALTY_GATHER) != 0) {
1578 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001579 if (violations == null) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001580 violations = new ArrayList<ViolationInfo>(1);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001581 gatheredViolations.set(violations);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001582 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001583 for (ViolationInfo previous : violations) {
1584 if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001585 // Duplicate. Don't log.
1586 return;
1587 }
1588 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001589 violations.add(info);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001590 return;
1591 }
1592
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001593 // Not perfect, but fast and good enough for dup suppression.
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08001594 Integer crashFingerprint = info.hashCode();
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001595 long lastViolationTime = 0;
Dianne Hackborn390517b2013-05-30 15:03:32 -07001596 if (mLastViolationTime != null) {
1597 Long vtime = mLastViolationTime.get(crashFingerprint);
1598 if (vtime != null) {
1599 lastViolationTime = vtime;
1600 }
1601 } else {
1602 mLastViolationTime = new ArrayMap<Integer, Long>(1);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001603 }
1604 long now = SystemClock.uptimeMillis();
1605 mLastViolationTime.put(crashFingerprint, now);
1606 long timeSinceLastViolationMillis = lastViolationTime == 0 ?
1607 Long.MAX_VALUE : (now - lastViolationTime);
1608
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -06001609 if ((info.policy & PENALTY_LOG) != 0 && sListener != null) {
1610 sListener.onViolation(info.crashInfo.stackTrace);
1611 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001612 if ((info.policy & PENALTY_LOG) != 0 &&
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001613 timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001614 if (info.durationMillis != -1) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001615 Log.d(TAG, "StrictMode policy violation; ~duration=" +
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001616 info.durationMillis + " ms: " + info.crashInfo.stackTrace);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001617 } else {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001618 Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001619 }
1620 }
1621
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001622 // The violationMaskSubset, passed to ActivityManager, is a
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001623 // subset of the original StrictMode policy bitmask, with
1624 // only the bit violated and penalty bits to be executed
1625 // by the ActivityManagerService remaining set.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001626 int violationMaskSubset = 0;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001627
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001628 if ((info.policy & PENALTY_DIALOG) != 0 &&
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001629 timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001630 violationMaskSubset |= PENALTY_DIALOG;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001631 }
1632
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001633 if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
1634 violationMaskSubset |= PENALTY_DROPBOX;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001635 }
1636
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001637 if (violationMaskSubset != 0) {
1638 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1639 violationMaskSubset |= violationBit;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001640 final int savedPolicyMask = getThreadPolicyMask();
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001641
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001642 final boolean justDropBox = (info.policy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001643 if (justDropBox) {
1644 // If all we're going to ask the activity manager
1645 // to do is dropbox it (the common case during
1646 // platform development), we can avoid doing this
1647 // call synchronously which Binder data suggests
1648 // isn't always super fast, despite the implementation
1649 // in the ActivityManager trying to be mostly async.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001650 dropboxViolationAsync(violationMaskSubset, info);
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001651 return;
1652 }
1653
1654 // Normal synchronous call to the ActivityManager.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001655 try {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001656 // First, remove any policy before we call into the Activity Manager,
1657 // otherwise we'll infinite recurse as we try to log policy violations
1658 // to disk, thus violating policy, thus requiring logging, etc...
1659 // We restore the current policy below, in the finally block.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001660 setThreadPolicyMask(0);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001661
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07001662 ActivityManager.getService().handleApplicationStrictModeViolation(
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001663 RuntimeInit.getApplicationObject(),
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001664 violationMaskSubset,
1665 info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001666 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001667 if (e instanceof DeadObjectException) {
1668 // System process is dead; ignore
1669 } else {
1670 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
1671 }
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001672 } finally {
1673 // Restore the policy.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001674 setThreadPolicyMask(savedPolicyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001675 }
1676 }
1677
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001678 if ((info.policy & PENALTY_DEATH) != 0) {
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001679 executeDeathPenalty(info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001680 }
1681 }
1682 }
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001683
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001684 private static void executeDeathPenalty(ViolationInfo info) {
1685 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
1686 throw new StrictModeViolation(info.policy, violationBit, null);
1687 }
1688
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001689 /**
1690 * In the common case, as set by conditionallyEnableDebugLogging,
1691 * we're just dropboxing any violations but not showing a dialog,
1692 * not loggging, and not killing the process. In these cases we
1693 * don't need to do a synchronous call to the ActivityManager.
1694 * This is used by both per-thread and vm-wide violations when
1695 * applicable.
1696 */
1697 private static void dropboxViolationAsync(
1698 final int violationMaskSubset, final ViolationInfo info) {
1699 int outstanding = sDropboxCallsInFlight.incrementAndGet();
1700 if (outstanding > 20) {
1701 // What's going on? Let's not make make the situation
1702 // worse and just not log.
1703 sDropboxCallsInFlight.decrementAndGet();
1704 return;
1705 }
1706
1707 if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1708
1709 new Thread("callActivityManagerForStrictModeDropbox") {
1710 public void run() {
1711 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1712 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001713 IActivityManager am = ActivityManager.getService();
Brad Fitzpatrick10656852010-11-23 19:01:13 -08001714 if (am == null) {
1715 Log.d(TAG, "No activity manager; failed to Dropbox violation.");
1716 } else {
1717 am.handleApplicationStrictModeViolation(
1718 RuntimeInit.getApplicationObject(),
1719 violationMaskSubset,
1720 info);
1721 }
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001722 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001723 if (e instanceof DeadObjectException) {
1724 // System process is dead; ignore
1725 } else {
1726 Log.e(TAG, "RemoteException handling StrictMode violation", e);
1727 }
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001728 }
1729 int outstanding = sDropboxCallsInFlight.decrementAndGet();
1730 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
1731 }
1732 }.start();
1733 }
1734
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001735 private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
Jeff Sharkey605eb792014-11-04 13:34:06 -08001736 public void report(String message, Throwable allocationSite) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001737 onVmPolicyViolation(message, allocationSite);
1738 }
1739 }
1740
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001741 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001742 * Called from Parcel.writeNoException()
1743 */
1744 /* package */ static boolean hasGatheredViolations() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001745 return gatheredViolations.get() != null;
1746 }
1747
1748 /**
1749 * Called from Parcel.writeException(), so we drop this memory and
1750 * don't incorrectly attribute it to the wrong caller on the next
1751 * Binder call on this thread.
1752 */
1753 /* package */ static void clearGatheredViolations() {
1754 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001755 }
1756
1757 /**
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001758 * @hide
1759 */
1760 public static void conditionallyCheckInstanceCounts() {
1761 VmPolicy policy = getVmPolicy();
Mathieu Chartierd288a262015-07-10 13:44:42 -07001762 int policySize = policy.classInstanceLimit.size();
1763 if (policySize == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001764 return;
1765 }
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08001766
1767 System.gc();
1768 System.runFinalization();
1769 System.gc();
1770
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001771 // Note: classInstanceLimit is immutable, so this is lock-free
Mathieu Chartierd288a262015-07-10 13:44:42 -07001772 // Create the classes array.
1773 Class[] classes = policy.classInstanceLimit.keySet().toArray(new Class[policySize]);
1774 long[] instanceCounts = VMDebug.countInstancesOfClasses(classes, false);
1775 for (int i = 0; i < classes.length; ++i) {
1776 Class klass = classes[i];
1777 int limit = policy.classInstanceLimit.get(klass);
1778 long instances = instanceCounts[i];
1779 if (instances > limit) {
1780 Throwable tr = new InstanceCountViolation(klass, instances, limit);
1781 onVmPolicyViolation(tr.getMessage(), tr);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001782 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001783 }
1784 }
1785
1786 private static long sLastInstanceCountCheckMillis = 0;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001787 private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001788 private static final MessageQueue.IdleHandler sProcessIdleHandler =
1789 new MessageQueue.IdleHandler() {
1790 public boolean queueIdle() {
1791 long now = SystemClock.uptimeMillis();
1792 if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1793 sLastInstanceCountCheckMillis = now;
1794 conditionallyCheckInstanceCounts();
1795 }
1796 return true;
1797 }
1798 };
1799
1800 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001801 * Sets the policy for what actions in the VM process (on any
1802 * thread) should be detected, as well as the penalty if such
1803 * actions occur.
1804 *
1805 * @param policy the policy to put into place
1806 */
1807 public static void setVmPolicy(final VmPolicy policy) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001808 synchronized (StrictMode.class) {
1809 sVmPolicy = policy;
1810 sVmPolicyMask = policy.mask;
1811 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001812
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001813 Looper looper = Looper.getMainLooper();
1814 if (looper != null) {
1815 MessageQueue mq = looper.mQueue;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001816 if (policy.classInstanceLimit.size() == 0 ||
1817 (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001818 mq.removeIdleHandler(sProcessIdleHandler);
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001819 sIsIdlerRegistered = false;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001820 } else if (!sIsIdlerRegistered) {
1821 mq.addIdleHandler(sProcessIdleHandler);
1822 sIsIdlerRegistered = true;
1823 }
1824 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08001825
1826 int networkPolicy = NETWORK_POLICY_ACCEPT;
1827 if ((sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
1828 if ((sVmPolicyMask & PENALTY_DEATH) != 0
1829 || (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
1830 networkPolicy = NETWORK_POLICY_REJECT;
1831 } else {
1832 networkPolicy = NETWORK_POLICY_LOG;
1833 }
1834 }
1835
1836 final INetworkManagementService netd = INetworkManagementService.Stub.asInterface(
1837 ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
1838 if (netd != null) {
1839 try {
1840 netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
1841 } catch (RemoteException ignored) {
1842 }
1843 } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
1844 Log.w(TAG, "Dropping requested network policy due to missing service!");
1845 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001846 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001847 }
1848
1849 /**
1850 * Gets the current VM policy.
1851 */
1852 public static VmPolicy getVmPolicy() {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001853 synchronized (StrictMode.class) {
1854 return sVmPolicy;
1855 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001856 }
1857
1858 /**
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001859 * Enable the recommended StrictMode defaults, with violations just being logged.
1860 *
1861 * <p>This catches disk and network access on the main thread, as
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001862 * well as leaked SQLite cursors and unclosed resources. This is
1863 * simply a wrapper around {@link #setVmPolicy} and {@link
1864 * #setThreadPolicy}.
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001865 */
1866 public static void enableDefaults() {
1867 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
1868 .detectAll()
1869 .penaltyLog()
1870 .build());
1871 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001872 .detectAll()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001873 .penaltyLog()
1874 .build());
1875 }
1876
1877 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001878 * @hide
1879 */
1880 public static boolean vmSqliteObjectLeaksEnabled() {
1881 return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
1882 }
1883
1884 /**
1885 * @hide
1886 */
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001887 public static boolean vmClosableObjectLeaksEnabled() {
1888 return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
1889 }
1890
1891 /**
1892 * @hide
1893 */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001894 public static boolean vmRegistrationLeaksEnabled() {
1895 return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
1896 }
1897
1898 /**
1899 * @hide
1900 */
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001901 public static boolean vmFileUriExposureEnabled() {
1902 return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
1903 }
1904
1905 /**
1906 * @hide
1907 */
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -07001908 public static boolean vmCleartextNetworkEnabled() {
1909 return (sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07001910 }
1911
1912 /**
1913 * @hide
1914 */
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -07001915 public static boolean vmContentUriWithoutPermissionEnabled() {
1916 return (sVmPolicyMask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
Jeff Sharkey605eb792014-11-04 13:34:06 -08001917 }
1918
1919 /**
1920 * @hide
1921 */
Jeff Sharkey619a5112017-01-19 11:55:54 -07001922 public static boolean vmUntaggedSocketEnabled() {
1923 return (sVmPolicyMask & DETECT_VM_UNTAGGED_SOCKET) != 0;
1924 }
1925
1926 /**
1927 * @hide
1928 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001929 public static void onSqliteObjectLeaked(String message, Throwable originStack) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001930 onVmPolicyViolation(message, originStack);
1931 }
1932
Steve Block08d584c2011-05-17 19:05:03 +01001933 /**
1934 * @hide
1935 */
1936 public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
1937 onVmPolicyViolation(null, originStack);
1938 }
1939
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001940 /**
1941 * @hide
1942 */
1943 public static void onIntentReceiverLeaked(Throwable originStack) {
1944 onVmPolicyViolation(null, originStack);
1945 }
1946
1947 /**
1948 * @hide
1949 */
1950 public static void onServiceConnectionLeaked(Throwable originStack) {
1951 onVmPolicyViolation(null, originStack);
1952 }
1953
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001954 /**
1955 * @hide
1956 */
Jeff Sharkey344744b2016-01-28 19:03:30 -07001957 public static void onFileUriExposed(Uri uri, String location) {
1958 final String message = uri + " exposed beyond app through " + location;
1959 if ((sVmPolicyMask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
1960 throw new FileUriExposedException(message);
1961 } else {
1962 onVmPolicyViolation(null, new Throwable(message));
1963 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08001964 }
1965
1966 /**
1967 * @hide
1968 */
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07001969 public static void onContentUriWithoutPermission(Uri uri, String location) {
1970 final String message = uri + " exposed beyond app through " + location
1971 + " without permission grant flags; did you forget"
1972 + " FLAG_GRANT_READ_URI_PERMISSION?";
1973 onVmPolicyViolation(null, new Throwable(message));
1974 }
1975
1976 /**
1977 * @hide
1978 */
Jeff Sharkey605eb792014-11-04 13:34:06 -08001979 public static void onCleartextNetworkDetected(byte[] firstPacket) {
1980 byte[] rawAddr = null;
1981 if (firstPacket != null) {
1982 if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
1983 // IPv4
1984 rawAddr = new byte[4];
1985 System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
1986 } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
1987 // IPv6
1988 rawAddr = new byte[16];
1989 System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
1990 }
1991 }
1992
1993 final int uid = android.os.Process.myUid();
1994 String msg = "Detected cleartext network traffic from UID " + uid;
1995 if (rawAddr != null) {
1996 try {
1997 msg = "Detected cleartext network traffic from UID " + uid + " to "
1998 + InetAddress.getByAddress(rawAddr);
1999 } catch (UnknownHostException ignored) {
2000 }
2001 }
2002
2003 final boolean forceDeath = (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
2004 onVmPolicyViolation(HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg),
2005 forceDeath);
Jeff Sharkeya14acd22013-04-02 18:27:45 -07002006 }
2007
Jeff Sharkey619a5112017-01-19 11:55:54 -07002008 /**
2009 * @hide
2010 */
2011 public static void onUntaggedSocket() {
2012 onVmPolicyViolation(null, new Throwable("Untagged socket detected; use"
2013 + " TrafficStats.setThreadSocketTag() to track all network usage"));
2014 }
2015
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002016 // Map from VM violation fingerprint to uptime millis.
2017 private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
2018
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08002019 /**
2020 * @hide
2021 */
2022 public static void onVmPolicyViolation(String message, Throwable originStack) {
Jeff Sharkey605eb792014-11-04 13:34:06 -08002023 onVmPolicyViolation(message, originStack, false);
2024 }
2025
2026 /**
2027 * @hide
2028 */
2029 public static void onVmPolicyViolation(String message, Throwable originStack,
2030 boolean forceDeath) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002031 final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
Jeff Sharkey605eb792014-11-04 13:34:06 -08002032 final boolean penaltyDeath = ((sVmPolicyMask & PENALTY_DEATH) != 0) || forceDeath;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002033 final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
Jeff Sharkey605eb792014-11-04 13:34:06 -08002034 final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicyMask);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002035
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002036 // Erase stuff not relevant for process-wide violations
2037 info.numAnimationsRunning = 0;
2038 info.tags = null;
2039 info.broadcastIntentAction = null;
2040
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002041 final Integer fingerprint = info.hashCode();
2042 final long now = SystemClock.uptimeMillis();
2043 long lastViolationTime = 0;
2044 long timeSinceLastViolationMillis = Long.MAX_VALUE;
2045 synchronized (sLastVmViolationTime) {
2046 if (sLastVmViolationTime.containsKey(fingerprint)) {
2047 lastViolationTime = sLastVmViolationTime.get(fingerprint);
2048 timeSinceLastViolationMillis = now - lastViolationTime;
2049 }
2050 if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
2051 sLastVmViolationTime.put(fingerprint, now);
2052 }
2053 }
2054
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -06002055 if (penaltyLog && sListener != null) {
2056 sListener.onViolation(originStack.toString());
2057 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002058 if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002059 Log.e(TAG, message, originStack);
2060 }
2061
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002062 int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08002063
2064 if (penaltyDropbox && !penaltyDeath) {
2065 // Common case for userdebug/eng builds. If no death and
2066 // just dropboxing, we can do the ActivityManager call
2067 // asynchronously.
2068 dropboxViolationAsync(violationMaskSubset, info);
2069 return;
2070 }
2071
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002072 if (penaltyDropbox && lastViolationTime == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002073 // The violationMask, passed to ActivityManager, is a
2074 // subset of the original StrictMode policy bitmask, with
2075 // only the bit violated and penalty bits to be executed
2076 // by the ActivityManagerService remaining set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002077 final int savedPolicyMask = getThreadPolicyMask();
2078 try {
2079 // First, remove any policy before we call into the Activity Manager,
2080 // otherwise we'll infinite recurse as we try to log policy violations
2081 // to disk, thus violating policy, thus requiring logging, etc...
2082 // We restore the current policy below, in the finally block.
2083 setThreadPolicyMask(0);
2084
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002085 ActivityManager.getService().handleApplicationStrictModeViolation(
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002086 RuntimeInit.getApplicationObject(),
2087 violationMaskSubset,
2088 info);
2089 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07002090 if (e instanceof DeadObjectException) {
2091 // System process is dead; ignore
2092 } else {
2093 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
2094 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002095 } finally {
2096 // Restore the policy.
2097 setThreadPolicyMask(savedPolicyMask);
2098 }
2099 }
2100
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08002101 if (penaltyDeath) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002102 System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
2103 Process.killProcess(Process.myPid());
2104 System.exit(10);
2105 }
2106 }
2107
2108 /**
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002109 * Called from Parcel.writeNoException()
2110 */
2111 /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002112 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002113 if (violations == null) {
2114 p.writeInt(0);
2115 } else {
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002116 // To avoid taking up too much transaction space, only include
2117 // details for the first 3 violations. Deep inside, CrashInfo
2118 // will truncate each stack trace to ~20kB.
2119 final int size = Math.min(violations.size(), 3);
2120 p.writeInt(size);
2121 for (int i = 0; i < size; i++) {
2122 violations.get(i).writeToParcel(p, 0);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002123 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002124 }
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002125 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002126 }
2127
2128 private static class LogStackTrace extends Exception {}
2129
2130 /**
2131 * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
2132 * we here read back all the encoded violations.
2133 */
2134 /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
2135 // Our own stack trace to append
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002136 StringWriter sw = new StringWriter();
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002137 sw.append("# via Binder call with stack:\n");
Dianne Hackborn8c841092013-06-24 13:46:13 -07002138 PrintWriter pw = new FastPrintWriter(sw, false, 256);
2139 new LogStackTrace().printStackTrace(pw);
2140 pw.flush();
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002141 String ourStack = sw.toString();
2142
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002143 final int policyMask = getThreadPolicyMask();
2144 final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002145
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002146 final int size = p.readInt();
2147 for (int i = 0; i < size; i++) {
2148 final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
2149 info.crashInfo.appendStackTrace(ourStack);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002150 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2151 if (policy instanceof AndroidBlockGuardPolicy) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002152 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002153 }
2154 }
2155 }
2156
2157 /**
Brad Fitzpatrick727de402010-07-07 16:06:39 -07002158 * Called from android_util_Binder.cpp's
2159 * android_os_Parcel_enforceInterface when an incoming Binder call
2160 * requires changing the StrictMode policy mask. The role of this
2161 * function is to ask Binder for its current (native) thread-local
2162 * policy value and synchronize it to libcore's (Java)
2163 * thread-local policy value.
2164 */
2165 private static void onBinderStrictModePolicyChange(int newPolicy) {
2166 setBlockGuardPolicy(newPolicy);
2167 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002168
2169 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002170 * A tracked, critical time span. (e.g. during an animation.)
2171 *
2172 * The object itself is a linked list node, to avoid any allocations
2173 * during rapid span entries and exits.
2174 *
2175 * @hide
2176 */
2177 public static class Span {
2178 private String mName;
2179 private long mCreateMillis;
2180 private Span mNext;
2181 private Span mPrev; // not used when in freeList, only active
2182 private final ThreadSpanState mContainerState;
2183
2184 Span(ThreadSpanState threadState) {
2185 mContainerState = threadState;
2186 }
2187
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002188 // Empty constructor for the NO_OP_SPAN
2189 protected Span() {
2190 mContainerState = null;
2191 }
2192
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002193 /**
2194 * To be called when the critical span is complete (i.e. the
2195 * animation is done animating). This can be called on any
2196 * thread (even a different one from where the animation was
2197 * taking place), but that's only a defensive implementation
2198 * measure. It really makes no sense for you to call this on
2199 * thread other than that where you created it.
2200 *
2201 * @hide
2202 */
2203 public void finish() {
2204 ThreadSpanState state = mContainerState;
2205 synchronized (state) {
2206 if (mName == null) {
2207 // Duplicate finish call. Ignore.
2208 return;
2209 }
2210
2211 // Remove ourselves from the active list.
2212 if (mPrev != null) {
2213 mPrev.mNext = mNext;
2214 }
2215 if (mNext != null) {
2216 mNext.mPrev = mPrev;
2217 }
2218 if (state.mActiveHead == this) {
2219 state.mActiveHead = mNext;
2220 }
2221
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002222 state.mActiveSize--;
2223
2224 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
2225
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002226 this.mCreateMillis = -1;
2227 this.mName = null;
2228 this.mPrev = null;
2229 this.mNext = null;
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002230
2231 // Add ourselves to the freeList, if it's not already
2232 // too big.
2233 if (state.mFreeListSize < 5) {
2234 this.mNext = state.mFreeListHead;
2235 state.mFreeListHead = this;
2236 state.mFreeListSize++;
2237 }
2238 }
2239 }
2240 }
2241
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002242 // The no-op span that's used in user builds.
2243 private static final Span NO_OP_SPAN = new Span() {
2244 public void finish() {
2245 // Do nothing.
2246 }
2247 };
2248
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002249 /**
2250 * Linked lists of active spans and a freelist.
2251 *
2252 * Locking notes: there's one of these structures per thread and
2253 * all members of this structure (as well as the Span nodes under
2254 * it) are guarded by the ThreadSpanState object instance. While
2255 * in theory there'd be no locking required because it's all local
2256 * per-thread, the finish() method above is defensive against
2257 * people calling it on a different thread from where they created
2258 * the Span, hence the locking.
2259 */
2260 private static class ThreadSpanState {
2261 public Span mActiveHead; // doubly-linked list.
2262 public int mActiveSize;
2263 public Span mFreeListHead; // singly-linked list. only changes at head.
2264 public int mFreeListSize;
2265 }
2266
2267 private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
2268 new ThreadLocal<ThreadSpanState>() {
2269 @Override protected ThreadSpanState initialValue() {
2270 return new ThreadSpanState();
2271 }
2272 };
2273
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08002274 private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
2275 protected IWindowManager create() {
2276 return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
2277 }
2278 };
2279
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002280 /**
2281 * Enter a named critical span (e.g. an animation)
2282 *
2283 * <p>The name is an arbitary label (or tag) that will be applied
2284 * to any strictmode violation that happens while this span is
2285 * active. You must call finish() on the span when done.
2286 *
2287 * <p>This will never return null, but on devices without debugging
2288 * enabled, this may return a dummy object on which the finish()
2289 * method is a no-op.
2290 *
2291 * <p>TODO: add CloseGuard to this, verifying callers call finish.
2292 *
2293 * @hide
2294 */
2295 public static Span enterCriticalSpan(String name) {
Jeff Sharkey5ab02432017-06-27 11:01:36 -06002296 if (Build.IS_USER) {
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002297 return NO_OP_SPAN;
2298 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002299 if (name == null || name.isEmpty()) {
2300 throw new IllegalArgumentException("name must be non-null and non-empty");
2301 }
2302 ThreadSpanState state = sThisThreadSpanState.get();
2303 Span span = null;
2304 synchronized (state) {
2305 if (state.mFreeListHead != null) {
2306 span = state.mFreeListHead;
2307 state.mFreeListHead = span.mNext;
2308 state.mFreeListSize--;
2309 } else {
2310 // Shouldn't have to do this often.
2311 span = new Span(state);
2312 }
2313 span.mName = name;
2314 span.mCreateMillis = SystemClock.uptimeMillis();
2315 span.mNext = state.mActiveHead;
2316 span.mPrev = null;
2317 state.mActiveHead = span;
2318 state.mActiveSize++;
2319 if (span.mNext != null) {
2320 span.mNext.mPrev = span;
2321 }
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002322 if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002323 }
2324 return span;
2325 }
2326
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002327 /**
2328 * For code to note that it's slow. This is a no-op unless the
2329 * current thread's {@link android.os.StrictMode.ThreadPolicy} has
2330 * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls}
2331 * enabled.
2332 *
2333 * @param name a short string for the exception stack trace that's
2334 * built if when this fires.
2335 */
2336 public static void noteSlowCall(String name) {
2337 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2338 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2339 // StrictMode not enabled.
2340 return;
2341 }
2342 ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
2343 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002344
2345 /**
Alan Viverette6bbb47b2015-01-05 18:12:44 -08002346 * For code to note that a resource was obtained using a type other than
2347 * its defined type. This is a no-op unless the current thread's
2348 * {@link android.os.StrictMode.ThreadPolicy} has
2349 * {@link android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()}
2350 * enabled.
2351 *
2352 * @param tag an object for the exception stack trace that's
2353 * built if when this fires.
2354 * @hide
2355 */
2356 public static void noteResourceMismatch(Object tag) {
2357 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2358 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2359 // StrictMode not enabled.
2360 return;
2361 }
2362 ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag);
2363 }
2364
2365 /**
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002366 * @hide
2367 */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01002368 public static void noteUnbufferedIO() {
2369 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2370 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2371 // StrictMode not enabled.
2372 return;
2373 }
2374 ((AndroidBlockGuardPolicy) policy).onUnbufferedIO();
2375 }
2376
2377 /**
2378 * @hide
2379 */
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002380 public static void noteDiskRead() {
2381 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002382 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2383 // StrictMode not enabled.
2384 return;
2385 }
2386 ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
2387 }
2388
2389 /**
2390 * @hide
2391 */
2392 public static void noteDiskWrite() {
2393 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2394 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2395 // StrictMode not enabled.
2396 return;
2397 }
2398 ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
2399 }
2400
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002401 // Guarded by StrictMode.class
2402 private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
2403 new HashMap<Class, Integer>();
2404
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002405 /**
Jeff Brown7e442832011-06-10 18:00:16 -07002406 * Returns an object that is used to track instances of activites.
2407 * The activity should store a reference to the tracker object in one of its fields.
2408 * @hide
2409 */
2410 public static Object trackActivity(Object instance) {
2411 return new InstanceTracker(instance);
2412 }
2413
2414 /**
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002415 * @hide
2416 */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002417 public static void incrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002418 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002419 return;
2420 }
Jeff Brown7e442832011-06-10 18:00:16 -07002421
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002422 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002423 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2424 return;
2425 }
2426
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002427 Integer expected = sExpectedActivityInstanceCount.get(klass);
2428 Integer newExpected = expected == null ? 1 : expected + 1;
2429 sExpectedActivityInstanceCount.put(klass, newExpected);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002430 }
2431 }
2432
2433 /**
2434 * @hide
2435 */
2436 public static void decrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002437 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002438 return;
2439 }
Jeff Brown7e442832011-06-10 18:00:16 -07002440
2441 final int limit;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002442 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002443 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2444 return;
2445 }
2446
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002447 Integer expected = sExpectedActivityInstanceCount.get(klass);
Jeff Brown7e442832011-06-10 18:00:16 -07002448 int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002449 if (newExpected == 0) {
2450 sExpectedActivityInstanceCount.remove(klass);
2451 } else {
2452 sExpectedActivityInstanceCount.put(klass, newExpected);
2453 }
Jeff Brown7e442832011-06-10 18:00:16 -07002454
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002455 // Note: adding 1 here to give some breathing room during
2456 // orientation changes. (shouldn't be necessary, though?)
Jeff Brown7e442832011-06-10 18:00:16 -07002457 limit = newExpected + 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002458 }
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002459
Jeff Brown7e442832011-06-10 18:00:16 -07002460 // Quick check.
2461 int actual = InstanceTracker.getInstanceCount(klass);
2462 if (actual <= limit) {
2463 return;
2464 }
2465
2466 // Do a GC and explicit count to double-check.
2467 // This is the work that we are trying to avoid by tracking the object instances
2468 // explicity. Running an explicit GC can be expensive (80ms) and so can walking
2469 // the heap to count instance (30ms). This extra work can make the system feel
2470 // noticeably less responsive during orientation changes when activities are
2471 // being restarted. Granted, it is only a problem when StrictMode is enabled
2472 // but it is annoying.
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08002473
2474 System.gc();
2475 System.runFinalization();
2476 System.gc();
Jeff Brown7e442832011-06-10 18:00:16 -07002477
2478 long instances = VMDebug.countInstancesOfClass(klass, false);
2479 if (instances > limit) {
2480 Throwable tr = new InstanceCountViolation(klass, instances, limit);
2481 onVmPolicyViolation(tr.getMessage(), tr);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002482 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002483 }
2484
2485 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002486 * Parcelable that gets sent in Binder call headers back to callers
2487 * to report violations that happened during a cross-process call.
2488 *
2489 * @hide
2490 */
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07002491 public static class ViolationInfo implements Parcelable {
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002492 public final String message;
Jeff Sharkey605eb792014-11-04 13:34:06 -08002493
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002494 /**
2495 * Stack and other stuff info.
2496 */
2497 public final ApplicationErrorReport.CrashInfo crashInfo;
2498
2499 /**
2500 * The strict mode policy mask at the time of violation.
2501 */
2502 public final int policy;
2503
2504 /**
2505 * The wall time duration of the violation, when known. -1 when
2506 * not known.
2507 */
2508 public int durationMillis = -1;
2509
2510 /**
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002511 * The number of animations currently running.
2512 */
2513 public int numAnimationsRunning = 0;
2514
2515 /**
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002516 * List of tags from active Span instances during this
2517 * violation, or null for none.
2518 */
2519 public String[] tags;
2520
2521 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002522 * Which violation number this was (1-based) since the last Looper loop,
2523 * from the perspective of the root caller (if it crossed any processes
2524 * via Binder calls). The value is 0 if the root caller wasn't on a Looper
2525 * thread.
2526 */
2527 public int violationNumThisLoop;
2528
2529 /**
2530 * The time (in terms of SystemClock.uptimeMillis()) that the
2531 * violation occurred.
2532 */
2533 public long violationUptimeMillis;
2534
2535 /**
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002536 * The action of the Intent being broadcast to somebody's onReceive
2537 * on this thread right now, or null.
2538 */
2539 public String broadcastIntentAction;
2540
2541 /**
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002542 * If this is a instance count violation, the number of instances in memory,
2543 * else -1.
2544 */
2545 public long numInstances = -1;
2546
2547 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002548 * Create an uninitialized instance of ViolationInfo
2549 */
2550 public ViolationInfo() {
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002551 message = null;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002552 crashInfo = null;
2553 policy = 0;
2554 }
2555
Jeff Sharkey605eb792014-11-04 13:34:06 -08002556 public ViolationInfo(Throwable tr, int policy) {
2557 this(null, tr, policy);
2558 }
2559
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002560 /**
2561 * Create an instance of ViolationInfo initialized from an exception.
2562 */
Jeff Sharkey605eb792014-11-04 13:34:06 -08002563 public ViolationInfo(String message, Throwable tr, int policy) {
2564 this.message = message;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002565 crashInfo = new ApplicationErrorReport.CrashInfo(tr);
2566 violationUptimeMillis = SystemClock.uptimeMillis();
2567 this.policy = policy;
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002568 this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002569 Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2570 if (broadcastIntent != null) {
2571 broadcastIntentAction = broadcastIntent.getAction();
2572 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002573 ThreadSpanState state = sThisThreadSpanState.get();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002574 if (tr instanceof InstanceCountViolation) {
2575 this.numInstances = ((InstanceCountViolation) tr).mInstances;
2576 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002577 synchronized (state) {
2578 int spanActiveCount = state.mActiveSize;
2579 if (spanActiveCount > MAX_SPAN_TAGS) {
2580 spanActiveCount = MAX_SPAN_TAGS;
2581 }
2582 if (spanActiveCount != 0) {
2583 this.tags = new String[spanActiveCount];
2584 Span iter = state.mActiveHead;
2585 int index = 0;
2586 while (iter != null && index < spanActiveCount) {
2587 this.tags[index] = iter.mName;
2588 index++;
2589 iter = iter.mNext;
2590 }
2591 }
2592 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002593 }
2594
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002595 @Override
2596 public int hashCode() {
2597 int result = 17;
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002598 if (crashInfo != null) {
2599 result = 37 * result + crashInfo.stackTrace.hashCode();
2600 }
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002601 if (numAnimationsRunning != 0) {
2602 result *= 37;
2603 }
2604 if (broadcastIntentAction != null) {
2605 result = 37 * result + broadcastIntentAction.hashCode();
2606 }
2607 if (tags != null) {
2608 for (String tag : tags) {
2609 result = 37 * result + tag.hashCode();
2610 }
2611 }
2612 return result;
2613 }
2614
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002615 /**
2616 * Create an instance of ViolationInfo initialized from a Parcel.
2617 */
2618 public ViolationInfo(Parcel in) {
2619 this(in, false);
2620 }
2621
2622 /**
2623 * Create an instance of ViolationInfo initialized from a Parcel.
2624 *
2625 * @param unsetGatheringBit if true, the caller is the root caller
2626 * and the gathering penalty should be removed.
2627 */
2628 public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
Jeff Sharkey605eb792014-11-04 13:34:06 -08002629 message = in.readString();
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002630 if (in.readInt() != 0) {
2631 crashInfo = new ApplicationErrorReport.CrashInfo(in);
2632 } else {
2633 crashInfo = null;
2634 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002635 int rawPolicy = in.readInt();
2636 if (unsetGatheringBit) {
2637 policy = rawPolicy & ~PENALTY_GATHER;
2638 } else {
2639 policy = rawPolicy;
2640 }
2641 durationMillis = in.readInt();
2642 violationNumThisLoop = in.readInt();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002643 numAnimationsRunning = in.readInt();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002644 violationUptimeMillis = in.readLong();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002645 numInstances = in.readLong();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002646 broadcastIntentAction = in.readString();
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002647 tags = in.readStringArray();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002648 }
2649
2650 /**
2651 * Save a ViolationInfo instance to a parcel.
2652 */
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07002653 @Override
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002654 public void writeToParcel(Parcel dest, int flags) {
Jeff Sharkey605eb792014-11-04 13:34:06 -08002655 dest.writeString(message);
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002656 if (crashInfo != null) {
2657 dest.writeInt(1);
2658 crashInfo.writeToParcel(dest, flags);
2659 } else {
2660 dest.writeInt(0);
2661 }
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002662 int start = dest.dataPosition();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002663 dest.writeInt(policy);
2664 dest.writeInt(durationMillis);
2665 dest.writeInt(violationNumThisLoop);
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002666 dest.writeInt(numAnimationsRunning);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002667 dest.writeLong(violationUptimeMillis);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002668 dest.writeLong(numInstances);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002669 dest.writeString(broadcastIntentAction);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002670 dest.writeStringArray(tags);
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002671 int total = dest.dataPosition()-start;
Jeff Sharkeyf5299f12017-03-17 10:25:07 -06002672 if (Binder.CHECK_PARCEL_SIZE && total > 10*1024) {
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002673 Slog.d(TAG, "VIO: policy=" + policy + " dur=" + durationMillis
2674 + " numLoop=" + violationNumThisLoop
2675 + " anim=" + numAnimationsRunning
2676 + " uptime=" + violationUptimeMillis
2677 + " numInst=" + numInstances);
2678 Slog.d(TAG, "VIO: action=" + broadcastIntentAction);
2679 Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags));
2680 Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition()-start));
2681 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002682 }
2683
2684
2685 /**
2686 * Dump a ViolationInfo instance to a Printer.
2687 */
2688 public void dump(Printer pw, String prefix) {
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002689 if (crashInfo != null) {
2690 crashInfo.dump(pw, prefix);
2691 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002692 pw.println(prefix + "policy: " + policy);
2693 if (durationMillis != -1) {
2694 pw.println(prefix + "durationMillis: " + durationMillis);
2695 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002696 if (numInstances != -1) {
2697 pw.println(prefix + "numInstances: " + numInstances);
2698 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002699 if (violationNumThisLoop != 0) {
2700 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2701 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002702 if (numAnimationsRunning != 0) {
2703 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2704 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002705 pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002706 if (broadcastIntentAction != null) {
2707 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2708 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002709 if (tags != null) {
2710 int index = 0;
2711 for (String tag : tags) {
2712 pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2713 }
2714 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002715 }
2716
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07002717 @Override
2718 public int describeContents() {
2719 return 0;
2720 }
2721
2722 public static final Parcelable.Creator<ViolationInfo> CREATOR =
2723 new Parcelable.Creator<ViolationInfo>() {
2724 @Override
2725 public ViolationInfo createFromParcel(Parcel in) {
2726 return new ViolationInfo(in);
2727 }
2728
2729 @Override
2730 public ViolationInfo[] newArray(int size) {
2731 return new ViolationInfo[size];
2732 }
2733 };
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002734 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002735
2736 // Dummy throwable, for now, since we don't know when or where the
2737 // leaked instances came from. We might in the future, but for
2738 // now we suppress the stack trace because it's useless and/or
2739 // misleading.
2740 private static class InstanceCountViolation extends Throwable {
2741 final Class mClass;
2742 final long mInstances;
2743 final int mLimit;
2744
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002745 private static final StackTraceElement[] FAKE_STACK = {
2746 new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
2747 "StrictMode.java", 1)
2748 };
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002749
2750 public InstanceCountViolation(Class klass, long instances, int limit) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002751 super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002752 setStackTrace(FAKE_STACK);
2753 mClass = klass;
2754 mInstances = instances;
2755 mLimit = limit;
2756 }
2757 }
Jeff Brown7e442832011-06-10 18:00:16 -07002758
2759 private static final class InstanceTracker {
2760 private static final HashMap<Class<?>, Integer> sInstanceCounts =
2761 new HashMap<Class<?>, Integer>();
2762
2763 private final Class<?> mKlass;
2764
2765 public InstanceTracker(Object instance) {
2766 mKlass = instance.getClass();
2767
2768 synchronized (sInstanceCounts) {
2769 final Integer value = sInstanceCounts.get(mKlass);
2770 final int newValue = value != null ? value + 1 : 1;
2771 sInstanceCounts.put(mKlass, newValue);
2772 }
2773 }
2774
2775 @Override
2776 protected void finalize() throws Throwable {
2777 try {
2778 synchronized (sInstanceCounts) {
2779 final Integer value = sInstanceCounts.get(mKlass);
2780 if (value != null) {
2781 final int newValue = value - 1;
2782 if (newValue > 0) {
2783 sInstanceCounts.put(mKlass, newValue);
2784 } else {
2785 sInstanceCounts.remove(mKlass);
2786 }
2787 }
2788 }
2789 } finally {
2790 super.finalize();
2791 }
2792 }
2793
2794 public static int getInstanceCount(Class<?> klass) {
2795 synchronized (sInstanceCounts) {
2796 final Integer value = sInstanceCounts.get(klass);
2797 return value != null ? value : 0;
2798 }
2799 }
2800 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07002801}