blob: f90604abf29364d3806ca6779dcfbe9a47aa80a2 [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;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -070019import android.annotation.NonNull;
Kurt Nelson7d5c07a2017-09-07 16:43:45 -070020import android.annotation.Nullable;
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -060021import android.annotation.TestApi;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070022import android.app.ActivityManager;
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -070023import android.app.ActivityThread;
Brad Fitzpatrick10656852010-11-23 19:01:13 -080024import android.app.IActivityManager;
Jeff Sharkeyd7026f12012-03-01 20:50:32 -080025import android.content.BroadcastReceiver;
26import android.content.Context;
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -070027import android.content.Intent;
Jeff Sharkeyd7026f12012-03-01 20:50:32 -080028import android.content.ServiceConnection;
Jeff Sharkey89182982017-11-01 19:02:56 -060029import android.content.pm.ApplicationInfo;
Jeff Sharkey619a5112017-01-19 11:55:54 -070030import android.net.TrafficStats;
Jeff Sharkey344744b2016-01-28 19:03:30 -070031import android.net.Uri;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -070032import android.os.strictmode.CleartextNetworkViolation;
33import android.os.strictmode.ContentUriWithoutPermissionViolation;
34import android.os.strictmode.CustomViolation;
35import android.os.strictmode.DiskReadViolation;
36import android.os.strictmode.DiskWriteViolation;
37import android.os.strictmode.FileUriExposedViolation;
38import android.os.strictmode.InstanceCountViolation;
39import android.os.strictmode.IntentReceiverLeakedViolation;
40import android.os.strictmode.LeakedClosableViolation;
41import android.os.strictmode.NetworkViolation;
42import android.os.strictmode.ResourceMismatchViolation;
43import android.os.strictmode.ServiceConnectionLeakedViolation;
44import android.os.strictmode.SqliteObjectLeakedViolation;
Kurt Nelson0e612802017-11-09 17:25:40 -080045import android.os.strictmode.UnbufferedIoViolation;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -070046import android.os.strictmode.UntaggedSocketViolation;
47import android.os.strictmode.Violation;
48import android.os.strictmode.WebViewMethodCalledOnWrongThreadViolation;
Dianne Hackborn390517b2013-05-30 15:03:32 -070049import android.util.ArrayMap;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070050import android.util.Log;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070051import android.util.Printer;
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -080052import android.util.Singleton;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070053import android.util.Slog;
Brad Fitzpatrick68044332010-11-22 18:19:48 -080054import android.view.IWindowManager;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070055
Kurt Nelson1981f422017-10-25 13:49:26 -070056import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -070057import com.android.internal.os.BackgroundThread;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070058import com.android.internal.os.RuntimeInit;
Dianne Hackborn8c841092013-06-24 13:46:13 -070059import com.android.internal.util.FastPrintWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080060import com.android.internal.util.HexDump;
61
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070062import dalvik.system.BlockGuard;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070063import dalvik.system.CloseGuard;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -080064import dalvik.system.VMDebug;
Jeff Sharkey0b558702017-01-26 16:48:01 -070065import dalvik.system.VMRuntime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070066
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070067import java.io.PrintWriter;
68import java.io.StringWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080069import java.net.InetAddress;
70import java.net.UnknownHostException;
Kurt Nelson0918c932017-09-07 10:56:56 -070071import java.util.ArrayDeque;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070072import java.util.ArrayList;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070073import java.util.Arrays;
Kurt Nelson0918c932017-09-07 10:56:56 -070074import java.util.Deque;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070075import java.util.HashMap;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -070076import java.util.concurrent.Executor;
77import java.util.concurrent.RejectedExecutionException;
Brad Fitzpatrickbee24872010-11-20 12:09:10 -080078import java.util.concurrent.atomic.AtomicInteger;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070079
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070080/**
Kurt Nelson46974a22017-08-30 13:30:26 -070081 * StrictMode is a developer tool which detects things you might be doing by accident and brings
82 * them to your attention so you can fix them.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070083 *
Kurt Nelson46974a22017-08-30 13:30:26 -070084 * <p>StrictMode is most commonly used to catch accidental disk or network access on the
85 * application's main thread, where UI operations are received and animations take place. Keeping
86 * disk and network operations off the main thread makes for much smoother, more responsive
87 * applications. By keeping your application's main thread responsive, you also prevent <a
88 * href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a> from being shown to
89 * users.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070090 *
Kurt Nelson46974a22017-08-30 13:30:26 -070091 * <p class="note">Note that even though an Android device's disk is often on flash memory, many
92 * devices run a filesystem on top of that memory with very limited concurrency. It's often the case
93 * that almost all disk accesses are fast, but may in individual cases be dramatically slower when
94 * certain I/O is happening in the background from other processes. If possible, it's best to assume
95 * that such things are not fast.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070096 *
Kurt Nelson46974a22017-08-30 13:30:26 -070097 * <p>Example code to enable from early in your {@link android.app.Application}, {@link
98 * android.app.Activity}, or other application component's {@link android.app.Application#onCreate}
99 * method:
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700100 *
101 * <pre>
102 * public void onCreate() {
103 * if (DEVELOPER_MODE) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700104 * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
105 * .detectDiskReads()
106 * .detectDiskWrites()
107 * .detectNetwork() // or .detectAll() for all detectable problems
108 * .penaltyLog()
109 * .build());
110 * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -0700111 * .detectLeakedSqlLiteObjects()
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700112 * .detectLeakedClosableObjects()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700113 * .penaltyLog()
114 * .penaltyDeath()
115 * .build());
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700116 * }
117 * super.onCreate();
118 * }
119 * </pre>
120 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700121 * <p>You can decide what should happen when a violation is detected. For example, using {@link
122 * ThreadPolicy.Builder#penaltyLog} you can watch the output of <code>adb logcat</code> while you
123 * use your application to see the violations as they happen.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700124 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700125 * <p>If you find violations that you feel are problematic, there are a variety of tools to help
126 * solve them: threads, {@link android.os.Handler}, {@link android.os.AsyncTask}, {@link
127 * android.app.IntentService}, etc. But don't feel compelled to fix everything that StrictMode
128 * finds. In particular, many cases of disk access are often necessary during the normal activity
129 * lifecycle. Use StrictMode to find things you did by accident. Network requests on the UI thread
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700130 * are almost always a problem, though.
131 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700132 * <p class="note">StrictMode is not a security mechanism and is not guaranteed to find all disk or
133 * network accesses. While it does propagate its state across process boundaries when doing {@link
134 * android.os.Binder} calls, it's still ultimately a best effort mechanism. Notably, disk or network
135 * access from JNI calls won't necessarily trigger it. Future versions of Android may catch more (or
136 * fewer) operations, so you should never leave StrictMode enabled in applications distributed on
137 * Google Play.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700138 */
139public final class StrictMode {
140 private static final String TAG = "StrictMode";
Brad Fitzpatrick82829ef2010-11-18 18:25:08 -0800141 private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700142
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800143 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700144 * Boolean system property to disable strict mode checks outright. Set this to 'true' to force
145 * disable; 'false' has no effect on other enable/disable policy.
146 *
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700147 * @hide
148 */
149 public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
150
151 /**
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800152 * The boolean system property to control screen flashes on violations.
153 *
154 * @hide
155 */
156 public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
157
Jeff Sharkey605eb792014-11-04 13:34:06 -0800158 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700159 * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK} in {@link
160 * VmPolicy.Builder#detectAll()}. Apps can still always opt-into detection using {@link
161 * VmPolicy.Builder#detectCleartextNetwork()}.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800162 */
Jeff Sharkey2e571642015-01-22 11:51:43 -0700163 private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.clear";
Jeff Sharkey605eb792014-11-04 13:34:06 -0800164
Jeff Sharkey89182982017-11-01 19:02:56 -0600165 /**
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700166 * Quick feature-flag that can be used to disable the defaults provided by {@link
167 * #initThreadDefaults(ApplicationInfo)} and {@link #initVmDefaults(ApplicationInfo)}.
Jeff Sharkey89182982017-11-01 19:02:56 -0600168 */
Jeff Sharkey617e1132017-11-03 17:28:45 -0600169 private static final boolean DISABLE = false;
Jeff Sharkey89182982017-11-01 19:02:56 -0600170
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700171 // Only apply VM penalties for the same violation at this interval.
172 private static final long MIN_VM_INTERVAL_MS = 1000;
173
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700174 // Only log a duplicate stack trace to the logs every second.
175 private static final long MIN_LOG_INTERVAL_MS = 1000;
176
177 // Only show an annoying dialog at most every 30 seconds
178 private static final long MIN_DIALOG_INTERVAL_MS = 30000;
179
Brad Fitzpatricke7520d82010-11-10 18:08:36 -0800180 // How many Span tags (e.g. animations) to report.
181 private static final int MAX_SPAN_TAGS = 20;
182
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -0700183 // How many offending stacks to keep track of (and time) per loop
184 // of the Looper.
185 private static final int MAX_OFFENSES_PER_LOOP = 10;
186
Jeff Sharkey605eb792014-11-04 13:34:06 -0800187 // Byte 1: Thread-policy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700188
Kurt Nelson46974a22017-08-30 13:30:26 -0700189 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700190 @TestApi public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700191
Kurt Nelson46974a22017-08-30 13:30:26 -0700192 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700193 @TestApi public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700194
Kurt Nelson46974a22017-08-30 13:30:26 -0700195 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700196 @TestApi public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700197
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800198 /**
199 * For StrictMode.noteSlowCall()
200 *
201 * @hide
202 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700203 @TestApi public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800204
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800205 /**
206 * For StrictMode.noteResourceMismatch()
207 *
208 * @hide
209 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700210 @TestApi public static final int DETECT_RESOURCE_MISMATCH = 0x10; // for ThreadPolicy
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800211
Kurt Nelson46974a22017-08-30 13:30:26 -0700212 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700213 @TestApi public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100214
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800215 private static final int ALL_THREAD_DETECT_BITS =
Kurt Nelson46974a22017-08-30 13:30:26 -0700216 DETECT_DISK_WRITE
217 | DETECT_DISK_READ
218 | DETECT_NETWORK
219 | DETECT_CUSTOM
220 | DETECT_RESOURCE_MISMATCH
221 | DETECT_UNBUFFERED_IO;
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800222
Jeff Sharkey605eb792014-11-04 13:34:06 -0800223 // Byte 2: Process-policy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700224
225 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700226 * Note, a "VM_" bit, not thread.
Kurt Nelson46974a22017-08-30 13:30:26 -0700227 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700228 * @hide
229 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700230 @TestApi public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8; // for VmPolicy
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700231
232 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700233 * Note, a "VM_" bit, not thread.
Kurt Nelson46974a22017-08-30 13:30:26 -0700234 *
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700235 * @hide
236 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700237 @TestApi public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8; // for VmPolicy
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800238
239 /**
240 * Note, a "VM_" bit, not thread.
Kurt Nelson46974a22017-08-30 13:30:26 -0700241 *
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800242 * @hide
243 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700244 @TestApi public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8; // for VmPolicy
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700245
Kurt Nelson46974a22017-08-30 13:30:26 -0700246 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700247 @TestApi public static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8; // for VmPolicy
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800248
Kurt Nelson46974a22017-08-30 13:30:26 -0700249 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700250 @TestApi public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8; // for VmPolicy
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800251
Kurt Nelson46974a22017-08-30 13:30:26 -0700252 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700253 @TestApi public static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8; // for VmPolicy
Jeff Sharkey605eb792014-11-04 13:34:06 -0800254
Kurt Nelson46974a22017-08-30 13:30:26 -0700255 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700256 @TestApi public static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8; // for VmPolicy
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700257
Kurt Nelson46974a22017-08-30 13:30:26 -0700258 /** @hide */
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -0700259 @TestApi
260 public static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -0700261
Kurt Nelson46974a22017-08-30 13:30:26 -0700262 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700263 @TestApi public static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy
Jeff Sharkey619a5112017-01-19 11:55:54 -0700264
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800265 private static final int ALL_VM_DETECT_BITS =
Kurt Nelson46974a22017-08-30 13:30:26 -0700266 DETECT_VM_CURSOR_LEAKS
267 | DETECT_VM_CLOSABLE_LEAKS
268 | DETECT_VM_ACTIVITY_LEAKS
269 | DETECT_VM_INSTANCE_LEAKS
270 | DETECT_VM_REGISTRATION_LEAKS
271 | DETECT_VM_FILE_URI_EXPOSURE
272 | DETECT_VM_CLEARTEXT_NETWORK
273 | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION
274 | DETECT_VM_UNTAGGED_SOCKET;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800275
276 // Byte 3: Penalty
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800277
Jeff Sharkey344744b2016-01-28 19:03:30 -0700278 /** {@hide} */
Kurt Nelson46974a22017-08-30 13:30:26 -0700279 public static final int PENALTY_LOG = 0x01 << 16; // normal android.util.Log
Jeff Sharkey344744b2016-01-28 19:03:30 -0700280 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800281 public static final int PENALTY_DIALOG = 0x02 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700282 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800283 public static final int PENALTY_DEATH = 0x04 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700284 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800285 public static final int PENALTY_FLASH = 0x10 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700286 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800287 public static final int PENALTY_DROPBOX = 0x20 << 16;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700288
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700289 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700290 * Non-public penalty mode which overrides all the other penalty bits and signals that we're in
291 * a Binder call and we should ignore the other penalty bits and instead serialize back all our
292 * offending stack traces to the caller to ultimately handle in the originating process.
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700293 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700294 * <p>This must be kept in sync with the constant in libs/binder/Parcel.cpp
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700295 *
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700296 * @hide
297 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800298 public static final int PENALTY_GATHER = 0x40 << 16;
299
Jeff Sharkey344744b2016-01-28 19:03:30 -0700300 // Byte 4: Special cases
301
302 /**
303 * Death when network traffic is detected on main thread.
304 *
305 * @hide
306 */
307 public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
308
Jeff Sharkey605eb792014-11-04 13:34:06 -0800309 /**
310 * Death when cleartext network traffic is detected.
311 *
312 * @hide
313 */
Jeff Sharkey344744b2016-01-28 19:03:30 -0700314 public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
315
316 /**
317 * Death when file exposure is detected.
318 *
319 * @hide
320 */
321 public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700322
Jeff Sharkey619a5112017-01-19 11:55:54 -0700323 // CAUTION: we started stealing the top bits of Byte 4 for VM above
324
Kurt Nelson46974a22017-08-30 13:30:26 -0700325 /** Mask of all the penalty bits valid for thread policies. */
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800326 private static final int THREAD_PENALTY_MASK =
Kurt Nelson46974a22017-08-30 13:30:26 -0700327 PENALTY_LOG
328 | PENALTY_DIALOG
329 | PENALTY_DEATH
330 | PENALTY_DROPBOX
331 | PENALTY_GATHER
332 | PENALTY_DEATH_ON_NETWORK
333 | PENALTY_FLASH;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700334
Kurt Nelson46974a22017-08-30 13:30:26 -0700335 /** Mask of all the penalty bits valid for VM policies. */
336 private static final int VM_PENALTY_MASK =
337 PENALTY_LOG
338 | PENALTY_DEATH
339 | PENALTY_DROPBOX
340 | PENALTY_DEATH_ON_CLEARTEXT_NETWORK
341 | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800342
Jeff Sharkey605eb792014-11-04 13:34:06 -0800343 /** {@hide} */
344 public static final int NETWORK_POLICY_ACCEPT = 0;
345 /** {@hide} */
346 public static final int NETWORK_POLICY_LOG = 1;
347 /** {@hide} */
348 public static final int NETWORK_POLICY_REJECT = 2;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800349
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800350 // TODO: wrap in some ImmutableHashMap thing.
351 // Note: must be before static initialization of sVmPolicy.
Kurt Nelson46974a22017-08-30 13:30:26 -0700352 private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP =
353 new HashMap<Class, Integer>();
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800354
Kurt Nelson2c883f32017-09-01 10:52:45 -0700355 /** The current VmPolicy in effect. */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800356 private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700357
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600358 /** {@hide} */
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -0600359 @TestApi
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700360 public interface ViolationLogger {
361
362 /** Called when penaltyLog is enabled and a violation needs logging. */
363 void log(ViolationInfo info);
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600364 }
365
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700366 private static final ViolationLogger LOGCAT_LOGGER =
367 info -> {
368 String msg;
369 if (info.durationMillis != -1) {
370 msg = "StrictMode policy violation; ~duration=" + info.durationMillis + " ms:";
371 } else {
372 msg = "StrictMode policy violation:";
373 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700374 Log.d(TAG, msg + " " + info.getStackTrace());
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700375 };
376
377 private static volatile ViolationLogger sLogger = LOGCAT_LOGGER;
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600378
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700379 private static final ThreadLocal<OnThreadViolationListener> sThreadViolationListener =
380 new ThreadLocal<>();
381 private static final ThreadLocal<Executor> sThreadViolationExecutor = new ThreadLocal<>();
382
383 /**
384 * When #{@link ThreadPolicy.Builder#penaltyListener} is enabled, the listener is called on the
385 * provided executor when a Thread violation occurs.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700386 */
387 public interface OnThreadViolationListener {
388 /** Called on a thread policy violation. */
389 void onThreadViolation(Violation v);
390 }
391
392 /**
393 * When #{@link VmPolicy.Builder#penaltyListener} is enabled, the listener is called on the
394 * provided executor when a VM violation occurs.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700395 */
396 public interface OnVmViolationListener {
397 /** Called on a VM policy violation. */
398 void onVmViolation(Violation v);
399 }
400
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600401 /** {@hide} */
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -0600402 @TestApi
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700403 public static void setViolationLogger(ViolationLogger listener) {
404 if (listener == null) {
405 listener = LOGCAT_LOGGER;
406 }
407 sLogger = listener;
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600408 }
409
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800410 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700411 * The number of threads trying to do an async dropbox write. Just to limit ourselves out of
412 * paranoia.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800413 */
414 private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
415
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700416 private StrictMode() {}
417
418 /**
419 * {@link StrictMode} policy applied to a certain thread.
420 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700421 * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy can be retrieved
422 * with {@link #getThreadPolicy}.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700423 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700424 * <p>Note that multiple penalties may be provided and they're run in order from least to most
425 * severe (logging before process death, for example). There's currently no mechanism to choose
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700426 * different penalties for different detected actions.
427 */
428 public static final class ThreadPolicy {
Kurt Nelson46974a22017-08-30 13:30:26 -0700429 /** The default, lax policy which doesn't catch anything. */
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700430 public static final ThreadPolicy LAX = new ThreadPolicy(0, null, null);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700431
432 final int mask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700433 final OnThreadViolationListener mListener;
434 final Executor mCallbackExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700435
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700436 private ThreadPolicy(int mask, OnThreadViolationListener listener, Executor executor) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700437 this.mask = mask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700438 mListener = listener;
439 mCallbackExecutor = executor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700440 }
441
442 @Override
443 public String toString() {
444 return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
445 }
446
447 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700448 * Creates {@link ThreadPolicy} instances. Methods whose names start with {@code detect}
449 * specify what problems we should look for. Methods whose names start with {@code penalty}
450 * specify what we should do when we detect a problem.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700451 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700452 * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently
453 * order is insignificant: all penalties apply to all detected problems.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700454 *
455 * <p>For example, detect everything and log anything that's found:
Kurt Nelson46974a22017-08-30 13:30:26 -0700456 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700457 * <pre>
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800458 * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700459 * .detectAll()
460 * .penaltyLog()
461 * .build();
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800462 * StrictMode.setThreadPolicy(policy);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700463 * </pre>
464 */
465 public static final class Builder {
466 private int mMask = 0;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700467 private OnThreadViolationListener mListener;
468 private Executor mExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700469
470 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700471 * Create a Builder that detects nothing and has no violations. (but note that {@link
472 * #build} will default to enabling {@link #penaltyLog} if no other penalties are
473 * specified)
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700474 */
475 public Builder() {
476 mMask = 0;
477 }
478
Kurt Nelson46974a22017-08-30 13:30:26 -0700479 /** Initialize a Builder from an existing ThreadPolicy. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700480 public Builder(ThreadPolicy policy) {
481 mMask = policy.mask;
482 }
483
484 /**
485 * Detect everything that's potentially suspect.
486 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700487 * <p>As of the Gingerbread release this includes network and disk operations but will
488 * likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700489 */
490 public Builder detectAll() {
Jeff Sharkey0b558702017-01-26 16:48:01 -0700491 detectDiskReads();
492 detectDiskWrites();
493 detectNetwork();
494
495 final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
496 if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
497 detectCustomSlowCalls();
498 }
499 if (targetSdk >= Build.VERSION_CODES.M) {
500 detectResourceMismatches();
501 }
502 if (targetSdk >= Build.VERSION_CODES.O) {
503 detectUnbufferedIo();
504 }
505 return this;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700506 }
507
Kurt Nelson46974a22017-08-30 13:30:26 -0700508 /** Disable the detection of everything. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700509 public Builder permitAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800510 return disable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700511 }
512
Kurt Nelson46974a22017-08-30 13:30:26 -0700513 /** Enable detection of network operations. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700514 public Builder detectNetwork() {
515 return enable(DETECT_NETWORK);
516 }
517
Kurt Nelson46974a22017-08-30 13:30:26 -0700518 /** Disable detection of network operations. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700519 public Builder permitNetwork() {
520 return disable(DETECT_NETWORK);
521 }
522
Kurt Nelson46974a22017-08-30 13:30:26 -0700523 /** Enable detection of disk reads. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700524 public Builder detectDiskReads() {
525 return enable(DETECT_DISK_READ);
526 }
527
Kurt Nelson46974a22017-08-30 13:30:26 -0700528 /** Disable detection of disk reads. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700529 public Builder permitDiskReads() {
530 return disable(DETECT_DISK_READ);
531 }
532
Kurt Nelson46974a22017-08-30 13:30:26 -0700533 /** Enable detection of slow calls. */
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800534 public Builder detectCustomSlowCalls() {
535 return enable(DETECT_CUSTOM);
536 }
537
Kurt Nelson46974a22017-08-30 13:30:26 -0700538 /** Disable detection of slow calls. */
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800539 public Builder permitCustomSlowCalls() {
Qi Wang097fbf22012-07-13 09:26:03 +0800540 return disable(DETECT_CUSTOM);
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800541 }
542
Kurt Nelson46974a22017-08-30 13:30:26 -0700543 /** Disable detection of mismatches between defined resource types and getter calls. */
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800544 public Builder permitResourceMismatches() {
545 return disable(DETECT_RESOURCE_MISMATCH);
546 }
547
Kurt Nelson46974a22017-08-30 13:30:26 -0700548 /** Detect unbuffered input/output operations. */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100549 public Builder detectUnbufferedIo() {
550 return enable(DETECT_UNBUFFERED_IO);
551 }
552
Kurt Nelson46974a22017-08-30 13:30:26 -0700553 /** Disable detection of unbuffered input/output operations. */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100554 public Builder permitUnbufferedIo() {
555 return disable(DETECT_UNBUFFERED_IO);
556 }
557
558 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700559 * Enables detection of mismatches between defined resource types and getter calls.
560 *
561 * <p>This helps detect accidental type mismatches and potentially expensive type
562 * conversions when obtaining typed resources.
563 *
564 * <p>For example, a strict mode violation would be thrown when calling {@link
565 * android.content.res.TypedArray#getInt(int, int)} on an index that contains a
566 * String-type resource. If the string value can be parsed as an integer, this method
567 * call will return a value without crashing; however, the developer should format the
568 * resource as an integer to avoid unnecessary type conversion.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800569 */
570 public Builder detectResourceMismatches() {
571 return enable(DETECT_RESOURCE_MISMATCH);
572 }
573
Kurt Nelson46974a22017-08-30 13:30:26 -0700574 /** Enable detection of disk writes. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700575 public Builder detectDiskWrites() {
576 return enable(DETECT_DISK_WRITE);
577 }
578
Kurt Nelson46974a22017-08-30 13:30:26 -0700579 /** Disable detection of disk writes. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700580 public Builder permitDiskWrites() {
581 return disable(DETECT_DISK_WRITE);
582 }
583
584 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700585 * Show an annoying dialog to the developer on detected violations, rate-limited to be
586 * only a little annoying.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700587 */
588 public Builder penaltyDialog() {
589 return enable(PENALTY_DIALOG);
590 }
591
592 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700593 * Crash the whole process on violation. This penalty runs at the end of all enabled
594 * penalties so you'll still get see logging or other violations before the process
595 * dies.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700596 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700597 * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies to disk reads, disk writes,
598 * and network usage if their corresponding detect flags are set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700599 */
600 public Builder penaltyDeath() {
601 return enable(PENALTY_DEATH);
602 }
603
604 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700605 * Crash the whole process on any network usage. Unlike {@link #penaltyDeath}, this
606 * penalty runs <em>before</em> anything else. You must still have called {@link
607 * #detectNetwork} to enable this.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700608 *
609 * <p>In the Honeycomb or later SDKs, this is on by default.
610 */
611 public Builder penaltyDeathOnNetwork() {
612 return enable(PENALTY_DEATH_ON_NETWORK);
613 }
614
Kurt Nelson46974a22017-08-30 13:30:26 -0700615 /** Flash the screen during a violation. */
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800616 public Builder penaltyFlashScreen() {
617 return enable(PENALTY_FLASH);
618 }
619
Kurt Nelson46974a22017-08-30 13:30:26 -0700620 /** Log detected violations to the system log. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700621 public Builder penaltyLog() {
622 return enable(PENALTY_LOG);
623 }
624
625 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700626 * Enable detected violations log a stacktrace and timing data to the {@link
627 * android.os.DropBoxManager DropBox} on policy violation. Intended mostly for platform
628 * integrators doing beta user field data collection.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700629 */
630 public Builder penaltyDropBox() {
631 return enable(PENALTY_DROPBOX);
632 }
633
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700634 /**
635 * Call #{@link OnThreadViolationListener#onThreadViolation(Violation)} on specified
636 * executor every violation.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700637 */
638 public Builder penaltyListener(
639 @NonNull OnThreadViolationListener listener, @NonNull Executor executor) {
640 if (executor == null) {
641 throw new NullPointerException("executor must not be null");
642 }
643 mListener = listener;
644 mExecutor = executor;
645 return this;
646 }
647
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700648 private Builder enable(int bit) {
649 mMask |= bit;
650 return this;
651 }
652
653 private Builder disable(int bit) {
654 mMask &= ~bit;
655 return this;
656 }
657
658 /**
659 * Construct the ThreadPolicy instance.
660 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700661 * <p>Note: if no penalties are enabled before calling <code>build</code>, {@link
662 * #penaltyLog} is implicitly set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700663 */
664 public ThreadPolicy build() {
665 // If there are detection bits set but no violation bits
666 // set, enable simple logging.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700667 if (mListener == null
668 && mMask != 0
Kurt Nelson46974a22017-08-30 13:30:26 -0700669 && (mMask
670 & (PENALTY_DEATH
671 | PENALTY_LOG
672 | PENALTY_DROPBOX
673 | PENALTY_DIALOG))
674 == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700675 penaltyLog();
676 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700677 return new ThreadPolicy(mMask, mListener, mExecutor);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700678 }
679 }
680 }
681
682 /**
683 * {@link StrictMode} policy applied to all threads in the virtual machine's process.
684 *
685 * <p>The policy is enabled by {@link #setVmPolicy}.
686 */
687 public static final class VmPolicy {
Kurt Nelson46974a22017-08-30 13:30:26 -0700688 /** The default, lax policy which doesn't catch anything. */
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700689 public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP, null, null);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700690
691 final int mask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700692 final OnVmViolationListener mListener;
693 final Executor mCallbackExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700694
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800695 // Map from class to max number of allowed instances in memory.
696 final HashMap<Class, Integer> classInstanceLimit;
697
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700698 private VmPolicy(
699 int mask,
700 HashMap<Class, Integer> classInstanceLimit,
701 OnVmViolationListener listener,
702 Executor executor) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800703 if (classInstanceLimit == null) {
704 throw new NullPointerException("classInstanceLimit == null");
705 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700706 this.mask = mask;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800707 this.classInstanceLimit = classInstanceLimit;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700708 mListener = listener;
709 mCallbackExecutor = executor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700710 }
711
712 @Override
713 public String toString() {
714 return "[StrictMode.VmPolicy; mask=" + mask + "]";
715 }
716
717 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700718 * Creates {@link VmPolicy} instances. Methods whose names start with {@code detect} specify
719 * what problems we should look for. Methods whose names start with {@code penalty} specify
720 * what we should do when we detect a problem.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700721 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700722 * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently
723 * order is insignificant: all penalties apply to all detected problems.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700724 *
725 * <p>For example, detect everything and log anything that's found:
Kurt Nelson46974a22017-08-30 13:30:26 -0700726 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700727 * <pre>
728 * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
729 * .detectAll()
730 * .penaltyLog()
731 * .build();
732 * StrictMode.setVmPolicy(policy);
733 * </pre>
734 */
735 public static final class Builder {
736 private int mMask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700737 private OnVmViolationListener mListener;
738 private Executor mExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700739
Kurt Nelson46974a22017-08-30 13:30:26 -0700740 private HashMap<Class, Integer> mClassInstanceLimit; // null until needed
741 private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800742
743 public Builder() {
744 mMask = 0;
745 }
746
Kurt Nelson46974a22017-08-30 13:30:26 -0700747 /** Build upon an existing VmPolicy. */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800748 public Builder(VmPolicy base) {
749 mMask = base.mask;
750 mClassInstanceLimitNeedCow = true;
751 mClassInstanceLimit = base.classInstanceLimit;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700752 mListener = base.mListener;
753 mExecutor = base.mCallbackExecutor;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800754 }
755
756 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700757 * Set an upper bound on how many instances of a class can be in memory at once. Helps
758 * to prevent object leaks.
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800759 */
760 public Builder setClassInstanceLimit(Class klass, int instanceLimit) {
761 if (klass == null) {
762 throw new NullPointerException("klass == null");
763 }
764 if (mClassInstanceLimitNeedCow) {
Kurt Nelson46974a22017-08-30 13:30:26 -0700765 if (mClassInstanceLimit.containsKey(klass)
766 && mClassInstanceLimit.get(klass) == instanceLimit) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800767 // no-op; don't break COW
768 return this;
769 }
770 mClassInstanceLimitNeedCow = false;
771 mClassInstanceLimit = (HashMap<Class, Integer>) mClassInstanceLimit.clone();
772 } else if (mClassInstanceLimit == null) {
773 mClassInstanceLimit = new HashMap<Class, Integer>();
774 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800775 mMask |= DETECT_VM_INSTANCE_LEAKS;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800776 mClassInstanceLimit.put(klass, instanceLimit);
777 return this;
778 }
779
Kurt Nelson46974a22017-08-30 13:30:26 -0700780 /** Detect leaks of {@link android.app.Activity} subclasses. */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800781 public Builder detectActivityLeaks() {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800782 return enable(DETECT_VM_ACTIVITY_LEAKS);
783 }
784
Jeff Sharkey89182982017-11-01 19:02:56 -0600785 /** @hide */
786 public Builder permitActivityLeaks() {
787 return disable(DETECT_VM_ACTIVITY_LEAKS);
788 }
789
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700790 /**
791 * Detect everything that's potentially suspect.
792 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700793 * <p>In the Honeycomb release this includes leaks of SQLite cursors, Activities, and
794 * other closable objects but will likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700795 */
796 public Builder detectAll() {
Jeff Sharkey0b558702017-01-26 16:48:01 -0700797 detectLeakedSqlLiteObjects();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800798
Jeff Sharkey0b558702017-01-26 16:48:01 -0700799 final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
800 if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
801 detectActivityLeaks();
802 detectLeakedClosableObjects();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800803 }
Jeff Sharkey0b558702017-01-26 16:48:01 -0700804 if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) {
805 detectLeakedRegistrationObjects();
806 }
807 if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
808 detectFileUriExposure();
809 }
810 if (targetSdk >= Build.VERSION_CODES.M) {
811 // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have
812 // facility for apps to mark sockets that should be ignored
813 if (SystemProperties.getBoolean(CLEARTEXT_PROPERTY, false)) {
814 detectCleartextNetwork();
815 }
816 }
817 if (targetSdk >= Build.VERSION_CODES.O) {
818 detectContentUriWithoutPermission();
819 detectUntaggedSockets();
820 }
821 return this;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700822 }
823
824 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700825 * Detect when an {@link android.database.sqlite.SQLiteCursor} or other SQLite object is
826 * finalized without having been closed.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700827 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700828 * <p>You always want to explicitly close your SQLite cursors to avoid unnecessary
829 * database contention and temporary memory leaks.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700830 */
831 public Builder detectLeakedSqlLiteObjects() {
832 return enable(DETECT_VM_CURSOR_LEAKS);
833 }
834
835 /**
Kurt Nelsond25bd9f2017-09-14 11:36:34 -0700836 * Detect when an {@link java.io.Closeable} or other object with an explicit termination
Kurt Nelson46974a22017-08-30 13:30:26 -0700837 * method is finalized without having been closed.
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700838 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700839 * <p>You always want to explicitly close such objects to avoid unnecessary resources
840 * leaks.
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700841 */
842 public Builder detectLeakedClosableObjects() {
843 return enable(DETECT_VM_CLOSABLE_LEAKS);
844 }
845
846 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700847 * Detect when a {@link BroadcastReceiver} or {@link ServiceConnection} is leaked during
848 * {@link Context} teardown.
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800849 */
850 public Builder detectLeakedRegistrationObjects() {
851 return enable(DETECT_VM_REGISTRATION_LEAKS);
852 }
853
854 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700855 * Detect when the calling application exposes a {@code file://} {@link android.net.Uri}
856 * to another app.
857 *
858 * <p>This exposure is discouraged since the receiving app may not have access to the
859 * shared path. For example, the receiving app may not have requested the {@link
860 * android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime permission, or the
861 * platform may be sharing the {@link android.net.Uri} across user profile boundaries.
862 *
863 * <p>Instead, apps should use {@code content://} Uris so the platform can extend
864 * temporary permission for the receiving app to access the resource.
Jeff Sharkey344744b2016-01-28 19:03:30 -0700865 *
866 * @see android.support.v4.content.FileProvider
867 * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700868 */
869 public Builder detectFileUriExposure() {
870 return enable(DETECT_VM_FILE_URI_EXPOSURE);
871 }
872
873 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700874 * Detect any network traffic from the calling app which is not wrapped in SSL/TLS. This
875 * can help you detect places that your app is inadvertently sending cleartext data
876 * across the network.
877 *
878 * <p>Using {@link #penaltyDeath()} or {@link #penaltyDeathOnCleartextNetwork()} will
879 * block further traffic on that socket to prevent accidental data leakage, in addition
880 * to crashing your process.
881 *
882 * <p>Using {@link #penaltyDropBox()} will log the raw contents of the packet that
883 * triggered the violation.
884 *
885 * <p>This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it may be subject to
886 * false positives, such as when STARTTLS protocols or HTTP proxies are used.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800887 */
888 public Builder detectCleartextNetwork() {
889 return enable(DETECT_VM_CLEARTEXT_NETWORK);
890 }
891
892 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700893 * Detect when the calling application sends a {@code content://} {@link
894 * android.net.Uri} to another app without setting {@link
895 * Intent#FLAG_GRANT_READ_URI_PERMISSION} or {@link
896 * Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
897 *
898 * <p>Forgetting to include one or more of these flags when sending an intent is
899 * typically an app bug.
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -0700900 *
901 * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
902 * @see Intent#FLAG_GRANT_WRITE_URI_PERMISSION
903 */
904 public Builder detectContentUriWithoutPermission() {
905 return enable(DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION);
906 }
907
908 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700909 * Detect any sockets in the calling app which have not been tagged using {@link
910 * TrafficStats}. Tagging sockets can help you investigate network usage inside your
911 * app, such as a narrowing down heavy usage to a specific library or component.
912 *
913 * <p>This currently does not detect sockets created in native code.
Jeff Sharkey619a5112017-01-19 11:55:54 -0700914 *
915 * @see TrafficStats#setThreadStatsTag(int)
916 * @see TrafficStats#tagSocket(java.net.Socket)
917 * @see TrafficStats#tagDatagramSocket(java.net.DatagramSocket)
918 */
919 public Builder detectUntaggedSockets() {
920 return enable(DETECT_VM_UNTAGGED_SOCKET);
921 }
922
Jeff Sharkey89182982017-11-01 19:02:56 -0600923 /** @hide */
924 public Builder permitUntaggedSockets() {
925 return disable(DETECT_VM_UNTAGGED_SOCKET);
926 }
927
Jeff Sharkey619a5112017-01-19 11:55:54 -0700928 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700929 * Crashes the whole process on violation. This penalty runs at the end of all enabled
930 * penalties so you'll still get your logging or other violations before the process
931 * dies.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700932 */
933 public Builder penaltyDeath() {
934 return enable(PENALTY_DEATH);
935 }
936
937 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700938 * Crashes the whole process when cleartext network traffic is detected.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800939 *
940 * @see #detectCleartextNetwork()
Jeff Sharkey605eb792014-11-04 13:34:06 -0800941 */
942 public Builder penaltyDeathOnCleartextNetwork() {
943 return enable(PENALTY_DEATH_ON_CLEARTEXT_NETWORK);
944 }
945
946 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700947 * Crashes the whole process when a {@code file://} {@link android.net.Uri} is exposed
948 * beyond this app.
Jeff Sharkey344744b2016-01-28 19:03:30 -0700949 *
950 * @see #detectFileUriExposure()
951 */
952 public Builder penaltyDeathOnFileUriExposure() {
953 return enable(PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
954 }
955
Kurt Nelson46974a22017-08-30 13:30:26 -0700956 /** Log detected violations to the system log. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700957 public Builder penaltyLog() {
958 return enable(PENALTY_LOG);
959 }
960
961 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700962 * Enable detected violations log a stacktrace and timing data to the {@link
963 * android.os.DropBoxManager DropBox} on policy violation. Intended mostly for platform
964 * integrators doing beta user field data collection.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700965 */
966 public Builder penaltyDropBox() {
967 return enable(PENALTY_DROPBOX);
968 }
969
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700970 /**
971 * Call #{@link OnVmViolationListener#onVmViolation(Violation)} on every violation.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700972 */
973 public Builder penaltyListener(
974 @NonNull OnVmViolationListener listener, @NonNull Executor executor) {
975 if (executor == null) {
976 throw new NullPointerException("executor must not be null");
977 }
978 mListener = listener;
979 mExecutor = executor;
980 return this;
981 }
982
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700983 private Builder enable(int bit) {
984 mMask |= bit;
985 return this;
986 }
987
Mathieu Chartierca8c1052017-06-19 18:42:57 -0700988 Builder disable(int bit) {
989 mMask &= ~bit;
990 return this;
991 }
992
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700993 /**
994 * Construct the VmPolicy instance.
995 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700996 * <p>Note: if no penalties are enabled before calling <code>build</code>, {@link
997 * #penaltyLog} is implicitly set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700998 */
999 public VmPolicy build() {
1000 // If there are detection bits set but no violation bits
1001 // set, enable simple logging.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001002 if (mListener == null
1003 && mMask != 0
Kurt Nelson46974a22017-08-30 13:30:26 -07001004 && (mMask
1005 & (PENALTY_DEATH
1006 | PENALTY_LOG
1007 | PENALTY_DROPBOX
1008 | PENALTY_DIALOG))
1009 == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001010 penaltyLog();
1011 }
Kurt Nelson46974a22017-08-30 13:30:26 -07001012 return new VmPolicy(
1013 mMask,
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001014 mClassInstanceLimit != null ? mClassInstanceLimit : EMPTY_CLASS_LIMIT_MAP,
1015 mListener,
1016 mExecutor);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001017 }
1018 }
1019 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001020
1021 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001022 * Log of strict mode violation stack traces that have occurred during a Binder call, to be
1023 * serialized back later to the caller via Parcel.writeNoException() (amusingly) where the
1024 * caller can choose how to react.
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001025 */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001026 private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
1027 new ThreadLocal<ArrayList<ViolationInfo>>() {
Kurt Nelson46974a22017-08-30 13:30:26 -07001028 @Override
1029 protected ArrayList<ViolationInfo> initialValue() {
1030 // Starts null to avoid unnecessary allocations when
1031 // checking whether there are any violations or not in
1032 // hasGatheredViolations() below.
1033 return null;
1034 }
1035 };
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001036
1037 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001038 * Sets the policy for what actions on the current thread should be detected, as well as the
1039 * penalty if such actions occur.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001040 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001041 * <p>Internally this sets a thread-local variable which is propagated across cross-process IPC
1042 * calls, meaning you can catch violations when a system service or another process accesses the
1043 * disk or network on your behalf.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -07001044 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001045 * @param policy the policy to put into place
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001046 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001047 public static void setThreadPolicy(final ThreadPolicy policy) {
1048 setThreadPolicyMask(policy.mask);
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001049 sThreadViolationListener.set(policy.mListener);
1050 sThreadViolationExecutor.set(policy.mCallbackExecutor);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001051 }
1052
Jeff Sharkey89182982017-11-01 19:02:56 -06001053 /** @hide */
1054 public static void setThreadPolicyMask(final int policyMask) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001055 // In addition to the Java-level thread-local in Dalvik's
1056 // BlockGuard, we also need to keep a native thread-local in
1057 // Binder in order to propagate the value across Binder calls,
1058 // even across native-only processes. The two are kept in
1059 // sync via the callback to onStrictModePolicyChange, below.
1060 setBlockGuardPolicy(policyMask);
1061
1062 // And set the Android native version...
1063 Binder.setThreadStrictModePolicy(policyMask);
1064 }
1065
1066 // Sets the policy in Dalvik/libcore (BlockGuard)
1067 private static void setBlockGuardPolicy(final int policyMask) {
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001068 if (policyMask == 0) {
1069 BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
1070 return;
1071 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001072 final BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1073 final AndroidBlockGuardPolicy androidPolicy;
1074 if (policy instanceof AndroidBlockGuardPolicy) {
1075 androidPolicy = (AndroidBlockGuardPolicy) policy;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001076 } else {
Kurt Nelson46974a22017-08-30 13:30:26 -07001077 androidPolicy = THREAD_ANDROID_POLICY.get();
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001078 BlockGuard.setThreadPolicy(androidPolicy);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001079 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001080 androidPolicy.setPolicyMask(policyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001081 }
1082
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001083 // Sets up CloseGuard in Dalvik/libcore
1084 private static void setCloseGuardEnabled(boolean enabled) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -08001085 if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001086 CloseGuard.setReporter(new AndroidCloseGuardReporter());
1087 }
1088 CloseGuard.setEnabled(enabled);
1089 }
1090
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001091 /**
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -07001092 * Returns the bitmask of the current thread's policy.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001093 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001094 * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001095 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001096 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001097 public static int getThreadPolicyMask() {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001098 return BlockGuard.getThreadPolicy().getPolicyMask();
1099 }
1100
Kurt Nelson46974a22017-08-30 13:30:26 -07001101 /** Returns the current thread's policy. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001102 public static ThreadPolicy getThreadPolicy() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001103 // TODO: this was a last minute Gingerbread API change (to
1104 // introduce VmPolicy cleanly) but this isn't particularly
1105 // optimal for users who might call this method often. This
1106 // should be in a thread-local and not allocate on each call.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001107 return new ThreadPolicy(
1108 getThreadPolicyMask(),
1109 sThreadViolationListener.get(),
1110 sThreadViolationExecutor.get());
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001111 }
1112
1113 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001114 * A convenience wrapper that takes the current {@link ThreadPolicy} from {@link
1115 * #getThreadPolicy}, modifies it to permit both disk reads &amp; writes, and sets the new
1116 * policy with {@link #setThreadPolicy}, returning the old policy so you can restore it at the
1117 * end of a block.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001118 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001119 * @return the old policy, to be passed to {@link #setThreadPolicy} to restore the policy at the
1120 * end of a block
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001121 */
1122 public static ThreadPolicy allowThreadDiskWrites() {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001123 return new ThreadPolicy(
1124 allowThreadDiskWritesMask(),
1125 sThreadViolationListener.get(),
1126 sThreadViolationExecutor.get());
Jeff Sharkey89182982017-11-01 19:02:56 -06001127 }
1128
1129 /** @hide */
1130 public static int allowThreadDiskWritesMask() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001131 int oldPolicyMask = getThreadPolicyMask();
1132 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
1133 if (newPolicyMask != oldPolicyMask) {
1134 setThreadPolicyMask(newPolicyMask);
1135 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001136 return oldPolicyMask;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001137 }
1138
1139 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001140 * A convenience wrapper that takes the current {@link ThreadPolicy} from {@link
1141 * #getThreadPolicy}, modifies it to permit disk reads, and sets the new policy with {@link
1142 * #setThreadPolicy}, returning the old policy so you can restore it at the end of a block.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001143 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001144 * @return the old policy, to be passed to setThreadPolicy to restore the policy.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001145 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001146 public static ThreadPolicy allowThreadDiskReads() {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001147 return new ThreadPolicy(
1148 allowThreadDiskReadsMask(),
1149 sThreadViolationListener.get(),
1150 sThreadViolationExecutor.get());
Jeff Sharkey89182982017-11-01 19:02:56 -06001151 }
1152
1153 /** @hide */
1154 public static int allowThreadDiskReadsMask() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001155 int oldPolicyMask = getThreadPolicyMask();
1156 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
1157 if (newPolicyMask != oldPolicyMask) {
1158 setThreadPolicyMask(newPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001159 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001160 return oldPolicyMask;
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001161 }
1162
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001163 private static ThreadPolicy allowThreadViolations() {
1164 ThreadPolicy oldPolicy = getThreadPolicy();
1165 setThreadPolicyMask(0);
1166 return oldPolicy;
1167 }
1168
1169 private static VmPolicy allowVmViolations() {
1170 VmPolicy oldPolicy = getVmPolicy();
1171 sVmPolicy = VmPolicy.LAX;
1172 return oldPolicy;
1173 }
1174
Jeff Sharkey89182982017-11-01 19:02:56 -06001175 /**
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001176 * Determine if the given app is "bundled" as part of the system image. These bundled apps are
1177 * developed in lock-step with the OS, and they aren't updated outside of an OTA, so we want to
1178 * chase any {@link StrictMode} regressions by enabling detection when running on {@link
1179 * Build#IS_USERDEBUG} or {@link Build#IS_ENG} builds.
1180 *
1181 * <p>Unbundled apps included in the system image are expected to detect and triage their own
1182 * {@link StrictMode} issues separate from the OS release process, which is why we don't enable
1183 * them here.
Jeff Sharkey89182982017-11-01 19:02:56 -06001184 *
1185 * @hide
1186 */
1187 public static boolean isBundledSystemApp(ApplicationInfo ai) {
1188 if (ai == null || ai.packageName == null) {
1189 // Probably system server
1190 return true;
1191 } else if (ai.isSystemApp()) {
1192 // Ignore unbundled apps living in the wrong namespace
1193 if (ai.packageName.equals("com.android.vending")
1194 || ai.packageName.equals("com.android.chrome")) {
1195 return false;
1196 }
Brad Fitzpatrickf5454592010-11-24 15:27:51 -08001197
Jeff Sharkey89182982017-11-01 19:02:56 -06001198 // Ignore bundled apps that are way too spammy
1199 // STOPSHIP: burn this list down to zero
1200 if (ai.packageName.equals("com.android.phone")) {
1201 return false;
1202 }
1203
1204 if (ai.packageName.equals("android")
1205 || ai.packageName.startsWith("android.")
1206 || ai.packageName.startsWith("com.android.")) {
Brad Fitzpatrickf5454592010-11-24 15:27:51 -08001207 return true;
1208 }
1209 }
1210 return false;
1211 }
1212
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001213 /**
Jeff Sharkey89182982017-11-01 19:02:56 -06001214 * Initialize default {@link ThreadPolicy} for the current thread.
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001215 *
1216 * @hide
1217 */
Jeff Sharkey89182982017-11-01 19:02:56 -06001218 public static void initThreadDefaults(ApplicationInfo ai) {
1219 final ThreadPolicy.Builder builder = new ThreadPolicy.Builder();
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001220 final int targetSdkVersion =
1221 (ai != null) ? ai.targetSdkVersion : Build.VERSION_CODES.CUR_DEVELOPMENT;
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001222
Jeff Sharkey89182982017-11-01 19:02:56 -06001223 // Starting in HC, we don't allow network usage on the main thread
1224 if (targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
1225 builder.detectNetwork();
1226 builder.penaltyDeathOnNetwork();
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001227 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001228
Jeff Sharkey89182982017-11-01 19:02:56 -06001229 if (Build.IS_USER || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) {
1230 // Detect nothing extra
1231 } else if (Build.IS_USERDEBUG) {
1232 // Detect everything in bundled apps
1233 if (isBundledSystemApp(ai)) {
1234 builder.detectAll();
1235 builder.penaltyDropBox();
1236 if (SystemProperties.getBoolean(VISUAL_PROPERTY, false)) {
1237 builder.penaltyFlashScreen();
1238 }
Mathieu Chartierca8c1052017-06-19 18:42:57 -07001239 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001240 } else if (Build.IS_ENG) {
1241 // Detect everything in bundled apps
1242 if (isBundledSystemApp(ai)) {
1243 builder.detectAll();
1244 builder.penaltyDropBox();
1245 builder.penaltyLog();
1246 builder.penaltyFlashScreen();
Jeff Brownd5875d92011-10-09 14:59:37 -07001247 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001248 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001249
1250 setThreadPolicy(builder.build());
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001251 }
1252
1253 /**
Jeff Sharkey89182982017-11-01 19:02:56 -06001254 * Initialize default {@link VmPolicy} for the current VM.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001255 *
1256 * @hide
1257 */
Jeff Sharkey89182982017-11-01 19:02:56 -06001258 public static void initVmDefaults(ApplicationInfo ai) {
1259 final VmPolicy.Builder builder = new VmPolicy.Builder();
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001260 final int targetSdkVersion =
1261 (ai != null) ? ai.targetSdkVersion : Build.VERSION_CODES.CUR_DEVELOPMENT;
Jeff Sharkey89182982017-11-01 19:02:56 -06001262
1263 // Starting in N, we don't allow file:// Uri exposure
1264 if (targetSdkVersion >= Build.VERSION_CODES.N) {
1265 builder.detectFileUriExposure();
1266 builder.penaltyDeathOnFileUriExposure();
1267 }
1268
1269 if (Build.IS_USER || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) {
1270 // Detect nothing extra
1271 } else if (Build.IS_USERDEBUG) {
1272 // Detect everything in bundled apps (except activity leaks, which
1273 // are expensive to track)
1274 if (isBundledSystemApp(ai)) {
1275 builder.detectAll();
1276 builder.permitActivityLeaks();
1277 builder.penaltyDropBox();
1278 }
1279 } else if (Build.IS_ENG) {
1280 // Detect everything in bundled apps
1281 if (isBundledSystemApp(ai)) {
1282 builder.detectAll();
1283 builder.penaltyDropBox();
1284 builder.penaltyLog();
1285 }
1286 }
1287
1288 setVmPolicy(builder.build());
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001289 }
1290
1291 /**
Jeff Sharkey344744b2016-01-28 19:03:30 -07001292 * Used by the framework to make file usage a fatal error.
1293 *
1294 * @hide
1295 */
1296 public static void enableDeathOnFileUriExposure() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001297 sVmPolicy =
1298 new VmPolicy(
1299 sVmPolicy.mask
1300 | DETECT_VM_FILE_URI_EXPOSURE
1301 | PENALTY_DEATH_ON_FILE_URI_EXPOSURE,
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001302 sVmPolicy.classInstanceLimit,
1303 sVmPolicy.mListener,
1304 sVmPolicy.mCallbackExecutor);
Jeff Sharkey344744b2016-01-28 19:03:30 -07001305 }
1306
1307 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001308 * Used by lame internal apps that haven't done the hard work to get themselves off file:// Uris
1309 * yet.
Jeff Sharkey344744b2016-01-28 19:03:30 -07001310 *
1311 * @hide
1312 */
1313 public static void disableDeathOnFileUriExposure() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001314 sVmPolicy =
1315 new VmPolicy(
1316 sVmPolicy.mask
1317 & ~(DETECT_VM_FILE_URI_EXPOSURE
1318 | PENALTY_DEATH_ON_FILE_URI_EXPOSURE),
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001319 sVmPolicy.classInstanceLimit,
1320 sVmPolicy.mListener,
1321 sVmPolicy.mCallbackExecutor);
Jeff Sharkey344744b2016-01-28 19:03:30 -07001322 }
1323
1324 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001325 * Parses the BlockGuard policy mask out from the Exception's getMessage() String value. Kinda
1326 * gross, but least invasive. :/
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001327 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001328 * <p>Input is of the following forms: "policy=137 violation=64" "policy=137 violation=64
1329 * msg=Arbitrary text"
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001330 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001331 * <p>Returns 0 on failure, which is a valid policy, but not a valid policy during a violation
1332 * (else there must've been some policy in effect to violate).
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001333 */
1334 private static int parsePolicyFromMessage(String message) {
1335 if (message == null || !message.startsWith("policy=")) {
1336 return 0;
1337 }
1338 int spaceIndex = message.indexOf(' ');
1339 if (spaceIndex == -1) {
1340 return 0;
1341 }
1342 String policyString = message.substring(7, spaceIndex);
1343 try {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001344 return Integer.parseInt(policyString);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001345 } catch (NumberFormatException e) {
1346 return 0;
1347 }
1348 }
1349
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001350 private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
1351 new ThreadLocal<ArrayList<ViolationInfo>>() {
Kurt Nelson46974a22017-08-30 13:30:26 -07001352 @Override
1353 protected ArrayList<ViolationInfo> initialValue() {
1354 return new ArrayList<ViolationInfo>();
1355 }
1356 };
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001357
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001358 // Note: only access this once verifying the thread has a Looper.
Kurt Nelson46974a22017-08-30 13:30:26 -07001359 private static final ThreadLocal<Handler> THREAD_HANDLER =
1360 new ThreadLocal<Handler>() {
1361 @Override
1362 protected Handler initialValue() {
1363 return new Handler();
1364 }
1365 };
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001366
Kurt Nelson46974a22017-08-30 13:30:26 -07001367 private static final ThreadLocal<AndroidBlockGuardPolicy> THREAD_ANDROID_POLICY =
1368 new ThreadLocal<AndroidBlockGuardPolicy>() {
1369 @Override
1370 protected AndroidBlockGuardPolicy initialValue() {
1371 return new AndroidBlockGuardPolicy(0);
1372 }
1373 };
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001374
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001375 private static boolean tooManyViolationsThisLoop() {
1376 return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
1377 }
1378
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001379 private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
1380 private int mPolicyMask;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001381
1382 // Map from violation stacktrace hashcode -> uptimeMillis of
1383 // last violation. No locking needed, as this is only
1384 // accessed by the same thread.
Dianne Hackborn390517b2013-05-30 15:03:32 -07001385 private ArrayMap<Integer, Long> mLastViolationTime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001386
1387 public AndroidBlockGuardPolicy(final int policyMask) {
1388 mPolicyMask = policyMask;
1389 }
1390
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001391 @Override
1392 public String toString() {
1393 return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
1394 }
1395
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001396 // Part of BlockGuard.Policy interface:
1397 public int getPolicyMask() {
1398 return mPolicyMask;
1399 }
1400
1401 // Part of BlockGuard.Policy interface:
1402 public void onWriteToDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001403 if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001404 return;
1405 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001406 if (tooManyViolationsThisLoop()) {
1407 return;
1408 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001409 startHandlingViolationException(new DiskWriteViolation());
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001410 }
1411
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001412 // Not part of BlockGuard.Policy; just part of StrictMode:
1413 void onCustomSlowCall(String name) {
1414 if ((mPolicyMask & DETECT_CUSTOM) == 0) {
1415 return;
1416 }
1417 if (tooManyViolationsThisLoop()) {
1418 return;
1419 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001420 startHandlingViolationException(new CustomViolation(name));
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001421 }
1422
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001423 // Not part of BlockGuard.Policy; just part of StrictMode:
1424 void onResourceMismatch(Object tag) {
1425 if ((mPolicyMask & DETECT_RESOURCE_MISMATCH) == 0) {
1426 return;
1427 }
1428 if (tooManyViolationsThisLoop()) {
1429 return;
1430 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001431 startHandlingViolationException(new ResourceMismatchViolation(tag));
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001432 }
1433
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001434 // Not part of BlockGuard.Policy; just part of StrictMode:
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001435 public void onUnbufferedIO() {
1436 if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
1437 return;
1438 }
1439 if (tooManyViolationsThisLoop()) {
1440 return;
1441 }
Kurt Nelson0e612802017-11-09 17:25:40 -08001442 startHandlingViolationException(new UnbufferedIoViolation());
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001443 }
1444
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001445 // Part of BlockGuard.Policy interface:
1446 public void onReadFromDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001447 if ((mPolicyMask & DETECT_DISK_READ) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001448 return;
1449 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001450 if (tooManyViolationsThisLoop()) {
1451 return;
1452 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001453 startHandlingViolationException(new DiskReadViolation());
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001454 }
1455
1456 // Part of BlockGuard.Policy interface:
1457 public void onNetwork() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001458 if ((mPolicyMask & DETECT_NETWORK) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001459 return;
1460 }
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001461 if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
1462 throw new NetworkOnMainThreadException();
1463 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001464 if (tooManyViolationsThisLoop()) {
1465 return;
1466 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001467 startHandlingViolationException(new NetworkViolation());
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001468 }
1469
1470 public void setPolicyMask(int policyMask) {
1471 mPolicyMask = policyMask;
1472 }
1473
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001474 // Start handling a violation that just started and hasn't
1475 // actually run yet (e.g. no disk write or network operation
1476 // has yet occurred). This sees if we're in an event loop
1477 // thread and, if so, uses it to roughly measure how long the
1478 // violation took.
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001479 void startHandlingViolationException(Violation e) {
1480 final ViolationInfo info = new ViolationInfo(e, mPolicyMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001481 info.violationUptimeMillis = SystemClock.uptimeMillis();
1482 handleViolationWithTimingAttempt(info);
1483 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001484
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001485 // Attempts to fill in the provided ViolationInfo's
1486 // durationMillis field if this thread has a Looper we can use
1487 // to measure with. We measure from the time of violation
1488 // until the time the looper is idle again (right before
1489 // the next epoll_wait)
1490 void handleViolationWithTimingAttempt(final ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001491 Looper looper = Looper.myLooper();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001492
1493 // Without a Looper, we're unable to time how long the
1494 // violation takes place. This case should be rare, as
1495 // most users will care about timing violations that
1496 // happen on their main UI thread. Note that this case is
1497 // also hit when a violation takes place in a Binder
1498 // thread, in "gather" mode. In this case, the duration
1499 // of the violation is computed by the ultimate caller and
1500 // its Looper, if any.
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001501 //
1502 // Also, as a special short-cut case when the only penalty
1503 // bit is death, we die immediately, rather than timing
1504 // the violation's duration. This makes it convenient to
1505 // use in unit tests too, rather than waiting on a Looper.
1506 //
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001507 // TODO: if in gather mode, ignore Looper.myLooper() and always
1508 // go into this immediate mode?
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001509 if (looper == null || (info.mPolicy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
Kurt Nelson46974a22017-08-30 13:30:26 -07001510 info.durationMillis = -1; // unknown (redundant, already set)
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001511 onThreadPolicyViolation(info);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001512 return;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001513 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001514
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001515 final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001516 if (records.size() >= MAX_OFFENSES_PER_LOOP) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001517 // Not worth measuring. Too many offenses in one loop.
1518 return;
1519 }
1520 records.add(info);
1521 if (records.size() > 1) {
1522 // There's already been a violation this loop, so we've already
1523 // registered an idle handler to process the list of violations
1524 // at the end of this Looper's loop.
1525 return;
1526 }
1527
Kurt Nelson46974a22017-08-30 13:30:26 -07001528 final IWindowManager windowManager =
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001529 info.penaltyEnabled(PENALTY_FLASH) ? sWindowManager.get() : null;
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001530 if (windowManager != null) {
1531 try {
1532 windowManager.showStrictModeViolation(true);
1533 } catch (RemoteException unused) {
1534 }
1535 }
1536
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001537 // We post a runnable to a Handler (== delay 0 ms) for
1538 // measuring the end time of a violation instead of using
1539 // an IdleHandler (as was previously used) because an
1540 // IdleHandler may not run for quite a long period of time
1541 // if an ongoing animation is happening and continually
1542 // posting ASAP (0 ms) animation steps. Animations are
1543 // throttled back to 60fps via SurfaceFlinger/View
1544 // invalidates, _not_ by posting frame updates every 16
1545 // milliseconds.
Kurt Nelson46974a22017-08-30 13:30:26 -07001546 THREAD_HANDLER
1547 .get()
1548 .postAtFrontOfQueue(
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001549 () -> {
1550 long loopFinishTime = SystemClock.uptimeMillis();
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001551
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001552 // Note: we do this early, before handling the
1553 // violation below, as handling the violation
1554 // may include PENALTY_DEATH and we don't want
1555 // to keep the red border on.
1556 if (windowManager != null) {
1557 try {
1558 windowManager.showStrictModeViolation(false);
1559 } catch (RemoteException unused) {
Kurt Nelson46974a22017-08-30 13:30:26 -07001560 }
Kurt Nelson46974a22017-08-30 13:30:26 -07001561 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001562
1563 for (int n = 0; n < records.size(); ++n) {
1564 ViolationInfo v = records.get(n);
1565 v.violationNumThisLoop = n + 1;
1566 v.durationMillis =
1567 (int) (loopFinishTime - v.violationUptimeMillis);
1568 onThreadPolicyViolation(v);
1569 }
1570 records.clear();
Kurt Nelson46974a22017-08-30 13:30:26 -07001571 });
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001572 }
1573
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001574 // Note: It's possible (even quite likely) that the
1575 // thread-local policy mask has changed from the time the
1576 // violation fired and now (after the violating code ran) due
1577 // to people who push/pop temporary policy in regions of code,
1578 // hence the policy being passed around.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001579 void onThreadPolicyViolation(final ViolationInfo info) {
1580 if (LOG_V) Log.d(TAG, "onThreadPolicyViolation; policy=" + info.mPolicy);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001581
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001582 if (info.penaltyEnabled(PENALTY_GATHER)) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001583 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001584 if (violations == null) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001585 violations = new ArrayList<>(1);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001586 gatheredViolations.set(violations);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001587 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001588 for (ViolationInfo previous : violations) {
Kurt Nelson0918c932017-09-07 10:56:56 -07001589 if (info.getStackTrace().equals(previous.getStackTrace())) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001590 // Duplicate. Don't log.
1591 return;
1592 }
1593 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001594 violations.add(info);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001595 return;
1596 }
1597
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001598 // Not perfect, but fast and good enough for dup suppression.
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08001599 Integer crashFingerprint = info.hashCode();
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001600 long lastViolationTime = 0;
Dianne Hackborn390517b2013-05-30 15:03:32 -07001601 if (mLastViolationTime != null) {
1602 Long vtime = mLastViolationTime.get(crashFingerprint);
1603 if (vtime != null) {
1604 lastViolationTime = vtime;
1605 }
1606 } else {
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07001607 mLastViolationTime = new ArrayMap<>(1);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001608 }
1609 long now = SystemClock.uptimeMillis();
1610 mLastViolationTime.put(crashFingerprint, now);
Kurt Nelson46974a22017-08-30 13:30:26 -07001611 long timeSinceLastViolationMillis =
1612 lastViolationTime == 0 ? Long.MAX_VALUE : (now - lastViolationTime);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001613
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001614 if (info.penaltyEnabled(PENALTY_LOG)
Kurt Nelson46974a22017-08-30 13:30:26 -07001615 && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07001616 sLogger.log(info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001617 }
1618
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001619 final Violation violation = info.mViolation;
1620
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001621 // The violationMaskSubset, passed to ActivityManager, is a
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001622 // subset of the original StrictMode policy bitmask, with
1623 // only the bit violated and penalty bits to be executed
1624 // by the ActivityManagerService remaining set.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001625 int violationMaskSubset = 0;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001626
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001627 if (info.penaltyEnabled(PENALTY_DIALOG)
Kurt Nelson46974a22017-08-30 13:30:26 -07001628 && timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001629 violationMaskSubset |= PENALTY_DIALOG;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001630 }
1631
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001632 if (info.penaltyEnabled(PENALTY_DROPBOX) && lastViolationTime == 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001633 violationMaskSubset |= PENALTY_DROPBOX;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001634 }
1635
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001636 if (violationMaskSubset != 0) {
Kurt Nelson0918c932017-09-07 10:56:56 -07001637 violationMaskSubset |= info.getViolationBit();
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001638
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001639 final boolean justDropBox = (info.mPolicy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001640 if (justDropBox) {
1641 // If all we're going to ask the activity manager
1642 // to do is dropbox it (the common case during
1643 // platform development), we can avoid doing this
1644 // call synchronously which Binder data suggests
1645 // isn't always super fast, despite the implementation
1646 // in the ActivityManager trying to be mostly async.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001647 dropboxViolationAsync(violationMaskSubset, info);
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -07001648 } else {
1649 handleApplicationStrictModeViolation(violationMaskSubset, info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001650 }
1651 }
1652
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001653 if ((info.getPolicyMask() & PENALTY_DEATH) != 0) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001654 throw new RuntimeException("StrictMode ThreadPolicy violation", violation);
1655 }
1656
1657 // penaltyDeath will cause penaltyCallback to no-op since we cannot guarantee the
1658 // executor finishes before crashing.
1659 final OnThreadViolationListener listener = sThreadViolationListener.get();
1660 final Executor executor = sThreadViolationExecutor.get();
1661 if (listener != null && executor != null) {
1662 try {
1663 executor.execute(
1664 () -> {
1665 // Lift violated policy to prevent infinite recursion.
1666 ThreadPolicy oldPolicy = allowThreadViolations();
1667 try {
1668 listener.onThreadViolation(violation);
1669 } finally {
1670 setThreadPolicy(oldPolicy);
1671 }
1672 });
1673 } catch (RejectedExecutionException e) {
1674 Log.e(TAG, "ThreadPolicy penaltyCallback failed", e);
1675 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001676 }
1677 }
1678 }
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001679
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001680 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001681 * In the common case, as set by conditionallyEnableDebugLogging, we're just dropboxing any
1682 * violations but not showing a dialog, not loggging, and not killing the process. In these
1683 * cases we don't need to do a synchronous call to the ActivityManager. This is used by both
1684 * per-thread and vm-wide violations when applicable.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001685 */
1686 private static void dropboxViolationAsync(
1687 final int violationMaskSubset, final ViolationInfo info) {
1688 int outstanding = sDropboxCallsInFlight.incrementAndGet();
1689 if (outstanding > 20) {
1690 // What's going on? Let's not make make the situation
1691 // worse and just not log.
1692 sDropboxCallsInFlight.decrementAndGet();
1693 return;
1694 }
1695
1696 if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1697
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -07001698 BackgroundThread.getHandler().post(() -> {
1699 handleApplicationStrictModeViolation(violationMaskSubset, info);
1700 int outstandingInner = sDropboxCallsInFlight.decrementAndGet();
1701 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstandingInner);
1702 });
1703 }
1704
1705 private static void handleApplicationStrictModeViolation(int violationMaskSubset,
1706 ViolationInfo info) {
1707 final int oldMask = getThreadPolicyMask();
1708 try {
1709 // First, remove any policy before we call into the Activity Manager,
1710 // otherwise we'll infinite recurse as we try to log policy violations
1711 // to disk, thus violating policy, thus requiring logging, etc...
1712 // We restore the current policy below, in the finally block.
1713 setThreadPolicyMask(0);
1714
1715 IActivityManager am = ActivityManager.getService();
1716 if (am == null) {
1717 Log.w(TAG, "No activity manager; failed to Dropbox violation.");
1718 } else {
1719 am.handleApplicationStrictModeViolation(
1720 RuntimeInit.getApplicationObject(), violationMaskSubset, info);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001721 }
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -07001722 } catch (RemoteException e) {
1723 if (e instanceof DeadObjectException) {
1724 // System process is dead; ignore
1725 } else {
1726 Log.e(TAG, "RemoteException handling StrictMode violation", e);
1727 }
1728 } finally {
1729 setThreadPolicyMask(oldMask);
1730 }
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001731 }
1732
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001733 private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
Jeff Sharkey605eb792014-11-04 13:34:06 -08001734 public void report(String message, Throwable allocationSite) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001735 onVmPolicyViolation(new LeakedClosableViolation(message, allocationSite));
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001736 }
1737 }
1738
Kurt Nelson46974a22017-08-30 13:30:26 -07001739 /** Called from Parcel.writeNoException() */
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001740 /* package */ static boolean hasGatheredViolations() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001741 return gatheredViolations.get() != null;
1742 }
1743
1744 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001745 * Called from Parcel.writeException(), so we drop this memory and don't incorrectly attribute
1746 * it to the wrong caller on the next Binder call on this thread.
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001747 */
1748 /* package */ static void clearGatheredViolations() {
1749 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001750 }
1751
Kurt Nelson46974a22017-08-30 13:30:26 -07001752 /** @hide */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001753 public static void conditionallyCheckInstanceCounts() {
1754 VmPolicy policy = getVmPolicy();
Mathieu Chartierd288a262015-07-10 13:44:42 -07001755 int policySize = policy.classInstanceLimit.size();
1756 if (policySize == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001757 return;
1758 }
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08001759
1760 System.gc();
1761 System.runFinalization();
1762 System.gc();
1763
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001764 // Note: classInstanceLimit is immutable, so this is lock-free
Mathieu Chartierd288a262015-07-10 13:44:42 -07001765 // Create the classes array.
1766 Class[] classes = policy.classInstanceLimit.keySet().toArray(new Class[policySize]);
1767 long[] instanceCounts = VMDebug.countInstancesOfClasses(classes, false);
1768 for (int i = 0; i < classes.length; ++i) {
1769 Class klass = classes[i];
1770 int limit = policy.classInstanceLimit.get(klass);
1771 long instances = instanceCounts[i];
1772 if (instances > limit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001773 onVmPolicyViolation(new InstanceCountViolation(klass, instances, limit));
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001774 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001775 }
1776 }
1777
1778 private static long sLastInstanceCountCheckMillis = 0;
Kurt Nelson46974a22017-08-30 13:30:26 -07001779 private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001780 private static final MessageQueue.IdleHandler sProcessIdleHandler =
1781 new MessageQueue.IdleHandler() {
1782 public boolean queueIdle() {
1783 long now = SystemClock.uptimeMillis();
1784 if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1785 sLastInstanceCountCheckMillis = now;
1786 conditionallyCheckInstanceCounts();
1787 }
1788 return true;
1789 }
1790 };
1791
1792 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001793 * Sets the policy for what actions in the VM process (on any thread) should be detected, as
1794 * well as the penalty if such actions occur.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001795 *
1796 * @param policy the policy to put into place
1797 */
1798 public static void setVmPolicy(final VmPolicy policy) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001799 synchronized (StrictMode.class) {
1800 sVmPolicy = policy;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001801 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001802
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001803 Looper looper = Looper.getMainLooper();
1804 if (looper != null) {
1805 MessageQueue mq = looper.mQueue;
Kurt Nelson46974a22017-08-30 13:30:26 -07001806 if (policy.classInstanceLimit.size() == 0
Kurt Nelson2c883f32017-09-01 10:52:45 -07001807 || (sVmPolicy.mask & VM_PENALTY_MASK) == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001808 mq.removeIdleHandler(sProcessIdleHandler);
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001809 sIsIdlerRegistered = false;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001810 } else if (!sIsIdlerRegistered) {
1811 mq.addIdleHandler(sProcessIdleHandler);
1812 sIsIdlerRegistered = true;
1813 }
1814 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08001815
1816 int networkPolicy = NETWORK_POLICY_ACCEPT;
Kurt Nelson2c883f32017-09-01 10:52:45 -07001817 if ((sVmPolicy.mask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
1818 if ((sVmPolicy.mask & PENALTY_DEATH) != 0
1819 || (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
Jeff Sharkey605eb792014-11-04 13:34:06 -08001820 networkPolicy = NETWORK_POLICY_REJECT;
1821 } else {
1822 networkPolicy = NETWORK_POLICY_LOG;
1823 }
1824 }
1825
Kurt Nelson46974a22017-08-30 13:30:26 -07001826 final INetworkManagementService netd =
1827 INetworkManagementService.Stub.asInterface(
1828 ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
Jeff Sharkey605eb792014-11-04 13:34:06 -08001829 if (netd != null) {
1830 try {
1831 netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
1832 } catch (RemoteException ignored) {
1833 }
1834 } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
1835 Log.w(TAG, "Dropping requested network policy due to missing service!");
1836 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001837 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001838 }
1839
Kurt Nelson46974a22017-08-30 13:30:26 -07001840 /** Gets the current VM policy. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001841 public static VmPolicy getVmPolicy() {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001842 synchronized (StrictMode.class) {
1843 return sVmPolicy;
1844 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001845 }
1846
1847 /**
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001848 * Enable the recommended StrictMode defaults, with violations just being logged.
1849 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001850 * <p>This catches disk and network access on the main thread, as well as leaked SQLite cursors
1851 * and unclosed resources. This is simply a wrapper around {@link #setVmPolicy} and {@link
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001852 * #setThreadPolicy}.
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001853 */
1854 public static void enableDefaults() {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001855 setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
1856 setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001857 }
1858
Kurt Nelson46974a22017-08-30 13:30:26 -07001859 /** @hide */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001860 public static boolean vmSqliteObjectLeaksEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001861 return (sVmPolicy.mask & DETECT_VM_CURSOR_LEAKS) != 0;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001862 }
1863
Kurt Nelson46974a22017-08-30 13:30:26 -07001864 /** @hide */
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001865 public static boolean vmClosableObjectLeaksEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001866 return (sVmPolicy.mask & DETECT_VM_CLOSABLE_LEAKS) != 0;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001867 }
1868
Kurt Nelson46974a22017-08-30 13:30:26 -07001869 /** @hide */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001870 public static boolean vmRegistrationLeaksEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001871 return (sVmPolicy.mask & DETECT_VM_REGISTRATION_LEAKS) != 0;
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001872 }
1873
Kurt Nelson46974a22017-08-30 13:30:26 -07001874 /** @hide */
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001875 public static boolean vmFileUriExposureEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001876 return (sVmPolicy.mask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001877 }
1878
Kurt Nelson46974a22017-08-30 13:30:26 -07001879 /** @hide */
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -07001880 public static boolean vmCleartextNetworkEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001881 return (sVmPolicy.mask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07001882 }
1883
Kurt Nelson46974a22017-08-30 13:30:26 -07001884 /** @hide */
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -07001885 public static boolean vmContentUriWithoutPermissionEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001886 return (sVmPolicy.mask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
Jeff Sharkey605eb792014-11-04 13:34:06 -08001887 }
1888
Kurt Nelson46974a22017-08-30 13:30:26 -07001889 /** @hide */
Jeff Sharkey619a5112017-01-19 11:55:54 -07001890 public static boolean vmUntaggedSocketEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001891 return (sVmPolicy.mask & DETECT_VM_UNTAGGED_SOCKET) != 0;
Jeff Sharkey619a5112017-01-19 11:55:54 -07001892 }
1893
Kurt Nelson46974a22017-08-30 13:30:26 -07001894 /** @hide */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001895 public static void onSqliteObjectLeaked(String message, Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001896 onVmPolicyViolation(new SqliteObjectLeakedViolation(message, originStack));
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001897 }
1898
Kurt Nelson46974a22017-08-30 13:30:26 -07001899 /** @hide */
Steve Block08d584c2011-05-17 19:05:03 +01001900 public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001901 onVmPolicyViolation(new WebViewMethodCalledOnWrongThreadViolation(originStack));
Steve Block08d584c2011-05-17 19:05:03 +01001902 }
1903
Kurt Nelson46974a22017-08-30 13:30:26 -07001904 /** @hide */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001905 public static void onIntentReceiverLeaked(Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001906 onVmPolicyViolation(new IntentReceiverLeakedViolation(originStack));
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001907 }
1908
Kurt Nelson46974a22017-08-30 13:30:26 -07001909 /** @hide */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001910 public static void onServiceConnectionLeaked(Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001911 onVmPolicyViolation(new ServiceConnectionLeakedViolation(originStack));
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001912 }
1913
Kurt Nelson46974a22017-08-30 13:30:26 -07001914 /** @hide */
Jeff Sharkey344744b2016-01-28 19:03:30 -07001915 public static void onFileUriExposed(Uri uri, String location) {
1916 final String message = uri + " exposed beyond app through " + location;
Kurt Nelson2c883f32017-09-01 10:52:45 -07001917 if ((sVmPolicy.mask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
Jeff Sharkey344744b2016-01-28 19:03:30 -07001918 throw new FileUriExposedException(message);
1919 } else {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001920 onVmPolicyViolation(new FileUriExposedViolation(message));
Jeff Sharkey344744b2016-01-28 19:03:30 -07001921 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08001922 }
1923
Kurt Nelson46974a22017-08-30 13:30:26 -07001924 /** @hide */
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07001925 public static void onContentUriWithoutPermission(Uri uri, String location) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001926 onVmPolicyViolation(new ContentUriWithoutPermissionViolation(uri, location));
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07001927 }
1928
Kurt Nelson46974a22017-08-30 13:30:26 -07001929 /** @hide */
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -07001930 public static final String CLEARTEXT_DETECTED_MSG =
1931 "Detected cleartext network traffic from UID ";
1932
1933 /** @hide */
Jeff Sharkey605eb792014-11-04 13:34:06 -08001934 public static void onCleartextNetworkDetected(byte[] firstPacket) {
1935 byte[] rawAddr = null;
1936 if (firstPacket != null) {
1937 if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
1938 // IPv4
1939 rawAddr = new byte[4];
1940 System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
1941 } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
1942 // IPv6
1943 rawAddr = new byte[16];
1944 System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
1945 }
1946 }
1947
1948 final int uid = android.os.Process.myUid();
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -07001949 String msg = CLEARTEXT_DETECTED_MSG + uid;
Jeff Sharkey605eb792014-11-04 13:34:06 -08001950 if (rawAddr != null) {
1951 try {
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -07001952 msg += " to " + InetAddress.getByAddress(rawAddr);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001953 } catch (UnknownHostException ignored) {
1954 }
1955 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07001956 msg += HexDump.dumpHexString(firstPacket).trim() + " ";
Kurt Nelson2c883f32017-09-01 10:52:45 -07001957 final boolean forceDeath = (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001958 onVmPolicyViolation(new CleartextNetworkViolation(msg), forceDeath);
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001959 }
1960
Kurt Nelson46974a22017-08-30 13:30:26 -07001961 /** @hide */
Jeff Sharkey619a5112017-01-19 11:55:54 -07001962 public static void onUntaggedSocket() {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001963 onVmPolicyViolation(new UntaggedSocketViolation());
Jeff Sharkey619a5112017-01-19 11:55:54 -07001964 }
1965
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001966 // Map from VM violation fingerprint to uptime millis.
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001967 private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<>();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001968
Kurt Nelson46974a22017-08-30 13:30:26 -07001969 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001970 public static void onVmPolicyViolation(Violation originStack) {
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07001971 onVmPolicyViolation(originStack, false);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001972 }
1973
Kurt Nelson46974a22017-08-30 13:30:26 -07001974 /** @hide */
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001975 public static void onVmPolicyViolation(Violation violation, boolean forceDeath) {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001976 final boolean penaltyDropbox = (sVmPolicy.mask & PENALTY_DROPBOX) != 0;
1977 final boolean penaltyDeath = ((sVmPolicy.mask & PENALTY_DEATH) != 0) || forceDeath;
1978 final boolean penaltyLog = (sVmPolicy.mask & PENALTY_LOG) != 0;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001979 final ViolationInfo info = new ViolationInfo(violation, sVmPolicy.mask);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001980
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001981 // Erase stuff not relevant for process-wide violations
1982 info.numAnimationsRunning = 0;
1983 info.tags = null;
1984 info.broadcastIntentAction = null;
1985
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001986 final Integer fingerprint = info.hashCode();
1987 final long now = SystemClock.uptimeMillis();
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001988 long lastViolationTime;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001989 long timeSinceLastViolationMillis = Long.MAX_VALUE;
1990 synchronized (sLastVmViolationTime) {
1991 if (sLastVmViolationTime.containsKey(fingerprint)) {
1992 lastViolationTime = sLastVmViolationTime.get(fingerprint);
1993 timeSinceLastViolationMillis = now - lastViolationTime;
1994 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001995 if (timeSinceLastViolationMillis > MIN_VM_INTERVAL_MS) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001996 sLastVmViolationTime.put(fingerprint, now);
1997 }
1998 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001999 if (timeSinceLastViolationMillis <= MIN_VM_INTERVAL_MS) {
2000 // Rate limit all penalties.
2001 return;
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -06002002 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002003
2004 if (penaltyLog && sLogger != null && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07002005 sLogger.log(info);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002006 }
2007
Kurt Nelson2c883f32017-09-01 10:52:45 -07002008 int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicy.mask);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08002009
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002010 if (penaltyDropbox) {
2011 if (penaltyDeath) {
2012 handleApplicationStrictModeViolation(violationMaskSubset, info);
2013 } else {
2014 // Common case for userdebug/eng builds. If no death and
2015 // just dropboxing, we can do the ActivityManager call
2016 // asynchronously.
2017 dropboxViolationAsync(violationMaskSubset, info);
2018 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002019 }
2020
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08002021 if (penaltyDeath) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002022 System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
2023 Process.killProcess(Process.myPid());
2024 System.exit(10);
2025 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002026
2027 // If penaltyDeath, we can't guarantee this callback finishes before the process dies for
2028 // all executors. penaltyDeath supersedes penaltyCallback.
2029 if (sVmPolicy.mListener != null && sVmPolicy.mCallbackExecutor != null) {
2030 final OnVmViolationListener listener = sVmPolicy.mListener;
2031 try {
2032 sVmPolicy.mCallbackExecutor.execute(
2033 () -> {
2034 // Lift violated policy to prevent infinite recursion.
2035 VmPolicy oldPolicy = allowVmViolations();
2036 try {
2037 listener.onVmViolation(violation);
2038 } finally {
2039 setVmPolicy(oldPolicy);
2040 }
2041 });
2042 } catch (RejectedExecutionException e) {
2043 Log.e(TAG, "VmPolicy penaltyCallback failed", e);
2044 }
2045 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002046 }
2047
Kurt Nelson46974a22017-08-30 13:30:26 -07002048 /** Called from Parcel.writeNoException() */
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002049 /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002050 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002051 if (violations == null) {
2052 p.writeInt(0);
2053 } else {
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002054 // To avoid taking up too much transaction space, only include
2055 // details for the first 3 violations. Deep inside, CrashInfo
2056 // will truncate each stack trace to ~20kB.
2057 final int size = Math.min(violations.size(), 3);
2058 p.writeInt(size);
2059 for (int i = 0; i < size; i++) {
2060 violations.get(i).writeToParcel(p, 0);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002061 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002062 }
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002063 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002064 }
2065
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002066 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002067 * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, we here
2068 * read back all the encoded violations.
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002069 */
2070 /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002071 Throwable localCallSite = new Throwable();
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002072 final int policyMask = getThreadPolicyMask();
2073 final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002074
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002075 final int size = p.readInt();
2076 for (int i = 0; i < size; i++) {
2077 final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
Kurt Nelson0918c932017-09-07 10:56:56 -07002078 info.addLocalStack(localCallSite);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002079 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2080 if (policy instanceof AndroidBlockGuardPolicy) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002081 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002082 }
2083 }
2084 }
2085
2086 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002087 * Called from android_util_Binder.cpp's android_os_Parcel_enforceInterface when an incoming
2088 * Binder call requires changing the StrictMode policy mask. The role of this function is to ask
2089 * Binder for its current (native) thread-local policy value and synchronize it to libcore's
2090 * (Java) thread-local policy value.
Brad Fitzpatrick727de402010-07-07 16:06:39 -07002091 */
2092 private static void onBinderStrictModePolicyChange(int newPolicy) {
2093 setBlockGuardPolicy(newPolicy);
2094 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002095
2096 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002097 * A tracked, critical time span. (e.g. during an animation.)
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002098 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002099 * <p>The object itself is a linked list node, to avoid any allocations during rapid span
2100 * entries and exits.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002101 *
2102 * @hide
2103 */
2104 public static class Span {
2105 private String mName;
2106 private long mCreateMillis;
2107 private Span mNext;
Kurt Nelson46974a22017-08-30 13:30:26 -07002108 private Span mPrev; // not used when in freeList, only active
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002109 private final ThreadSpanState mContainerState;
2110
2111 Span(ThreadSpanState threadState) {
2112 mContainerState = threadState;
2113 }
2114
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002115 // Empty constructor for the NO_OP_SPAN
2116 protected Span() {
2117 mContainerState = null;
2118 }
2119
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002120 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002121 * To be called when the critical span is complete (i.e. the animation is done animating).
2122 * This can be called on any thread (even a different one from where the animation was
2123 * taking place), but that's only a defensive implementation measure. It really makes no
2124 * sense for you to call this on thread other than that where you created it.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002125 *
2126 * @hide
2127 */
2128 public void finish() {
2129 ThreadSpanState state = mContainerState;
2130 synchronized (state) {
2131 if (mName == null) {
2132 // Duplicate finish call. Ignore.
2133 return;
2134 }
2135
2136 // Remove ourselves from the active list.
2137 if (mPrev != null) {
2138 mPrev.mNext = mNext;
2139 }
2140 if (mNext != null) {
2141 mNext.mPrev = mPrev;
2142 }
2143 if (state.mActiveHead == this) {
2144 state.mActiveHead = mNext;
2145 }
2146
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002147 state.mActiveSize--;
2148
2149 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
2150
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002151 this.mCreateMillis = -1;
2152 this.mName = null;
2153 this.mPrev = null;
2154 this.mNext = null;
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002155
2156 // Add ourselves to the freeList, if it's not already
2157 // too big.
2158 if (state.mFreeListSize < 5) {
2159 this.mNext = state.mFreeListHead;
2160 state.mFreeListHead = this;
2161 state.mFreeListSize++;
2162 }
2163 }
2164 }
2165 }
2166
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002167 // The no-op span that's used in user builds.
Kurt Nelson46974a22017-08-30 13:30:26 -07002168 private static final Span NO_OP_SPAN =
2169 new Span() {
2170 public void finish() {
2171 // Do nothing.
2172 }
2173 };
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002174
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002175 /**
2176 * Linked lists of active spans and a freelist.
2177 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002178 * <p>Locking notes: there's one of these structures per thread and all members of this
2179 * structure (as well as the Span nodes under it) are guarded by the ThreadSpanState object
2180 * instance. While in theory there'd be no locking required because it's all local per-thread,
2181 * the finish() method above is defensive against people calling it on a different thread from
2182 * where they created the Span, hence the locking.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002183 */
2184 private static class ThreadSpanState {
Kurt Nelson46974a22017-08-30 13:30:26 -07002185 public Span mActiveHead; // doubly-linked list.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002186 public int mActiveSize;
Kurt Nelson46974a22017-08-30 13:30:26 -07002187 public Span mFreeListHead; // singly-linked list. only changes at head.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002188 public int mFreeListSize;
2189 }
2190
2191 private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
2192 new ThreadLocal<ThreadSpanState>() {
Kurt Nelson46974a22017-08-30 13:30:26 -07002193 @Override
2194 protected ThreadSpanState initialValue() {
2195 return new ThreadSpanState();
2196 }
2197 };
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002198
Kurt Nelson46974a22017-08-30 13:30:26 -07002199 private static Singleton<IWindowManager> sWindowManager =
2200 new Singleton<IWindowManager>() {
2201 protected IWindowManager create() {
2202 return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
2203 }
2204 };
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08002205
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002206 /**
2207 * Enter a named critical span (e.g. an animation)
2208 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002209 * <p>The name is an arbitary label (or tag) that will be applied to any strictmode violation
2210 * that happens while this span is active. You must call finish() on the span when done.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002211 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002212 * <p>This will never return null, but on devices without debugging enabled, this may return a
2213 * dummy object on which the finish() method is a no-op.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002214 *
2215 * <p>TODO: add CloseGuard to this, verifying callers call finish.
2216 *
2217 * @hide
2218 */
2219 public static Span enterCriticalSpan(String name) {
Jeff Sharkey5ab02432017-06-27 11:01:36 -06002220 if (Build.IS_USER) {
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002221 return NO_OP_SPAN;
2222 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002223 if (name == null || name.isEmpty()) {
2224 throw new IllegalArgumentException("name must be non-null and non-empty");
2225 }
2226 ThreadSpanState state = sThisThreadSpanState.get();
2227 Span span = null;
2228 synchronized (state) {
2229 if (state.mFreeListHead != null) {
2230 span = state.mFreeListHead;
2231 state.mFreeListHead = span.mNext;
2232 state.mFreeListSize--;
2233 } else {
2234 // Shouldn't have to do this often.
2235 span = new Span(state);
2236 }
2237 span.mName = name;
2238 span.mCreateMillis = SystemClock.uptimeMillis();
2239 span.mNext = state.mActiveHead;
2240 span.mPrev = null;
2241 state.mActiveHead = span;
2242 state.mActiveSize++;
2243 if (span.mNext != null) {
2244 span.mNext.mPrev = span;
2245 }
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002246 if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002247 }
2248 return span;
2249 }
2250
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002251 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002252 * For code to note that it's slow. This is a no-op unless the current thread's {@link
2253 * android.os.StrictMode.ThreadPolicy} has {@link
2254 * android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls} enabled.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002255 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002256 * @param name a short string for the exception stack trace that's built if when this fires.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002257 */
2258 public static void noteSlowCall(String name) {
2259 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2260 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2261 // StrictMode not enabled.
2262 return;
2263 }
2264 ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
2265 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002266
2267 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002268 * For code to note that a resource was obtained using a type other than its defined type. This
2269 * is a no-op unless the current thread's {@link android.os.StrictMode.ThreadPolicy} has {@link
2270 * android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()} enabled.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08002271 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002272 * @param tag an object for the exception stack trace that's built if when this fires.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08002273 * @hide
2274 */
2275 public static void noteResourceMismatch(Object tag) {
2276 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2277 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2278 // StrictMode not enabled.
2279 return;
2280 }
2281 ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag);
2282 }
2283
Kurt Nelson46974a22017-08-30 13:30:26 -07002284 /** @hide */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01002285 public static void noteUnbufferedIO() {
2286 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2287 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2288 // StrictMode not enabled.
2289 return;
2290 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002291 policy.onUnbufferedIO();
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01002292 }
2293
Kurt Nelson46974a22017-08-30 13:30:26 -07002294 /** @hide */
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002295 public static void noteDiskRead() {
2296 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002297 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2298 // StrictMode not enabled.
2299 return;
2300 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002301 policy.onReadFromDisk();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002302 }
2303
Kurt Nelson46974a22017-08-30 13:30:26 -07002304 /** @hide */
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002305 public static void noteDiskWrite() {
2306 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2307 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2308 // StrictMode not enabled.
2309 return;
2310 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002311 policy.onWriteToDisk();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002312 }
2313
Kurt Nelson1981f422017-10-25 13:49:26 -07002314 @GuardedBy("StrictMode.class")
2315 private static final HashMap<Class, Integer> sExpectedActivityInstanceCount = new HashMap<>();
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002316
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002317 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002318 * Returns an object that is used to track instances of activites. The activity should store a
2319 * reference to the tracker object in one of its fields.
2320 *
Jeff Brown7e442832011-06-10 18:00:16 -07002321 * @hide
2322 */
2323 public static Object trackActivity(Object instance) {
2324 return new InstanceTracker(instance);
2325 }
2326
Kurt Nelson46974a22017-08-30 13:30:26 -07002327 /** @hide */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002328 public static void incrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002329 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002330 return;
2331 }
Jeff Brown7e442832011-06-10 18:00:16 -07002332
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002333 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002334 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2335 return;
2336 }
2337
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002338 Integer expected = sExpectedActivityInstanceCount.get(klass);
2339 Integer newExpected = expected == null ? 1 : expected + 1;
2340 sExpectedActivityInstanceCount.put(klass, newExpected);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002341 }
2342 }
2343
Kurt Nelson46974a22017-08-30 13:30:26 -07002344 /** @hide */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002345 public static void decrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002346 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002347 return;
2348 }
Jeff Brown7e442832011-06-10 18:00:16 -07002349
2350 final int limit;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002351 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002352 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2353 return;
2354 }
2355
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002356 Integer expected = sExpectedActivityInstanceCount.get(klass);
Jeff Brown7e442832011-06-10 18:00:16 -07002357 int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002358 if (newExpected == 0) {
2359 sExpectedActivityInstanceCount.remove(klass);
2360 } else {
2361 sExpectedActivityInstanceCount.put(klass, newExpected);
2362 }
Jeff Brown7e442832011-06-10 18:00:16 -07002363
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002364 // Note: adding 1 here to give some breathing room during
2365 // orientation changes. (shouldn't be necessary, though?)
Jeff Brown7e442832011-06-10 18:00:16 -07002366 limit = newExpected + 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002367 }
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002368
Jeff Brown7e442832011-06-10 18:00:16 -07002369 // Quick check.
2370 int actual = InstanceTracker.getInstanceCount(klass);
2371 if (actual <= limit) {
2372 return;
2373 }
2374
2375 // Do a GC and explicit count to double-check.
2376 // This is the work that we are trying to avoid by tracking the object instances
2377 // explicity. Running an explicit GC can be expensive (80ms) and so can walking
2378 // the heap to count instance (30ms). This extra work can make the system feel
2379 // noticeably less responsive during orientation changes when activities are
2380 // being restarted. Granted, it is only a problem when StrictMode is enabled
2381 // but it is annoying.
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08002382
2383 System.gc();
2384 System.runFinalization();
2385 System.gc();
Jeff Brown7e442832011-06-10 18:00:16 -07002386
2387 long instances = VMDebug.countInstancesOfClass(klass, false);
2388 if (instances > limit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002389 onVmPolicyViolation(new InstanceCountViolation(klass, instances, limit));
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002390 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002391 }
2392
2393 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002394 * Parcelable that gets sent in Binder call headers back to callers to report violations that
2395 * happened during a cross-process call.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002396 *
2397 * @hide
2398 */
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07002399 @TestApi
2400 public static final class ViolationInfo implements Parcelable {
Kurt Nelson0918c932017-09-07 10:56:56 -07002401 /** Stack and violation details. */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002402 private final Violation mViolation;
Kurt Nelson0918c932017-09-07 10:56:56 -07002403
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002404 /** Path leading to a violation that occurred across binder. */
2405 private final Deque<StackTraceElement[]> mBinderStack = new ArrayDeque<>();
Kurt Nelson0918c932017-09-07 10:56:56 -07002406
2407 /** Memoized stack trace of full violation. */
2408 @Nullable private String mStackTrace;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002409
Kurt Nelson46974a22017-08-30 13:30:26 -07002410 /** The strict mode policy mask at the time of violation. */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002411 private final int mPolicy;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002412
Kurt Nelson46974a22017-08-30 13:30:26 -07002413 /** The wall time duration of the violation, when known. -1 when not known. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002414 public int durationMillis = -1;
2415
Kurt Nelson46974a22017-08-30 13:30:26 -07002416 /** The number of animations currently running. */
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002417 public int numAnimationsRunning = 0;
2418
Kurt Nelson46974a22017-08-30 13:30:26 -07002419 /** List of tags from active Span instances during this violation, or null for none. */
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002420 public String[] tags;
2421
2422 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002423 * Which violation number this was (1-based) since the last Looper loop, from the
2424 * perspective of the root caller (if it crossed any processes via Binder calls). The value
2425 * is 0 if the root caller wasn't on a Looper thread.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002426 */
2427 public int violationNumThisLoop;
2428
Kurt Nelson46974a22017-08-30 13:30:26 -07002429 /** The time (in terms of SystemClock.uptimeMillis()) that the violation occurred. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002430 public long violationUptimeMillis;
2431
2432 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002433 * The action of the Intent being broadcast to somebody's onReceive on this thread right
2434 * now, or null.
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002435 */
2436 public String broadcastIntentAction;
2437
Kurt Nelson46974a22017-08-30 13:30:26 -07002438 /** If this is a instance count violation, the number of instances in memory, else -1. */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002439 public long numInstances = -1;
2440
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002441 /** Create an instance of ViolationInfo initialized from an exception. */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002442 ViolationInfo(Violation tr, int policy) {
2443 this.mViolation = tr;
2444 this.mPolicy = policy;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002445 violationUptimeMillis = SystemClock.uptimeMillis();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002446 this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002447 Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2448 if (broadcastIntent != null) {
2449 broadcastIntentAction = broadcastIntent.getAction();
2450 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002451 ThreadSpanState state = sThisThreadSpanState.get();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002452 if (tr instanceof InstanceCountViolation) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002453 this.numInstances = ((InstanceCountViolation) tr).getNumberOfInstances();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002454 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002455 synchronized (state) {
2456 int spanActiveCount = state.mActiveSize;
2457 if (spanActiveCount > MAX_SPAN_TAGS) {
2458 spanActiveCount = MAX_SPAN_TAGS;
2459 }
2460 if (spanActiveCount != 0) {
2461 this.tags = new String[spanActiveCount];
2462 Span iter = state.mActiveHead;
2463 int index = 0;
2464 while (iter != null && index < spanActiveCount) {
2465 this.tags[index] = iter.mName;
2466 index++;
2467 iter = iter.mNext;
2468 }
2469 }
2470 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002471 }
2472
Kurt Nelson0918c932017-09-07 10:56:56 -07002473 /** Equivalent output to {@link ApplicationErrorReport.CrashInfo#stackTrace}. */
2474 public String getStackTrace() {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002475 if (mStackTrace == null) {
Kurt Nelson0918c932017-09-07 10:56:56 -07002476 StringWriter sw = new StringWriter();
2477 PrintWriter pw = new FastPrintWriter(sw, false, 256);
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002478 mViolation.printStackTrace(pw);
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002479 for (StackTraceElement[] traces : mBinderStack) {
Kurt Nelson0918c932017-09-07 10:56:56 -07002480 pw.append("# via Binder call with stack:\n");
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002481 for (StackTraceElement traceElement : traces) {
2482 pw.append("\tat ");
2483 pw.append(traceElement.toString());
2484 pw.append('\n');
2485 }
Kurt Nelson0918c932017-09-07 10:56:56 -07002486 }
2487 pw.flush();
2488 pw.close();
2489 mStackTrace = sw.toString();
2490 }
2491 return mStackTrace;
2492 }
2493
2494 /**
2495 * Optional message describing this violation.
2496 *
2497 * @hide
2498 */
2499 @TestApi
2500 public String getViolationDetails() {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002501 return mViolation.getMessage();
Kurt Nelson0918c932017-09-07 10:56:56 -07002502 }
2503
2504 /**
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002505 * Policy mask at time of violation.
Kurt Nelson0918c932017-09-07 10:56:56 -07002506 *
2507 * @hide
2508 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002509 @TestApi
2510 public int getPolicyMask() {
2511 return mPolicy;
2512 }
2513
2514 boolean penaltyEnabled(int p) {
2515 return (mPolicy & p) != 0;
Kurt Nelson0918c932017-09-07 10:56:56 -07002516 }
2517
2518 /**
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002519 * Add a {@link Throwable} from the current process that caused the underlying violation. We
2520 * only preserve the stack trace elements.
Kurt Nelson0918c932017-09-07 10:56:56 -07002521 *
2522 * @hide
2523 */
2524 void addLocalStack(Throwable t) {
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002525 mBinderStack.addFirst(t.getStackTrace());
Kurt Nelson0918c932017-09-07 10:56:56 -07002526 }
2527
2528 /**
2529 * Retrieve the type of StrictMode violation.
2530 *
2531 * @hide
2532 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002533 @TestApi
2534 public int getViolationBit() {
2535 if (mViolation instanceof DiskWriteViolation) {
2536 return DETECT_DISK_WRITE;
2537 } else if (mViolation instanceof DiskReadViolation) {
2538 return DETECT_DISK_READ;
2539 } else if (mViolation instanceof NetworkViolation) {
2540 return DETECT_NETWORK;
2541 } else if (mViolation instanceof CustomViolation) {
2542 return DETECT_CUSTOM;
2543 } else if (mViolation instanceof ResourceMismatchViolation) {
2544 return DETECT_RESOURCE_MISMATCH;
Kurt Nelson0e612802017-11-09 17:25:40 -08002545 } else if (mViolation instanceof UnbufferedIoViolation) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002546 return DETECT_UNBUFFERED_IO;
2547 } else if (mViolation instanceof SqliteObjectLeakedViolation) {
2548 return DETECT_VM_CURSOR_LEAKS;
2549 } else if (mViolation instanceof LeakedClosableViolation) {
2550 return DETECT_VM_CLOSABLE_LEAKS;
2551 } else if (mViolation instanceof InstanceCountViolation) {
2552 return DETECT_VM_INSTANCE_LEAKS;
2553 } else if (mViolation instanceof IntentReceiverLeakedViolation) {
2554 return DETECT_VM_REGISTRATION_LEAKS;
2555 } else if (mViolation instanceof ServiceConnectionLeakedViolation) {
2556 return DETECT_VM_REGISTRATION_LEAKS;
2557 } else if (mViolation instanceof FileUriExposedViolation) {
2558 return DETECT_VM_FILE_URI_EXPOSURE;
2559 } else if (mViolation instanceof CleartextNetworkViolation) {
2560 return DETECT_VM_CLEARTEXT_NETWORK;
2561 } else if (mViolation instanceof ContentUriWithoutPermissionViolation) {
2562 return DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION;
2563 } else if (mViolation instanceof UntaggedSocketViolation) {
2564 return DETECT_VM_UNTAGGED_SOCKET;
Kurt Nelson0918c932017-09-07 10:56:56 -07002565 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002566 throw new IllegalStateException("missing violation bit");
Kurt Nelson0918c932017-09-07 10:56:56 -07002567 }
2568
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002569 @Override
2570 public int hashCode() {
2571 int result = 17;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002572 if (mViolation != null) {
2573 result = 37 * result + mViolation.hashCode();
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002574 }
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002575 if (numAnimationsRunning != 0) {
2576 result *= 37;
2577 }
2578 if (broadcastIntentAction != null) {
2579 result = 37 * result + broadcastIntentAction.hashCode();
2580 }
2581 if (tags != null) {
2582 for (String tag : tags) {
2583 result = 37 * result + tag.hashCode();
2584 }
2585 }
2586 return result;
2587 }
2588
Kurt Nelson46974a22017-08-30 13:30:26 -07002589 /** Create an instance of ViolationInfo initialized from a Parcel. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002590 public ViolationInfo(Parcel in) {
2591 this(in, false);
2592 }
2593
2594 /**
2595 * Create an instance of ViolationInfo initialized from a Parcel.
2596 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002597 * @param unsetGatheringBit if true, the caller is the root caller and the gathering penalty
2598 * should be removed.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002599 */
2600 public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002601 mViolation = (Violation) in.readSerializable();
Kurt Nelson0918c932017-09-07 10:56:56 -07002602 int binderStackSize = in.readInt();
2603 for (int i = 0; i < binderStackSize; i++) {
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002604 StackTraceElement[] traceElements = new StackTraceElement[in.readInt()];
2605 for (int j = 0; j < traceElements.length; j++) {
2606 StackTraceElement element =
2607 new StackTraceElement(
2608 in.readString(),
2609 in.readString(),
2610 in.readString(),
2611 in.readInt());
2612 traceElements[j] = element;
2613 }
2614 mBinderStack.add(traceElements);
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002615 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002616 int rawPolicy = in.readInt();
2617 if (unsetGatheringBit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002618 mPolicy = rawPolicy & ~PENALTY_GATHER;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002619 } else {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002620 mPolicy = rawPolicy;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002621 }
2622 durationMillis = in.readInt();
2623 violationNumThisLoop = in.readInt();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002624 numAnimationsRunning = in.readInt();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002625 violationUptimeMillis = in.readLong();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002626 numInstances = in.readLong();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002627 broadcastIntentAction = in.readString();
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002628 tags = in.readStringArray();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002629 }
2630
Kurt Nelson46974a22017-08-30 13:30:26 -07002631 /** Save a ViolationInfo instance to a parcel. */
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07002632 @Override
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002633 public void writeToParcel(Parcel dest, int flags) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002634 dest.writeSerializable(mViolation);
Kurt Nelson0918c932017-09-07 10:56:56 -07002635 dest.writeInt(mBinderStack.size());
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002636 for (StackTraceElement[] traceElements : mBinderStack) {
2637 dest.writeInt(traceElements.length);
2638 for (StackTraceElement element : traceElements) {
2639 dest.writeString(element.getClassName());
2640 dest.writeString(element.getMethodName());
2641 dest.writeString(element.getFileName());
2642 dest.writeInt(element.getLineNumber());
2643 }
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002644 }
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002645 int start = dest.dataPosition();
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002646 dest.writeInt(mPolicy);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002647 dest.writeInt(durationMillis);
2648 dest.writeInt(violationNumThisLoop);
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002649 dest.writeInt(numAnimationsRunning);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002650 dest.writeLong(violationUptimeMillis);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002651 dest.writeLong(numInstances);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002652 dest.writeString(broadcastIntentAction);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002653 dest.writeStringArray(tags);
Kurt Nelson46974a22017-08-30 13:30:26 -07002654 int total = dest.dataPosition() - start;
2655 if (Binder.CHECK_PARCEL_SIZE && total > 10 * 1024) {
2656 Slog.d(
2657 TAG,
2658 "VIO: policy="
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002659 + mPolicy
Kurt Nelson46974a22017-08-30 13:30:26 -07002660 + " dur="
2661 + durationMillis
2662 + " numLoop="
2663 + violationNumThisLoop
2664 + " anim="
2665 + numAnimationsRunning
2666 + " uptime="
2667 + violationUptimeMillis
2668 + " numInst="
2669 + numInstances);
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002670 Slog.d(TAG, "VIO: action=" + broadcastIntentAction);
2671 Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags));
Kurt Nelson46974a22017-08-30 13:30:26 -07002672 Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition() - start));
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002673 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002674 }
2675
Kurt Nelson46974a22017-08-30 13:30:26 -07002676 /** Dump a ViolationInfo instance to a Printer. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002677 public void dump(Printer pw, String prefix) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002678 pw.println(prefix + "stackTrace: " + getStackTrace());
2679 pw.println(prefix + "policy: " + mPolicy);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002680 if (durationMillis != -1) {
2681 pw.println(prefix + "durationMillis: " + durationMillis);
2682 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002683 if (numInstances != -1) {
2684 pw.println(prefix + "numInstances: " + numInstances);
2685 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002686 if (violationNumThisLoop != 0) {
2687 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2688 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002689 if (numAnimationsRunning != 0) {
2690 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2691 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002692 pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002693 if (broadcastIntentAction != null) {
2694 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2695 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002696 if (tags != null) {
2697 int index = 0;
2698 for (String tag : tags) {
2699 pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2700 }
2701 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002702 }
2703
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07002704 @Override
2705 public int describeContents() {
2706 return 0;
2707 }
2708
2709 public static final Parcelable.Creator<ViolationInfo> CREATOR =
2710 new Parcelable.Creator<ViolationInfo>() {
2711 @Override
2712 public ViolationInfo createFromParcel(Parcel in) {
2713 return new ViolationInfo(in);
2714 }
2715
2716 @Override
2717 public ViolationInfo[] newArray(int size) {
2718 return new ViolationInfo[size];
2719 }
2720 };
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002721 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002722
Jeff Brown7e442832011-06-10 18:00:16 -07002723 private static final class InstanceTracker {
2724 private static final HashMap<Class<?>, Integer> sInstanceCounts =
2725 new HashMap<Class<?>, Integer>();
2726
2727 private final Class<?> mKlass;
2728
2729 public InstanceTracker(Object instance) {
2730 mKlass = instance.getClass();
2731
2732 synchronized (sInstanceCounts) {
2733 final Integer value = sInstanceCounts.get(mKlass);
2734 final int newValue = value != null ? value + 1 : 1;
2735 sInstanceCounts.put(mKlass, newValue);
2736 }
2737 }
2738
2739 @Override
2740 protected void finalize() throws Throwable {
2741 try {
2742 synchronized (sInstanceCounts) {
2743 final Integer value = sInstanceCounts.get(mKlass);
2744 if (value != null) {
2745 final int newValue = value - 1;
2746 if (newValue > 0) {
2747 sInstanceCounts.put(mKlass, newValue);
2748 } else {
2749 sInstanceCounts.remove(mKlass);
2750 }
2751 }
2752 }
2753 } finally {
2754 super.finalize();
2755 }
2756 }
2757
2758 public static int getInstanceCount(Class<?> klass) {
2759 synchronized (sInstanceCounts) {
2760 final Integer value = sInstanceCounts.get(klass);
2761 return value != null ? value : 0;
2762 }
2763 }
2764 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07002765}