blob: 59380fd3d06b065c4422677afa1acc8d84f4d724 [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;
Narayan Kamathad1b2a92018-03-28 11:29:40 +010042import android.os.strictmode.NonSdkApiUsedViolation;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -070043import android.os.strictmode.ResourceMismatchViolation;
44import android.os.strictmode.ServiceConnectionLeakedViolation;
45import android.os.strictmode.SqliteObjectLeakedViolation;
Kurt Nelson0e612802017-11-09 17:25:40 -080046import android.os.strictmode.UnbufferedIoViolation;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -070047import android.os.strictmode.UntaggedSocketViolation;
48import android.os.strictmode.Violation;
49import android.os.strictmode.WebViewMethodCalledOnWrongThreadViolation;
Dianne Hackborn390517b2013-05-30 15:03:32 -070050import android.util.ArrayMap;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070051import android.util.Log;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070052import android.util.Printer;
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -080053import android.util.Singleton;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070054import android.util.Slog;
Brad Fitzpatrick68044332010-11-22 18:19:48 -080055import android.view.IWindowManager;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070056
Kurt Nelson1981f422017-10-25 13:49:26 -070057import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -070058import com.android.internal.os.BackgroundThread;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070059import com.android.internal.os.RuntimeInit;
Dianne Hackborn8c841092013-06-24 13:46:13 -070060import com.android.internal.util.FastPrintWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080061import com.android.internal.util.HexDump;
62
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070063import dalvik.system.BlockGuard;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070064import dalvik.system.CloseGuard;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -080065import dalvik.system.VMDebug;
Jeff Sharkey0b558702017-01-26 16:48:01 -070066import dalvik.system.VMRuntime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070067
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070068import java.io.PrintWriter;
69import java.io.StringWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080070import java.net.InetAddress;
71import java.net.UnknownHostException;
Kurt Nelson0918c932017-09-07 10:56:56 -070072import java.util.ArrayDeque;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070073import java.util.ArrayList;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070074import java.util.Arrays;
Kurt Nelson0918c932017-09-07 10:56:56 -070075import java.util.Deque;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070076import java.util.HashMap;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -070077import java.util.concurrent.Executor;
78import java.util.concurrent.RejectedExecutionException;
Brad Fitzpatrickbee24872010-11-20 12:09:10 -080079import java.util.concurrent.atomic.AtomicInteger;
Narayan Kamathad1b2a92018-03-28 11:29:40 +010080import java.util.function.Consumer;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070081
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070082/**
Kurt Nelson46974a22017-08-30 13:30:26 -070083 * StrictMode is a developer tool which detects things you might be doing by accident and brings
84 * them to your attention so you can fix them.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070085 *
Kurt Nelson46974a22017-08-30 13:30:26 -070086 * <p>StrictMode is most commonly used to catch accidental disk or network access on the
87 * application's main thread, where UI operations are received and animations take place. Keeping
88 * disk and network operations off the main thread makes for much smoother, more responsive
89 * applications. By keeping your application's main thread responsive, you also prevent <a
90 * href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a> from being shown to
91 * users.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070092 *
Kurt Nelson46974a22017-08-30 13:30:26 -070093 * <p class="note">Note that even though an Android device's disk is often on flash memory, many
94 * devices run a filesystem on top of that memory with very limited concurrency. It's often the case
95 * that almost all disk accesses are fast, but may in individual cases be dramatically slower when
96 * certain I/O is happening in the background from other processes. If possible, it's best to assume
97 * that such things are not fast.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070098 *
Kurt Nelson46974a22017-08-30 13:30:26 -070099 * <p>Example code to enable from early in your {@link android.app.Application}, {@link
100 * android.app.Activity}, or other application component's {@link android.app.Application#onCreate}
101 * method:
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700102 *
103 * <pre>
104 * public void onCreate() {
105 * if (DEVELOPER_MODE) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700106 * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
107 * .detectDiskReads()
108 * .detectDiskWrites()
109 * .detectNetwork() // or .detectAll() for all detectable problems
110 * .penaltyLog()
111 * .build());
112 * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -0700113 * .detectLeakedSqlLiteObjects()
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700114 * .detectLeakedClosableObjects()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700115 * .penaltyLog()
116 * .penaltyDeath()
117 * .build());
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700118 * }
119 * super.onCreate();
120 * }
121 * </pre>
122 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700123 * <p>You can decide what should happen when a violation is detected. For example, using {@link
124 * ThreadPolicy.Builder#penaltyLog} you can watch the output of <code>adb logcat</code> while you
125 * use your application to see the violations as they happen.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700126 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700127 * <p>If you find violations that you feel are problematic, there are a variety of tools to help
128 * solve them: threads, {@link android.os.Handler}, {@link android.os.AsyncTask}, {@link
129 * android.app.IntentService}, etc. But don't feel compelled to fix everything that StrictMode
130 * finds. In particular, many cases of disk access are often necessary during the normal activity
131 * lifecycle. Use StrictMode to find things you did by accident. Network requests on the UI thread
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700132 * are almost always a problem, though.
133 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700134 * <p class="note">StrictMode is not a security mechanism and is not guaranteed to find all disk or
135 * network accesses. While it does propagate its state across process boundaries when doing {@link
136 * android.os.Binder} calls, it's still ultimately a best effort mechanism. Notably, disk or network
137 * access from JNI calls won't necessarily trigger it. Future versions of Android may catch more (or
138 * fewer) operations, so you should never leave StrictMode enabled in applications distributed on
139 * Google Play.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700140 */
141public final class StrictMode {
142 private static final String TAG = "StrictMode";
Brad Fitzpatrick82829ef2010-11-18 18:25:08 -0800143 private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700144
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800145 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700146 * Boolean system property to disable strict mode checks outright. Set this to 'true' to force
147 * disable; 'false' has no effect on other enable/disable policy.
148 *
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700149 * @hide
150 */
151 public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
152
153 /**
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800154 * The boolean system property to control screen flashes on violations.
155 *
156 * @hide
157 */
158 public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
159
Jeff Sharkey605eb792014-11-04 13:34:06 -0800160 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700161 * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK} in {@link
162 * VmPolicy.Builder#detectAll()}. Apps can still always opt-into detection using {@link
163 * VmPolicy.Builder#detectCleartextNetwork()}.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800164 */
Jeff Sharkey2e571642015-01-22 11:51:43 -0700165 private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.clear";
Jeff Sharkey605eb792014-11-04 13:34:06 -0800166
Jeff Sharkey89182982017-11-01 19:02:56 -0600167 /**
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700168 * Quick feature-flag that can be used to disable the defaults provided by {@link
169 * #initThreadDefaults(ApplicationInfo)} and {@link #initVmDefaults(ApplicationInfo)}.
Jeff Sharkey89182982017-11-01 19:02:56 -0600170 */
Jeff Sharkey617e1132017-11-03 17:28:45 -0600171 private static final boolean DISABLE = false;
Jeff Sharkey89182982017-11-01 19:02:56 -0600172
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700173 // Only apply VM penalties for the same violation at this interval.
174 private static final long MIN_VM_INTERVAL_MS = 1000;
175
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700176 // Only log a duplicate stack trace to the logs every second.
177 private static final long MIN_LOG_INTERVAL_MS = 1000;
178
179 // Only show an annoying dialog at most every 30 seconds
180 private static final long MIN_DIALOG_INTERVAL_MS = 30000;
181
Brad Fitzpatricke7520d82010-11-10 18:08:36 -0800182 // How many Span tags (e.g. animations) to report.
183 private static final int MAX_SPAN_TAGS = 20;
184
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -0700185 // How many offending stacks to keep track of (and time) per loop
186 // of the Looper.
187 private static final int MAX_OFFENSES_PER_LOOP = 10;
188
Jeff Sharkey605eb792014-11-04 13:34:06 -0800189 // Byte 1: Thread-policy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700190
Kurt Nelson46974a22017-08-30 13:30:26 -0700191 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700192 @TestApi public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700193
Kurt Nelson46974a22017-08-30 13:30:26 -0700194 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700195 @TestApi public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700196
Kurt Nelson46974a22017-08-30 13:30:26 -0700197 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700198 @TestApi public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700199
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800200 /**
201 * For StrictMode.noteSlowCall()
202 *
203 * @hide
204 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700205 @TestApi public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800206
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800207 /**
208 * For StrictMode.noteResourceMismatch()
209 *
210 * @hide
211 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700212 @TestApi public static final int DETECT_RESOURCE_MISMATCH = 0x10; // for ThreadPolicy
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800213
Kurt Nelson46974a22017-08-30 13:30:26 -0700214 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700215 @TestApi public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100216
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800217 private static final int ALL_THREAD_DETECT_BITS =
Kurt Nelson46974a22017-08-30 13:30:26 -0700218 DETECT_DISK_WRITE
219 | DETECT_DISK_READ
220 | DETECT_NETWORK
221 | DETECT_CUSTOM
222 | DETECT_RESOURCE_MISMATCH
223 | DETECT_UNBUFFERED_IO;
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800224
Jeff Sharkey605eb792014-11-04 13:34:06 -0800225 // Byte 2: Process-policy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700226
227 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700228 * Note, a "VM_" bit, not thread.
Kurt Nelson46974a22017-08-30 13:30:26 -0700229 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700230 * @hide
231 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700232 @TestApi public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8; // for VmPolicy
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700233
234 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700235 * Note, a "VM_" bit, not thread.
Kurt Nelson46974a22017-08-30 13:30:26 -0700236 *
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700237 * @hide
238 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700239 @TestApi public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8; // for VmPolicy
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800240
241 /**
242 * Note, a "VM_" bit, not thread.
Kurt Nelson46974a22017-08-30 13:30:26 -0700243 *
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800244 * @hide
245 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700246 @TestApi public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8; // for VmPolicy
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700247
Kurt Nelson46974a22017-08-30 13:30:26 -0700248 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700249 @TestApi public static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8; // for VmPolicy
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800250
Kurt Nelson46974a22017-08-30 13:30:26 -0700251 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700252 @TestApi public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8; // for VmPolicy
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800253
Kurt Nelson46974a22017-08-30 13:30:26 -0700254 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700255 @TestApi public static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8; // for VmPolicy
Jeff Sharkey605eb792014-11-04 13:34:06 -0800256
Kurt Nelson46974a22017-08-30 13:30:26 -0700257 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700258 @TestApi public static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8; // for VmPolicy
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700259
Kurt Nelson46974a22017-08-30 13:30:26 -0700260 /** @hide */
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -0700261 @TestApi
262 public static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -0700263
Kurt Nelson46974a22017-08-30 13:30:26 -0700264 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700265 @TestApi public static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy
Jeff Sharkey619a5112017-01-19 11:55:54 -0700266
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100267 /** @hide */
268 @TestApi public static final int DETECT_VM_NON_SDK_API_USAGE = 0x40 << 24; // for VmPolicy
269
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800270 private static final int ALL_VM_DETECT_BITS =
Kurt Nelson46974a22017-08-30 13:30:26 -0700271 DETECT_VM_CURSOR_LEAKS
272 | DETECT_VM_CLOSABLE_LEAKS
273 | DETECT_VM_ACTIVITY_LEAKS
274 | DETECT_VM_INSTANCE_LEAKS
275 | DETECT_VM_REGISTRATION_LEAKS
276 | DETECT_VM_FILE_URI_EXPOSURE
277 | DETECT_VM_CLEARTEXT_NETWORK
278 | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100279 | DETECT_VM_UNTAGGED_SOCKET
280 | DETECT_VM_NON_SDK_API_USAGE;
281
Jeff Sharkey605eb792014-11-04 13:34:06 -0800282
283 // Byte 3: Penalty
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800284
Jeff Sharkey344744b2016-01-28 19:03:30 -0700285 /** {@hide} */
Kurt Nelson46974a22017-08-30 13:30:26 -0700286 public static final int PENALTY_LOG = 0x01 << 16; // normal android.util.Log
Jeff Sharkey344744b2016-01-28 19:03:30 -0700287 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800288 public static final int PENALTY_DIALOG = 0x02 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700289 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800290 public static final int PENALTY_DEATH = 0x04 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700291 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800292 public static final int PENALTY_FLASH = 0x10 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700293 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800294 public static final int PENALTY_DROPBOX = 0x20 << 16;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700295
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700296 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700297 * Non-public penalty mode which overrides all the other penalty bits and signals that we're in
298 * a Binder call and we should ignore the other penalty bits and instead serialize back all our
299 * offending stack traces to the caller to ultimately handle in the originating process.
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700300 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700301 * <p>This must be kept in sync with the constant in libs/binder/Parcel.cpp
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700302 *
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700303 * @hide
304 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800305 public static final int PENALTY_GATHER = 0x40 << 16;
306
Jeff Sharkey344744b2016-01-28 19:03:30 -0700307 // Byte 4: Special cases
308
309 /**
310 * Death when network traffic is detected on main thread.
311 *
312 * @hide
313 */
314 public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
315
Jeff Sharkey605eb792014-11-04 13:34:06 -0800316 /**
317 * Death when cleartext network traffic is detected.
318 *
319 * @hide
320 */
Jeff Sharkey344744b2016-01-28 19:03:30 -0700321 public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
322
323 /**
324 * Death when file exposure is detected.
325 *
326 * @hide
327 */
328 public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700329
Jeff Sharkey619a5112017-01-19 11:55:54 -0700330 // CAUTION: we started stealing the top bits of Byte 4 for VM above
331
Kurt Nelson46974a22017-08-30 13:30:26 -0700332 /** Mask of all the penalty bits valid for thread policies. */
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800333 private static final int THREAD_PENALTY_MASK =
Kurt Nelson46974a22017-08-30 13:30:26 -0700334 PENALTY_LOG
335 | PENALTY_DIALOG
336 | PENALTY_DEATH
337 | PENALTY_DROPBOX
338 | PENALTY_GATHER
339 | PENALTY_DEATH_ON_NETWORK
340 | PENALTY_FLASH;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700341
Kurt Nelson46974a22017-08-30 13:30:26 -0700342 /** Mask of all the penalty bits valid for VM policies. */
343 private static final int VM_PENALTY_MASK =
344 PENALTY_LOG
345 | PENALTY_DEATH
346 | PENALTY_DROPBOX
347 | PENALTY_DEATH_ON_CLEARTEXT_NETWORK
348 | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800349
Jeff Sharkey605eb792014-11-04 13:34:06 -0800350 /** {@hide} */
351 public static final int NETWORK_POLICY_ACCEPT = 0;
352 /** {@hide} */
353 public static final int NETWORK_POLICY_LOG = 1;
354 /** {@hide} */
355 public static final int NETWORK_POLICY_REJECT = 2;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800356
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800357 // TODO: wrap in some ImmutableHashMap thing.
358 // Note: must be before static initialization of sVmPolicy.
Kurt Nelson46974a22017-08-30 13:30:26 -0700359 private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP =
360 new HashMap<Class, Integer>();
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800361
Kurt Nelson2c883f32017-09-01 10:52:45 -0700362 /** The current VmPolicy in effect. */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800363 private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700364
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600365 /** {@hide} */
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -0600366 @TestApi
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700367 public interface ViolationLogger {
368
369 /** Called when penaltyLog is enabled and a violation needs logging. */
370 void log(ViolationInfo info);
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600371 }
372
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700373 private static final ViolationLogger LOGCAT_LOGGER =
374 info -> {
375 String msg;
376 if (info.durationMillis != -1) {
377 msg = "StrictMode policy violation; ~duration=" + info.durationMillis + " ms:";
378 } else {
379 msg = "StrictMode policy violation:";
380 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700381 Log.d(TAG, msg + " " + info.getStackTrace());
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700382 };
383
384 private static volatile ViolationLogger sLogger = LOGCAT_LOGGER;
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600385
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700386 private static final ThreadLocal<OnThreadViolationListener> sThreadViolationListener =
387 new ThreadLocal<>();
388 private static final ThreadLocal<Executor> sThreadViolationExecutor = new ThreadLocal<>();
389
390 /**
391 * When #{@link ThreadPolicy.Builder#penaltyListener} is enabled, the listener is called on the
392 * provided executor when a Thread violation occurs.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700393 */
394 public interface OnThreadViolationListener {
395 /** Called on a thread policy violation. */
396 void onThreadViolation(Violation v);
397 }
398
399 /**
400 * When #{@link VmPolicy.Builder#penaltyListener} is enabled, the listener is called on the
401 * provided executor when a VM violation occurs.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700402 */
403 public interface OnVmViolationListener {
404 /** Called on a VM policy violation. */
405 void onVmViolation(Violation v);
406 }
407
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600408 /** {@hide} */
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -0600409 @TestApi
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700410 public static void setViolationLogger(ViolationLogger listener) {
411 if (listener == null) {
412 listener = LOGCAT_LOGGER;
413 }
414 sLogger = listener;
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600415 }
416
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800417 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700418 * The number of threads trying to do an async dropbox write. Just to limit ourselves out of
419 * paranoia.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800420 */
421 private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
422
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100423 /**
424 * Callback supplied to dalvik / libcore to get informed of usages of java API that are not
425 * a part of the public SDK.
426 */
427 private static final Consumer<String> sNonSdkApiUsageConsumer =
428 message -> onVmPolicyViolation(new NonSdkApiUsedViolation(message));
429
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700430 private StrictMode() {}
431
432 /**
433 * {@link StrictMode} policy applied to a certain thread.
434 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700435 * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy can be retrieved
436 * with {@link #getThreadPolicy}.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700437 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700438 * <p>Note that multiple penalties may be provided and they're run in order from least to most
439 * severe (logging before process death, for example). There's currently no mechanism to choose
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700440 * different penalties for different detected actions.
441 */
442 public static final class ThreadPolicy {
Kurt Nelson46974a22017-08-30 13:30:26 -0700443 /** The default, lax policy which doesn't catch anything. */
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700444 public static final ThreadPolicy LAX = new ThreadPolicy(0, null, null);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700445
446 final int mask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700447 final OnThreadViolationListener mListener;
448 final Executor mCallbackExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700449
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700450 private ThreadPolicy(int mask, OnThreadViolationListener listener, Executor executor) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700451 this.mask = mask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700452 mListener = listener;
453 mCallbackExecutor = executor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700454 }
455
456 @Override
457 public String toString() {
458 return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
459 }
460
461 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700462 * Creates {@link ThreadPolicy} instances. Methods whose names start with {@code detect}
463 * specify what problems we should look for. Methods whose names start with {@code penalty}
464 * specify what we should do when we detect a problem.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700465 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700466 * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently
467 * order is insignificant: all penalties apply to all detected problems.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700468 *
469 * <p>For example, detect everything and log anything that's found:
Kurt Nelson46974a22017-08-30 13:30:26 -0700470 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700471 * <pre>
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800472 * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700473 * .detectAll()
474 * .penaltyLog()
475 * .build();
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800476 * StrictMode.setThreadPolicy(policy);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700477 * </pre>
478 */
479 public static final class Builder {
480 private int mMask = 0;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700481 private OnThreadViolationListener mListener;
482 private Executor mExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700483
484 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700485 * Create a Builder that detects nothing and has no violations. (but note that {@link
486 * #build} will default to enabling {@link #penaltyLog} if no other penalties are
487 * specified)
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700488 */
489 public Builder() {
490 mMask = 0;
491 }
492
Kurt Nelson46974a22017-08-30 13:30:26 -0700493 /** Initialize a Builder from an existing ThreadPolicy. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700494 public Builder(ThreadPolicy policy) {
495 mMask = policy.mask;
Kurt Nelson7a8804a2018-02-27 16:45:27 -0800496 mListener = policy.mListener;
497 mExecutor = policy.mCallbackExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700498 }
499
500 /**
501 * Detect everything that's potentially suspect.
502 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700503 * <p>As of the Gingerbread release this includes network and disk operations but will
504 * likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700505 */
506 public Builder detectAll() {
Jeff Sharkey0b558702017-01-26 16:48:01 -0700507 detectDiskReads();
508 detectDiskWrites();
509 detectNetwork();
510
511 final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
512 if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
513 detectCustomSlowCalls();
514 }
515 if (targetSdk >= Build.VERSION_CODES.M) {
516 detectResourceMismatches();
517 }
518 if (targetSdk >= Build.VERSION_CODES.O) {
519 detectUnbufferedIo();
520 }
521 return this;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700522 }
523
Kurt Nelson46974a22017-08-30 13:30:26 -0700524 /** Disable the detection of everything. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700525 public Builder permitAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800526 return disable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700527 }
528
Kurt Nelson46974a22017-08-30 13:30:26 -0700529 /** Enable detection of network operations. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700530 public Builder detectNetwork() {
531 return enable(DETECT_NETWORK);
532 }
533
Kurt Nelson46974a22017-08-30 13:30:26 -0700534 /** Disable detection of network operations. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700535 public Builder permitNetwork() {
536 return disable(DETECT_NETWORK);
537 }
538
Kurt Nelson46974a22017-08-30 13:30:26 -0700539 /** Enable detection of disk reads. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700540 public Builder detectDiskReads() {
541 return enable(DETECT_DISK_READ);
542 }
543
Kurt Nelson46974a22017-08-30 13:30:26 -0700544 /** Disable detection of disk reads. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700545 public Builder permitDiskReads() {
546 return disable(DETECT_DISK_READ);
547 }
548
Kurt Nelson46974a22017-08-30 13:30:26 -0700549 /** Enable detection of slow calls. */
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800550 public Builder detectCustomSlowCalls() {
551 return enable(DETECT_CUSTOM);
552 }
553
Kurt Nelson46974a22017-08-30 13:30:26 -0700554 /** Disable detection of slow calls. */
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800555 public Builder permitCustomSlowCalls() {
Qi Wang097fbf22012-07-13 09:26:03 +0800556 return disable(DETECT_CUSTOM);
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800557 }
558
Kurt Nelson46974a22017-08-30 13:30:26 -0700559 /** Disable detection of mismatches between defined resource types and getter calls. */
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800560 public Builder permitResourceMismatches() {
561 return disable(DETECT_RESOURCE_MISMATCH);
562 }
563
Kurt Nelson46974a22017-08-30 13:30:26 -0700564 /** Detect unbuffered input/output operations. */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100565 public Builder detectUnbufferedIo() {
566 return enable(DETECT_UNBUFFERED_IO);
567 }
568
Kurt Nelson46974a22017-08-30 13:30:26 -0700569 /** Disable detection of unbuffered input/output operations. */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100570 public Builder permitUnbufferedIo() {
571 return disable(DETECT_UNBUFFERED_IO);
572 }
573
574 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700575 * Enables detection of mismatches between defined resource types and getter calls.
576 *
577 * <p>This helps detect accidental type mismatches and potentially expensive type
578 * conversions when obtaining typed resources.
579 *
580 * <p>For example, a strict mode violation would be thrown when calling {@link
581 * android.content.res.TypedArray#getInt(int, int)} on an index that contains a
582 * String-type resource. If the string value can be parsed as an integer, this method
583 * call will return a value without crashing; however, the developer should format the
584 * resource as an integer to avoid unnecessary type conversion.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800585 */
586 public Builder detectResourceMismatches() {
587 return enable(DETECT_RESOURCE_MISMATCH);
588 }
589
Kurt Nelson46974a22017-08-30 13:30:26 -0700590 /** Enable detection of disk writes. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700591 public Builder detectDiskWrites() {
592 return enable(DETECT_DISK_WRITE);
593 }
594
Kurt Nelson46974a22017-08-30 13:30:26 -0700595 /** Disable detection of disk writes. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700596 public Builder permitDiskWrites() {
597 return disable(DETECT_DISK_WRITE);
598 }
599
600 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700601 * Show an annoying dialog to the developer on detected violations, rate-limited to be
602 * only a little annoying.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700603 */
604 public Builder penaltyDialog() {
605 return enable(PENALTY_DIALOG);
606 }
607
608 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700609 * Crash the whole process on violation. This penalty runs at the end of all enabled
610 * penalties so you'll still get see logging or other violations before the process
611 * dies.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700612 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700613 * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies to disk reads, disk writes,
614 * and network usage if their corresponding detect flags are set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700615 */
616 public Builder penaltyDeath() {
617 return enable(PENALTY_DEATH);
618 }
619
620 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700621 * Crash the whole process on any network usage. Unlike {@link #penaltyDeath}, this
622 * penalty runs <em>before</em> anything else. You must still have called {@link
623 * #detectNetwork} to enable this.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700624 *
625 * <p>In the Honeycomb or later SDKs, this is on by default.
626 */
627 public Builder penaltyDeathOnNetwork() {
628 return enable(PENALTY_DEATH_ON_NETWORK);
629 }
630
Kurt Nelson46974a22017-08-30 13:30:26 -0700631 /** Flash the screen during a violation. */
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800632 public Builder penaltyFlashScreen() {
633 return enable(PENALTY_FLASH);
634 }
635
Kurt Nelson46974a22017-08-30 13:30:26 -0700636 /** Log detected violations to the system log. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700637 public Builder penaltyLog() {
638 return enable(PENALTY_LOG);
639 }
640
641 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700642 * Enable detected violations log a stacktrace and timing data to the {@link
643 * android.os.DropBoxManager DropBox} on policy violation. Intended mostly for platform
644 * integrators doing beta user field data collection.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700645 */
646 public Builder penaltyDropBox() {
647 return enable(PENALTY_DROPBOX);
648 }
649
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700650 /**
651 * Call #{@link OnThreadViolationListener#onThreadViolation(Violation)} on specified
652 * executor every violation.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700653 */
654 public Builder penaltyListener(
Kurt Nelson72534b72018-02-22 11:21:15 -0800655 @NonNull Executor executor, @NonNull OnThreadViolationListener listener) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700656 if (executor == null) {
657 throw new NullPointerException("executor must not be null");
658 }
659 mListener = listener;
660 mExecutor = executor;
661 return this;
662 }
663
Kurt Nelson72534b72018-02-22 11:21:15 -0800664 /** @removed */
665 public Builder penaltyListener(
666 @NonNull OnThreadViolationListener listener, @NonNull Executor executor) {
667 return penaltyListener(executor, listener);
668 }
669
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700670 private Builder enable(int bit) {
671 mMask |= bit;
672 return this;
673 }
674
675 private Builder disable(int bit) {
676 mMask &= ~bit;
677 return this;
678 }
679
680 /**
681 * Construct the ThreadPolicy instance.
682 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700683 * <p>Note: if no penalties are enabled before calling <code>build</code>, {@link
684 * #penaltyLog} is implicitly set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700685 */
686 public ThreadPolicy build() {
687 // If there are detection bits set but no violation bits
688 // set, enable simple logging.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700689 if (mListener == null
690 && mMask != 0
Kurt Nelson46974a22017-08-30 13:30:26 -0700691 && (mMask
692 & (PENALTY_DEATH
693 | PENALTY_LOG
694 | PENALTY_DROPBOX
695 | PENALTY_DIALOG))
696 == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700697 penaltyLog();
698 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700699 return new ThreadPolicy(mMask, mListener, mExecutor);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700700 }
701 }
702 }
703
704 /**
705 * {@link StrictMode} policy applied to all threads in the virtual machine's process.
706 *
707 * <p>The policy is enabled by {@link #setVmPolicy}.
708 */
709 public static final class VmPolicy {
Kurt Nelson46974a22017-08-30 13:30:26 -0700710 /** The default, lax policy which doesn't catch anything. */
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700711 public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP, null, null);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700712
713 final int mask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700714 final OnVmViolationListener mListener;
715 final Executor mCallbackExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700716
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800717 // Map from class to max number of allowed instances in memory.
718 final HashMap<Class, Integer> classInstanceLimit;
719
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700720 private VmPolicy(
721 int mask,
722 HashMap<Class, Integer> classInstanceLimit,
723 OnVmViolationListener listener,
724 Executor executor) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800725 if (classInstanceLimit == null) {
726 throw new NullPointerException("classInstanceLimit == null");
727 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700728 this.mask = mask;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800729 this.classInstanceLimit = classInstanceLimit;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700730 mListener = listener;
731 mCallbackExecutor = executor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700732 }
733
734 @Override
735 public String toString() {
736 return "[StrictMode.VmPolicy; mask=" + mask + "]";
737 }
738
739 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700740 * Creates {@link VmPolicy} instances. Methods whose names start with {@code detect} specify
741 * what problems we should look for. Methods whose names start with {@code penalty} specify
742 * what we should do when we detect a problem.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700743 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700744 * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently
745 * order is insignificant: all penalties apply to all detected problems.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700746 *
747 * <p>For example, detect everything and log anything that's found:
Kurt Nelson46974a22017-08-30 13:30:26 -0700748 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700749 * <pre>
750 * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
751 * .detectAll()
752 * .penaltyLog()
753 * .build();
754 * StrictMode.setVmPolicy(policy);
755 * </pre>
756 */
757 public static final class Builder {
758 private int mMask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700759 private OnVmViolationListener mListener;
760 private Executor mExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700761
Kurt Nelson46974a22017-08-30 13:30:26 -0700762 private HashMap<Class, Integer> mClassInstanceLimit; // null until needed
763 private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800764
765 public Builder() {
766 mMask = 0;
767 }
768
Kurt Nelson46974a22017-08-30 13:30:26 -0700769 /** Build upon an existing VmPolicy. */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800770 public Builder(VmPolicy base) {
771 mMask = base.mask;
772 mClassInstanceLimitNeedCow = true;
773 mClassInstanceLimit = base.classInstanceLimit;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700774 mListener = base.mListener;
775 mExecutor = base.mCallbackExecutor;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800776 }
777
778 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700779 * Set an upper bound on how many instances of a class can be in memory at once. Helps
780 * to prevent object leaks.
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800781 */
782 public Builder setClassInstanceLimit(Class klass, int instanceLimit) {
783 if (klass == null) {
784 throw new NullPointerException("klass == null");
785 }
786 if (mClassInstanceLimitNeedCow) {
Kurt Nelson46974a22017-08-30 13:30:26 -0700787 if (mClassInstanceLimit.containsKey(klass)
788 && mClassInstanceLimit.get(klass) == instanceLimit) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800789 // no-op; don't break COW
790 return this;
791 }
792 mClassInstanceLimitNeedCow = false;
793 mClassInstanceLimit = (HashMap<Class, Integer>) mClassInstanceLimit.clone();
794 } else if (mClassInstanceLimit == null) {
795 mClassInstanceLimit = new HashMap<Class, Integer>();
796 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800797 mMask |= DETECT_VM_INSTANCE_LEAKS;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800798 mClassInstanceLimit.put(klass, instanceLimit);
799 return this;
800 }
801
Kurt Nelson46974a22017-08-30 13:30:26 -0700802 /** Detect leaks of {@link android.app.Activity} subclasses. */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800803 public Builder detectActivityLeaks() {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800804 return enable(DETECT_VM_ACTIVITY_LEAKS);
805 }
806
Jeff Sharkey89182982017-11-01 19:02:56 -0600807 /** @hide */
808 public Builder permitActivityLeaks() {
809 return disable(DETECT_VM_ACTIVITY_LEAKS);
810 }
811
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700812 /**
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100813 * Detect reflective usage of APIs that are not part of the public Android SDK.
814 */
815 public Builder detectNonSdkApiUsage() {
816 return enable(DETECT_VM_NON_SDK_API_USAGE);
817 }
818
819 /**
820 * Permit reflective usage of APIs that are not part of the public Android SDK. Note
821 * that this <b>only</b> affects {@code StrictMode}, the underlying runtime may
822 * continue to restrict or warn on access to methods that are not part of the
823 * public SDK.
824 */
825 public Builder permitNonSdkApiUsage() {
826 return disable(DETECT_VM_NON_SDK_API_USAGE);
827 }
828
829 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700830 * Detect everything that's potentially suspect.
831 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700832 * <p>In the Honeycomb release this includes leaks of SQLite cursors, Activities, and
833 * other closable objects but will likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700834 */
835 public Builder detectAll() {
Jeff Sharkey0b558702017-01-26 16:48:01 -0700836 detectLeakedSqlLiteObjects();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800837
Jeff Sharkey0b558702017-01-26 16:48:01 -0700838 final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
839 if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
840 detectActivityLeaks();
841 detectLeakedClosableObjects();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800842 }
Jeff Sharkey0b558702017-01-26 16:48:01 -0700843 if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) {
844 detectLeakedRegistrationObjects();
845 }
846 if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
847 detectFileUriExposure();
848 }
849 if (targetSdk >= Build.VERSION_CODES.M) {
850 // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have
851 // facility for apps to mark sockets that should be ignored
852 if (SystemProperties.getBoolean(CLEARTEXT_PROPERTY, false)) {
853 detectCleartextNetwork();
854 }
855 }
856 if (targetSdk >= Build.VERSION_CODES.O) {
857 detectContentUriWithoutPermission();
858 detectUntaggedSockets();
859 }
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100860
861 // TODO: Decide whether to detect non SDK API usage beyond a certain API level.
Jeff Sharkey0b558702017-01-26 16:48:01 -0700862 return this;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700863 }
864
865 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700866 * Detect when an {@link android.database.sqlite.SQLiteCursor} or other SQLite object is
867 * finalized without having been closed.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700868 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700869 * <p>You always want to explicitly close your SQLite cursors to avoid unnecessary
870 * database contention and temporary memory leaks.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700871 */
872 public Builder detectLeakedSqlLiteObjects() {
873 return enable(DETECT_VM_CURSOR_LEAKS);
874 }
875
876 /**
Kurt Nelsond25bd9f2017-09-14 11:36:34 -0700877 * Detect when an {@link java.io.Closeable} or other object with an explicit termination
Kurt Nelson46974a22017-08-30 13:30:26 -0700878 * method is finalized without having been closed.
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700879 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700880 * <p>You always want to explicitly close such objects to avoid unnecessary resources
881 * leaks.
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700882 */
883 public Builder detectLeakedClosableObjects() {
884 return enable(DETECT_VM_CLOSABLE_LEAKS);
885 }
886
887 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700888 * Detect when a {@link BroadcastReceiver} or {@link ServiceConnection} is leaked during
889 * {@link Context} teardown.
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800890 */
891 public Builder detectLeakedRegistrationObjects() {
892 return enable(DETECT_VM_REGISTRATION_LEAKS);
893 }
894
895 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700896 * Detect when the calling application exposes a {@code file://} {@link android.net.Uri}
897 * to another app.
898 *
899 * <p>This exposure is discouraged since the receiving app may not have access to the
900 * shared path. For example, the receiving app may not have requested the {@link
901 * android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime permission, or the
902 * platform may be sharing the {@link android.net.Uri} across user profile boundaries.
903 *
904 * <p>Instead, apps should use {@code content://} Uris so the platform can extend
905 * temporary permission for the receiving app to access the resource.
Jeff Sharkey344744b2016-01-28 19:03:30 -0700906 *
907 * @see android.support.v4.content.FileProvider
908 * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700909 */
910 public Builder detectFileUriExposure() {
911 return enable(DETECT_VM_FILE_URI_EXPOSURE);
912 }
913
914 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700915 * Detect any network traffic from the calling app which is not wrapped in SSL/TLS. This
916 * can help you detect places that your app is inadvertently sending cleartext data
917 * across the network.
918 *
919 * <p>Using {@link #penaltyDeath()} or {@link #penaltyDeathOnCleartextNetwork()} will
920 * block further traffic on that socket to prevent accidental data leakage, in addition
921 * to crashing your process.
922 *
923 * <p>Using {@link #penaltyDropBox()} will log the raw contents of the packet that
924 * triggered the violation.
925 *
926 * <p>This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it may be subject to
927 * false positives, such as when STARTTLS protocols or HTTP proxies are used.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800928 */
929 public Builder detectCleartextNetwork() {
930 return enable(DETECT_VM_CLEARTEXT_NETWORK);
931 }
932
933 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700934 * Detect when the calling application sends a {@code content://} {@link
935 * android.net.Uri} to another app without setting {@link
936 * Intent#FLAG_GRANT_READ_URI_PERMISSION} or {@link
937 * Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
938 *
939 * <p>Forgetting to include one or more of these flags when sending an intent is
940 * typically an app bug.
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -0700941 *
942 * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
943 * @see Intent#FLAG_GRANT_WRITE_URI_PERMISSION
944 */
945 public Builder detectContentUriWithoutPermission() {
946 return enable(DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION);
947 }
948
949 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700950 * Detect any sockets in the calling app which have not been tagged using {@link
951 * TrafficStats}. Tagging sockets can help you investigate network usage inside your
952 * app, such as a narrowing down heavy usage to a specific library or component.
953 *
954 * <p>This currently does not detect sockets created in native code.
Jeff Sharkey619a5112017-01-19 11:55:54 -0700955 *
956 * @see TrafficStats#setThreadStatsTag(int)
957 * @see TrafficStats#tagSocket(java.net.Socket)
958 * @see TrafficStats#tagDatagramSocket(java.net.DatagramSocket)
959 */
960 public Builder detectUntaggedSockets() {
961 return enable(DETECT_VM_UNTAGGED_SOCKET);
962 }
963
Jeff Sharkey89182982017-11-01 19:02:56 -0600964 /** @hide */
965 public Builder permitUntaggedSockets() {
966 return disable(DETECT_VM_UNTAGGED_SOCKET);
967 }
968
Jeff Sharkey619a5112017-01-19 11:55:54 -0700969 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700970 * Crashes the whole process on violation. This penalty runs at the end of all enabled
971 * penalties so you'll still get your logging or other violations before the process
972 * dies.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700973 */
974 public Builder penaltyDeath() {
975 return enable(PENALTY_DEATH);
976 }
977
978 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700979 * Crashes the whole process when cleartext network traffic is detected.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800980 *
981 * @see #detectCleartextNetwork()
Jeff Sharkey605eb792014-11-04 13:34:06 -0800982 */
983 public Builder penaltyDeathOnCleartextNetwork() {
984 return enable(PENALTY_DEATH_ON_CLEARTEXT_NETWORK);
985 }
986
987 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700988 * Crashes the whole process when a {@code file://} {@link android.net.Uri} is exposed
989 * beyond this app.
Jeff Sharkey344744b2016-01-28 19:03:30 -0700990 *
991 * @see #detectFileUriExposure()
992 */
993 public Builder penaltyDeathOnFileUriExposure() {
994 return enable(PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
995 }
996
Kurt Nelson46974a22017-08-30 13:30:26 -0700997 /** Log detected violations to the system log. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700998 public Builder penaltyLog() {
999 return enable(PENALTY_LOG);
1000 }
1001
1002 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001003 * Enable detected violations log a stacktrace and timing data to the {@link
1004 * android.os.DropBoxManager DropBox} on policy violation. Intended mostly for platform
1005 * integrators doing beta user field data collection.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001006 */
1007 public Builder penaltyDropBox() {
1008 return enable(PENALTY_DROPBOX);
1009 }
1010
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001011 /**
1012 * Call #{@link OnVmViolationListener#onVmViolation(Violation)} on every violation.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001013 */
1014 public Builder penaltyListener(
Kurt Nelson72534b72018-02-22 11:21:15 -08001015 @NonNull Executor executor, @NonNull OnVmViolationListener listener) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001016 if (executor == null) {
1017 throw new NullPointerException("executor must not be null");
1018 }
1019 mListener = listener;
1020 mExecutor = executor;
1021 return this;
1022 }
1023
Kurt Nelson72534b72018-02-22 11:21:15 -08001024 /** @removed */
1025 public Builder penaltyListener(
1026 @NonNull OnVmViolationListener listener, @NonNull Executor executor) {
1027 return penaltyListener(executor, listener);
1028 }
1029
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001030 private Builder enable(int bit) {
1031 mMask |= bit;
1032 return this;
1033 }
1034
Mathieu Chartierca8c1052017-06-19 18:42:57 -07001035 Builder disable(int bit) {
1036 mMask &= ~bit;
1037 return this;
1038 }
1039
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001040 /**
1041 * Construct the VmPolicy instance.
1042 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001043 * <p>Note: if no penalties are enabled before calling <code>build</code>, {@link
1044 * #penaltyLog} is implicitly set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001045 */
1046 public VmPolicy build() {
1047 // If there are detection bits set but no violation bits
1048 // set, enable simple logging.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001049 if (mListener == null
1050 && mMask != 0
Kurt Nelson46974a22017-08-30 13:30:26 -07001051 && (mMask
1052 & (PENALTY_DEATH
1053 | PENALTY_LOG
1054 | PENALTY_DROPBOX
1055 | PENALTY_DIALOG))
1056 == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001057 penaltyLog();
1058 }
Kurt Nelson46974a22017-08-30 13:30:26 -07001059 return new VmPolicy(
1060 mMask,
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001061 mClassInstanceLimit != null ? mClassInstanceLimit : EMPTY_CLASS_LIMIT_MAP,
1062 mListener,
1063 mExecutor);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001064 }
1065 }
1066 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001067
1068 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001069 * Log of strict mode violation stack traces that have occurred during a Binder call, to be
1070 * serialized back later to the caller via Parcel.writeNoException() (amusingly) where the
1071 * caller can choose how to react.
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001072 */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001073 private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
1074 new ThreadLocal<ArrayList<ViolationInfo>>() {
Kurt Nelson46974a22017-08-30 13:30:26 -07001075 @Override
1076 protected ArrayList<ViolationInfo> initialValue() {
1077 // Starts null to avoid unnecessary allocations when
1078 // checking whether there are any violations or not in
1079 // hasGatheredViolations() below.
1080 return null;
1081 }
1082 };
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001083
1084 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001085 * Sets the policy for what actions on the current thread should be detected, as well as the
1086 * penalty if such actions occur.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001087 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001088 * <p>Internally this sets a thread-local variable which is propagated across cross-process IPC
1089 * calls, meaning you can catch violations when a system service or another process accesses the
1090 * disk or network on your behalf.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -07001091 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001092 * @param policy the policy to put into place
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001093 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001094 public static void setThreadPolicy(final ThreadPolicy policy) {
1095 setThreadPolicyMask(policy.mask);
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001096 sThreadViolationListener.set(policy.mListener);
1097 sThreadViolationExecutor.set(policy.mCallbackExecutor);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001098 }
1099
Jeff Sharkey89182982017-11-01 19:02:56 -06001100 /** @hide */
1101 public static void setThreadPolicyMask(final int policyMask) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001102 // In addition to the Java-level thread-local in Dalvik's
1103 // BlockGuard, we also need to keep a native thread-local in
1104 // Binder in order to propagate the value across Binder calls,
1105 // even across native-only processes. The two are kept in
1106 // sync via the callback to onStrictModePolicyChange, below.
1107 setBlockGuardPolicy(policyMask);
1108
1109 // And set the Android native version...
1110 Binder.setThreadStrictModePolicy(policyMask);
1111 }
1112
1113 // Sets the policy in Dalvik/libcore (BlockGuard)
1114 private static void setBlockGuardPolicy(final int policyMask) {
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001115 if (policyMask == 0) {
1116 BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
1117 return;
1118 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001119 final BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1120 final AndroidBlockGuardPolicy androidPolicy;
1121 if (policy instanceof AndroidBlockGuardPolicy) {
1122 androidPolicy = (AndroidBlockGuardPolicy) policy;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001123 } else {
Kurt Nelson46974a22017-08-30 13:30:26 -07001124 androidPolicy = THREAD_ANDROID_POLICY.get();
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001125 BlockGuard.setThreadPolicy(androidPolicy);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001126 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001127 androidPolicy.setPolicyMask(policyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001128 }
1129
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001130 // Sets up CloseGuard in Dalvik/libcore
1131 private static void setCloseGuardEnabled(boolean enabled) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -08001132 if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001133 CloseGuard.setReporter(new AndroidCloseGuardReporter());
1134 }
1135 CloseGuard.setEnabled(enabled);
1136 }
1137
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001138 /**
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -07001139 * Returns the bitmask of the current thread's policy.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001140 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001141 * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001142 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001143 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001144 public static int getThreadPolicyMask() {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001145 return BlockGuard.getThreadPolicy().getPolicyMask();
1146 }
1147
Kurt Nelson46974a22017-08-30 13:30:26 -07001148 /** Returns the current thread's policy. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001149 public static ThreadPolicy getThreadPolicy() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001150 // TODO: this was a last minute Gingerbread API change (to
1151 // introduce VmPolicy cleanly) but this isn't particularly
1152 // optimal for users who might call this method often. This
1153 // should be in a thread-local and not allocate on each call.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001154 return new ThreadPolicy(
1155 getThreadPolicyMask(),
1156 sThreadViolationListener.get(),
1157 sThreadViolationExecutor.get());
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001158 }
1159
1160 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001161 * A convenience wrapper that takes the current {@link ThreadPolicy} from {@link
1162 * #getThreadPolicy}, modifies it to permit both disk reads &amp; writes, and sets the new
1163 * policy with {@link #setThreadPolicy}, returning the old policy so you can restore it at the
1164 * end of a block.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001165 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001166 * @return the old policy, to be passed to {@link #setThreadPolicy} to restore the policy at the
1167 * end of a block
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001168 */
1169 public static ThreadPolicy allowThreadDiskWrites() {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001170 return new ThreadPolicy(
1171 allowThreadDiskWritesMask(),
1172 sThreadViolationListener.get(),
1173 sThreadViolationExecutor.get());
Jeff Sharkey89182982017-11-01 19:02:56 -06001174 }
1175
1176 /** @hide */
1177 public static int allowThreadDiskWritesMask() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001178 int oldPolicyMask = getThreadPolicyMask();
1179 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
1180 if (newPolicyMask != oldPolicyMask) {
1181 setThreadPolicyMask(newPolicyMask);
1182 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001183 return oldPolicyMask;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001184 }
1185
1186 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001187 * A convenience wrapper that takes the current {@link ThreadPolicy} from {@link
1188 * #getThreadPolicy}, modifies it to permit disk reads, and sets the new policy with {@link
1189 * #setThreadPolicy}, returning the old policy so you can restore it at the end of a block.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001190 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001191 * @return the old policy, to be passed to setThreadPolicy to restore the policy.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001192 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001193 public static ThreadPolicy allowThreadDiskReads() {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001194 return new ThreadPolicy(
1195 allowThreadDiskReadsMask(),
1196 sThreadViolationListener.get(),
1197 sThreadViolationExecutor.get());
Jeff Sharkey89182982017-11-01 19:02:56 -06001198 }
1199
1200 /** @hide */
1201 public static int allowThreadDiskReadsMask() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001202 int oldPolicyMask = getThreadPolicyMask();
1203 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
1204 if (newPolicyMask != oldPolicyMask) {
1205 setThreadPolicyMask(newPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001206 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001207 return oldPolicyMask;
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001208 }
1209
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001210 private static ThreadPolicy allowThreadViolations() {
1211 ThreadPolicy oldPolicy = getThreadPolicy();
1212 setThreadPolicyMask(0);
1213 return oldPolicy;
1214 }
1215
1216 private static VmPolicy allowVmViolations() {
1217 VmPolicy oldPolicy = getVmPolicy();
1218 sVmPolicy = VmPolicy.LAX;
1219 return oldPolicy;
1220 }
1221
Jeff Sharkey89182982017-11-01 19:02:56 -06001222 /**
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001223 * Determine if the given app is "bundled" as part of the system image. These bundled apps are
1224 * developed in lock-step with the OS, and they aren't updated outside of an OTA, so we want to
1225 * chase any {@link StrictMode} regressions by enabling detection when running on {@link
1226 * Build#IS_USERDEBUG} or {@link Build#IS_ENG} builds.
1227 *
1228 * <p>Unbundled apps included in the system image are expected to detect and triage their own
1229 * {@link StrictMode} issues separate from the OS release process, which is why we don't enable
1230 * them here.
Jeff Sharkey89182982017-11-01 19:02:56 -06001231 *
1232 * @hide
1233 */
1234 public static boolean isBundledSystemApp(ApplicationInfo ai) {
1235 if (ai == null || ai.packageName == null) {
1236 // Probably system server
1237 return true;
1238 } else if (ai.isSystemApp()) {
1239 // Ignore unbundled apps living in the wrong namespace
1240 if (ai.packageName.equals("com.android.vending")
1241 || ai.packageName.equals("com.android.chrome")) {
1242 return false;
1243 }
Brad Fitzpatrickf5454592010-11-24 15:27:51 -08001244
Jeff Sharkey89182982017-11-01 19:02:56 -06001245 // Ignore bundled apps that are way too spammy
1246 // STOPSHIP: burn this list down to zero
1247 if (ai.packageName.equals("com.android.phone")) {
1248 return false;
1249 }
1250
1251 if (ai.packageName.equals("android")
1252 || ai.packageName.startsWith("android.")
1253 || ai.packageName.startsWith("com.android.")) {
Brad Fitzpatrickf5454592010-11-24 15:27:51 -08001254 return true;
1255 }
1256 }
1257 return false;
1258 }
1259
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001260 /**
Jeff Sharkey89182982017-11-01 19:02:56 -06001261 * Initialize default {@link ThreadPolicy} for the current thread.
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001262 *
1263 * @hide
1264 */
Jeff Sharkey89182982017-11-01 19:02:56 -06001265 public static void initThreadDefaults(ApplicationInfo ai) {
1266 final ThreadPolicy.Builder builder = new ThreadPolicy.Builder();
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001267 final int targetSdkVersion =
1268 (ai != null) ? ai.targetSdkVersion : Build.VERSION_CODES.CUR_DEVELOPMENT;
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001269
Jeff Sharkey89182982017-11-01 19:02:56 -06001270 // Starting in HC, we don't allow network usage on the main thread
1271 if (targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
1272 builder.detectNetwork();
1273 builder.penaltyDeathOnNetwork();
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001274 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001275
Jeff Sharkey89182982017-11-01 19:02:56 -06001276 if (Build.IS_USER || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) {
1277 // Detect nothing extra
1278 } else if (Build.IS_USERDEBUG) {
1279 // Detect everything in bundled apps
1280 if (isBundledSystemApp(ai)) {
1281 builder.detectAll();
1282 builder.penaltyDropBox();
1283 if (SystemProperties.getBoolean(VISUAL_PROPERTY, false)) {
1284 builder.penaltyFlashScreen();
1285 }
Mathieu Chartierca8c1052017-06-19 18:42:57 -07001286 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001287 } else if (Build.IS_ENG) {
1288 // Detect everything in bundled apps
1289 if (isBundledSystemApp(ai)) {
1290 builder.detectAll();
1291 builder.penaltyDropBox();
1292 builder.penaltyLog();
1293 builder.penaltyFlashScreen();
Jeff Brownd5875d92011-10-09 14:59:37 -07001294 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001295 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001296
1297 setThreadPolicy(builder.build());
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001298 }
1299
1300 /**
Jeff Sharkey89182982017-11-01 19:02:56 -06001301 * Initialize default {@link VmPolicy} for the current VM.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001302 *
1303 * @hide
1304 */
Jeff Sharkey89182982017-11-01 19:02:56 -06001305 public static void initVmDefaults(ApplicationInfo ai) {
1306 final VmPolicy.Builder builder = new VmPolicy.Builder();
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001307 final int targetSdkVersion =
1308 (ai != null) ? ai.targetSdkVersion : Build.VERSION_CODES.CUR_DEVELOPMENT;
Jeff Sharkey89182982017-11-01 19:02:56 -06001309
1310 // Starting in N, we don't allow file:// Uri exposure
1311 if (targetSdkVersion >= Build.VERSION_CODES.N) {
1312 builder.detectFileUriExposure();
1313 builder.penaltyDeathOnFileUriExposure();
1314 }
1315
1316 if (Build.IS_USER || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) {
1317 // Detect nothing extra
1318 } else if (Build.IS_USERDEBUG) {
1319 // Detect everything in bundled apps (except activity leaks, which
1320 // are expensive to track)
1321 if (isBundledSystemApp(ai)) {
1322 builder.detectAll();
1323 builder.permitActivityLeaks();
1324 builder.penaltyDropBox();
1325 }
1326 } else if (Build.IS_ENG) {
1327 // Detect everything in bundled apps
1328 if (isBundledSystemApp(ai)) {
1329 builder.detectAll();
1330 builder.penaltyDropBox();
1331 builder.penaltyLog();
1332 }
1333 }
1334
1335 setVmPolicy(builder.build());
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001336 }
1337
1338 /**
Jeff Sharkey344744b2016-01-28 19:03:30 -07001339 * Used by the framework to make file usage a fatal error.
1340 *
1341 * @hide
1342 */
1343 public static void enableDeathOnFileUriExposure() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001344 sVmPolicy =
1345 new VmPolicy(
1346 sVmPolicy.mask
1347 | DETECT_VM_FILE_URI_EXPOSURE
1348 | PENALTY_DEATH_ON_FILE_URI_EXPOSURE,
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001349 sVmPolicy.classInstanceLimit,
1350 sVmPolicy.mListener,
1351 sVmPolicy.mCallbackExecutor);
Jeff Sharkey344744b2016-01-28 19:03:30 -07001352 }
1353
1354 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001355 * Used by lame internal apps that haven't done the hard work to get themselves off file:// Uris
1356 * yet.
Jeff Sharkey344744b2016-01-28 19:03:30 -07001357 *
1358 * @hide
1359 */
1360 public static void disableDeathOnFileUriExposure() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001361 sVmPolicy =
1362 new VmPolicy(
1363 sVmPolicy.mask
1364 & ~(DETECT_VM_FILE_URI_EXPOSURE
1365 | PENALTY_DEATH_ON_FILE_URI_EXPOSURE),
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001366 sVmPolicy.classInstanceLimit,
1367 sVmPolicy.mListener,
1368 sVmPolicy.mCallbackExecutor);
Jeff Sharkey344744b2016-01-28 19:03:30 -07001369 }
1370
1371 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001372 * Parses the BlockGuard policy mask out from the Exception's getMessage() String value. Kinda
1373 * gross, but least invasive. :/
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001374 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001375 * <p>Input is of the following forms: "policy=137 violation=64" "policy=137 violation=64
1376 * msg=Arbitrary text"
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001377 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001378 * <p>Returns 0 on failure, which is a valid policy, but not a valid policy during a violation
1379 * (else there must've been some policy in effect to violate).
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001380 */
1381 private static int parsePolicyFromMessage(String message) {
1382 if (message == null || !message.startsWith("policy=")) {
1383 return 0;
1384 }
1385 int spaceIndex = message.indexOf(' ');
1386 if (spaceIndex == -1) {
1387 return 0;
1388 }
1389 String policyString = message.substring(7, spaceIndex);
1390 try {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001391 return Integer.parseInt(policyString);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001392 } catch (NumberFormatException e) {
1393 return 0;
1394 }
1395 }
1396
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001397 private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
1398 new ThreadLocal<ArrayList<ViolationInfo>>() {
Kurt Nelson46974a22017-08-30 13:30:26 -07001399 @Override
1400 protected ArrayList<ViolationInfo> initialValue() {
1401 return new ArrayList<ViolationInfo>();
1402 }
1403 };
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001404
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001405 // Note: only access this once verifying the thread has a Looper.
Kurt Nelson46974a22017-08-30 13:30:26 -07001406 private static final ThreadLocal<Handler> THREAD_HANDLER =
1407 new ThreadLocal<Handler>() {
1408 @Override
1409 protected Handler initialValue() {
1410 return new Handler();
1411 }
1412 };
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001413
Kurt Nelson46974a22017-08-30 13:30:26 -07001414 private static final ThreadLocal<AndroidBlockGuardPolicy> THREAD_ANDROID_POLICY =
1415 new ThreadLocal<AndroidBlockGuardPolicy>() {
1416 @Override
1417 protected AndroidBlockGuardPolicy initialValue() {
1418 return new AndroidBlockGuardPolicy(0);
1419 }
1420 };
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001421
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001422 private static boolean tooManyViolationsThisLoop() {
1423 return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
1424 }
1425
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001426 private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
1427 private int mPolicyMask;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001428
1429 // Map from violation stacktrace hashcode -> uptimeMillis of
1430 // last violation. No locking needed, as this is only
1431 // accessed by the same thread.
Dianne Hackborn390517b2013-05-30 15:03:32 -07001432 private ArrayMap<Integer, Long> mLastViolationTime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001433
1434 public AndroidBlockGuardPolicy(final int policyMask) {
1435 mPolicyMask = policyMask;
1436 }
1437
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001438 @Override
1439 public String toString() {
1440 return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
1441 }
1442
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001443 // Part of BlockGuard.Policy interface:
1444 public int getPolicyMask() {
1445 return mPolicyMask;
1446 }
1447
1448 // Part of BlockGuard.Policy interface:
1449 public void onWriteToDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001450 if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001451 return;
1452 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001453 if (tooManyViolationsThisLoop()) {
1454 return;
1455 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001456 startHandlingViolationException(new DiskWriteViolation());
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001457 }
1458
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001459 // Not part of BlockGuard.Policy; just part of StrictMode:
1460 void onCustomSlowCall(String name) {
1461 if ((mPolicyMask & DETECT_CUSTOM) == 0) {
1462 return;
1463 }
1464 if (tooManyViolationsThisLoop()) {
1465 return;
1466 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001467 startHandlingViolationException(new CustomViolation(name));
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001468 }
1469
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001470 // Not part of BlockGuard.Policy; just part of StrictMode:
1471 void onResourceMismatch(Object tag) {
1472 if ((mPolicyMask & DETECT_RESOURCE_MISMATCH) == 0) {
1473 return;
1474 }
1475 if (tooManyViolationsThisLoop()) {
1476 return;
1477 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001478 startHandlingViolationException(new ResourceMismatchViolation(tag));
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001479 }
1480
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001481 // Not part of BlockGuard.Policy; just part of StrictMode:
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001482 public void onUnbufferedIO() {
1483 if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
1484 return;
1485 }
1486 if (tooManyViolationsThisLoop()) {
1487 return;
1488 }
Kurt Nelson0e612802017-11-09 17:25:40 -08001489 startHandlingViolationException(new UnbufferedIoViolation());
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001490 }
1491
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001492 // Part of BlockGuard.Policy interface:
1493 public void onReadFromDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001494 if ((mPolicyMask & DETECT_DISK_READ) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001495 return;
1496 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001497 if (tooManyViolationsThisLoop()) {
1498 return;
1499 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001500 startHandlingViolationException(new DiskReadViolation());
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001501 }
1502
1503 // Part of BlockGuard.Policy interface:
1504 public void onNetwork() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001505 if ((mPolicyMask & DETECT_NETWORK) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001506 return;
1507 }
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001508 if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
1509 throw new NetworkOnMainThreadException();
1510 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001511 if (tooManyViolationsThisLoop()) {
1512 return;
1513 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001514 startHandlingViolationException(new NetworkViolation());
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001515 }
1516
1517 public void setPolicyMask(int policyMask) {
1518 mPolicyMask = policyMask;
1519 }
1520
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001521 // Start handling a violation that just started and hasn't
1522 // actually run yet (e.g. no disk write or network operation
1523 // has yet occurred). This sees if we're in an event loop
1524 // thread and, if so, uses it to roughly measure how long the
1525 // violation took.
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001526 void startHandlingViolationException(Violation e) {
1527 final ViolationInfo info = new ViolationInfo(e, mPolicyMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001528 info.violationUptimeMillis = SystemClock.uptimeMillis();
1529 handleViolationWithTimingAttempt(info);
1530 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001531
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001532 // Attempts to fill in the provided ViolationInfo's
1533 // durationMillis field if this thread has a Looper we can use
1534 // to measure with. We measure from the time of violation
1535 // until the time the looper is idle again (right before
1536 // the next epoll_wait)
1537 void handleViolationWithTimingAttempt(final ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001538 Looper looper = Looper.myLooper();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001539
1540 // Without a Looper, we're unable to time how long the
1541 // violation takes place. This case should be rare, as
1542 // most users will care about timing violations that
1543 // happen on their main UI thread. Note that this case is
1544 // also hit when a violation takes place in a Binder
1545 // thread, in "gather" mode. In this case, the duration
1546 // of the violation is computed by the ultimate caller and
1547 // its Looper, if any.
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001548 //
1549 // Also, as a special short-cut case when the only penalty
1550 // bit is death, we die immediately, rather than timing
1551 // the violation's duration. This makes it convenient to
1552 // use in unit tests too, rather than waiting on a Looper.
1553 //
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001554 // TODO: if in gather mode, ignore Looper.myLooper() and always
1555 // go into this immediate mode?
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001556 if (looper == null || (info.mPolicy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
Kurt Nelson46974a22017-08-30 13:30:26 -07001557 info.durationMillis = -1; // unknown (redundant, already set)
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001558 onThreadPolicyViolation(info);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001559 return;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001560 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001561
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001562 final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001563 if (records.size() >= MAX_OFFENSES_PER_LOOP) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001564 // Not worth measuring. Too many offenses in one loop.
1565 return;
1566 }
1567 records.add(info);
1568 if (records.size() > 1) {
1569 // There's already been a violation this loop, so we've already
1570 // registered an idle handler to process the list of violations
1571 // at the end of this Looper's loop.
1572 return;
1573 }
1574
Kurt Nelson46974a22017-08-30 13:30:26 -07001575 final IWindowManager windowManager =
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001576 info.penaltyEnabled(PENALTY_FLASH) ? sWindowManager.get() : null;
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001577 if (windowManager != null) {
1578 try {
1579 windowManager.showStrictModeViolation(true);
1580 } catch (RemoteException unused) {
1581 }
1582 }
1583
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001584 // We post a runnable to a Handler (== delay 0 ms) for
1585 // measuring the end time of a violation instead of using
1586 // an IdleHandler (as was previously used) because an
1587 // IdleHandler may not run for quite a long period of time
1588 // if an ongoing animation is happening and continually
1589 // posting ASAP (0 ms) animation steps. Animations are
1590 // throttled back to 60fps via SurfaceFlinger/View
1591 // invalidates, _not_ by posting frame updates every 16
1592 // milliseconds.
Kurt Nelson46974a22017-08-30 13:30:26 -07001593 THREAD_HANDLER
1594 .get()
1595 .postAtFrontOfQueue(
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001596 () -> {
1597 long loopFinishTime = SystemClock.uptimeMillis();
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001598
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001599 // Note: we do this early, before handling the
1600 // violation below, as handling the violation
1601 // may include PENALTY_DEATH and we don't want
1602 // to keep the red border on.
1603 if (windowManager != null) {
1604 try {
1605 windowManager.showStrictModeViolation(false);
1606 } catch (RemoteException unused) {
Kurt Nelson46974a22017-08-30 13:30:26 -07001607 }
Kurt Nelson46974a22017-08-30 13:30:26 -07001608 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001609
1610 for (int n = 0; n < records.size(); ++n) {
1611 ViolationInfo v = records.get(n);
1612 v.violationNumThisLoop = n + 1;
1613 v.durationMillis =
1614 (int) (loopFinishTime - v.violationUptimeMillis);
1615 onThreadPolicyViolation(v);
1616 }
1617 records.clear();
Kurt Nelson46974a22017-08-30 13:30:26 -07001618 });
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001619 }
1620
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001621 // Note: It's possible (even quite likely) that the
1622 // thread-local policy mask has changed from the time the
1623 // violation fired and now (after the violating code ran) due
1624 // to people who push/pop temporary policy in regions of code,
1625 // hence the policy being passed around.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001626 void onThreadPolicyViolation(final ViolationInfo info) {
1627 if (LOG_V) Log.d(TAG, "onThreadPolicyViolation; policy=" + info.mPolicy);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001628
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001629 if (info.penaltyEnabled(PENALTY_GATHER)) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001630 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001631 if (violations == null) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001632 violations = new ArrayList<>(1);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001633 gatheredViolations.set(violations);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001634 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001635 for (ViolationInfo previous : violations) {
Kurt Nelson0918c932017-09-07 10:56:56 -07001636 if (info.getStackTrace().equals(previous.getStackTrace())) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001637 // Duplicate. Don't log.
1638 return;
1639 }
1640 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001641 violations.add(info);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001642 return;
1643 }
1644
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001645 // Not perfect, but fast and good enough for dup suppression.
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08001646 Integer crashFingerprint = info.hashCode();
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001647 long lastViolationTime = 0;
Dianne Hackborn390517b2013-05-30 15:03:32 -07001648 if (mLastViolationTime != null) {
1649 Long vtime = mLastViolationTime.get(crashFingerprint);
1650 if (vtime != null) {
1651 lastViolationTime = vtime;
1652 }
1653 } else {
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07001654 mLastViolationTime = new ArrayMap<>(1);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001655 }
1656 long now = SystemClock.uptimeMillis();
1657 mLastViolationTime.put(crashFingerprint, now);
Kurt Nelson46974a22017-08-30 13:30:26 -07001658 long timeSinceLastViolationMillis =
1659 lastViolationTime == 0 ? Long.MAX_VALUE : (now - lastViolationTime);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001660
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001661 if (info.penaltyEnabled(PENALTY_LOG)
Kurt Nelson46974a22017-08-30 13:30:26 -07001662 && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07001663 sLogger.log(info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001664 }
1665
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001666 final Violation violation = info.mViolation;
1667
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001668 // The violationMaskSubset, passed to ActivityManager, is a
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001669 // subset of the original StrictMode policy bitmask, with
1670 // only the bit violated and penalty bits to be executed
1671 // by the ActivityManagerService remaining set.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001672 int violationMaskSubset = 0;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001673
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001674 if (info.penaltyEnabled(PENALTY_DIALOG)
Kurt Nelson46974a22017-08-30 13:30:26 -07001675 && timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001676 violationMaskSubset |= PENALTY_DIALOG;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001677 }
1678
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001679 if (info.penaltyEnabled(PENALTY_DROPBOX) && lastViolationTime == 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001680 violationMaskSubset |= PENALTY_DROPBOX;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001681 }
1682
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001683 if (violationMaskSubset != 0) {
Kurt Nelson0918c932017-09-07 10:56:56 -07001684 violationMaskSubset |= info.getViolationBit();
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001685
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001686 final boolean justDropBox = (info.mPolicy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001687 if (justDropBox) {
1688 // If all we're going to ask the activity manager
1689 // to do is dropbox it (the common case during
1690 // platform development), we can avoid doing this
1691 // call synchronously which Binder data suggests
1692 // isn't always super fast, despite the implementation
1693 // in the ActivityManager trying to be mostly async.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001694 dropboxViolationAsync(violationMaskSubset, info);
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -07001695 } else {
1696 handleApplicationStrictModeViolation(violationMaskSubset, info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001697 }
1698 }
1699
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001700 if ((info.getPolicyMask() & PENALTY_DEATH) != 0) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001701 throw new RuntimeException("StrictMode ThreadPolicy violation", violation);
1702 }
1703
1704 // penaltyDeath will cause penaltyCallback to no-op since we cannot guarantee the
1705 // executor finishes before crashing.
1706 final OnThreadViolationListener listener = sThreadViolationListener.get();
1707 final Executor executor = sThreadViolationExecutor.get();
1708 if (listener != null && executor != null) {
1709 try {
1710 executor.execute(
1711 () -> {
1712 // Lift violated policy to prevent infinite recursion.
1713 ThreadPolicy oldPolicy = allowThreadViolations();
1714 try {
1715 listener.onThreadViolation(violation);
1716 } finally {
1717 setThreadPolicy(oldPolicy);
1718 }
1719 });
1720 } catch (RejectedExecutionException e) {
1721 Log.e(TAG, "ThreadPolicy penaltyCallback failed", e);
1722 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001723 }
1724 }
1725 }
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001726
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001727 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001728 * In the common case, as set by conditionallyEnableDebugLogging, we're just dropboxing any
1729 * violations but not showing a dialog, not loggging, and not killing the process. In these
1730 * cases we don't need to do a synchronous call to the ActivityManager. This is used by both
1731 * per-thread and vm-wide violations when applicable.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001732 */
1733 private static void dropboxViolationAsync(
1734 final int violationMaskSubset, final ViolationInfo info) {
1735 int outstanding = sDropboxCallsInFlight.incrementAndGet();
1736 if (outstanding > 20) {
1737 // What's going on? Let's not make make the situation
1738 // worse and just not log.
1739 sDropboxCallsInFlight.decrementAndGet();
1740 return;
1741 }
1742
1743 if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1744
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -07001745 BackgroundThread.getHandler().post(() -> {
1746 handleApplicationStrictModeViolation(violationMaskSubset, info);
1747 int outstandingInner = sDropboxCallsInFlight.decrementAndGet();
1748 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstandingInner);
1749 });
1750 }
1751
1752 private static void handleApplicationStrictModeViolation(int violationMaskSubset,
1753 ViolationInfo info) {
1754 final int oldMask = getThreadPolicyMask();
1755 try {
1756 // First, remove any policy before we call into the Activity Manager,
1757 // otherwise we'll infinite recurse as we try to log policy violations
1758 // to disk, thus violating policy, thus requiring logging, etc...
1759 // We restore the current policy below, in the finally block.
1760 setThreadPolicyMask(0);
1761
1762 IActivityManager am = ActivityManager.getService();
1763 if (am == null) {
1764 Log.w(TAG, "No activity manager; failed to Dropbox violation.");
1765 } else {
1766 am.handleApplicationStrictModeViolation(
1767 RuntimeInit.getApplicationObject(), violationMaskSubset, info);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001768 }
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -07001769 } catch (RemoteException e) {
1770 if (e instanceof DeadObjectException) {
1771 // System process is dead; ignore
1772 } else {
1773 Log.e(TAG, "RemoteException handling StrictMode violation", e);
1774 }
1775 } finally {
1776 setThreadPolicyMask(oldMask);
1777 }
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001778 }
1779
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001780 private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
Jeff Sharkey605eb792014-11-04 13:34:06 -08001781 public void report(String message, Throwable allocationSite) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001782 onVmPolicyViolation(new LeakedClosableViolation(message, allocationSite));
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001783 }
1784 }
1785
Kurt Nelson46974a22017-08-30 13:30:26 -07001786 /** Called from Parcel.writeNoException() */
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001787 /* package */ static boolean hasGatheredViolations() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001788 return gatheredViolations.get() != null;
1789 }
1790
1791 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001792 * Called from Parcel.writeException(), so we drop this memory and don't incorrectly attribute
1793 * it to the wrong caller on the next Binder call on this thread.
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001794 */
1795 /* package */ static void clearGatheredViolations() {
1796 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001797 }
1798
Kurt Nelson46974a22017-08-30 13:30:26 -07001799 /** @hide */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001800 public static void conditionallyCheckInstanceCounts() {
1801 VmPolicy policy = getVmPolicy();
Mathieu Chartierd288a262015-07-10 13:44:42 -07001802 int policySize = policy.classInstanceLimit.size();
1803 if (policySize == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001804 return;
1805 }
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08001806
1807 System.gc();
1808 System.runFinalization();
1809 System.gc();
1810
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001811 // Note: classInstanceLimit is immutable, so this is lock-free
Mathieu Chartierd288a262015-07-10 13:44:42 -07001812 // Create the classes array.
1813 Class[] classes = policy.classInstanceLimit.keySet().toArray(new Class[policySize]);
1814 long[] instanceCounts = VMDebug.countInstancesOfClasses(classes, false);
1815 for (int i = 0; i < classes.length; ++i) {
1816 Class klass = classes[i];
1817 int limit = policy.classInstanceLimit.get(klass);
1818 long instances = instanceCounts[i];
1819 if (instances > limit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001820 onVmPolicyViolation(new InstanceCountViolation(klass, instances, limit));
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001821 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001822 }
1823 }
1824
1825 private static long sLastInstanceCountCheckMillis = 0;
Kurt Nelson46974a22017-08-30 13:30:26 -07001826 private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001827 private static final MessageQueue.IdleHandler sProcessIdleHandler =
1828 new MessageQueue.IdleHandler() {
1829 public boolean queueIdle() {
1830 long now = SystemClock.uptimeMillis();
1831 if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1832 sLastInstanceCountCheckMillis = now;
1833 conditionallyCheckInstanceCounts();
1834 }
1835 return true;
1836 }
1837 };
1838
1839 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001840 * Sets the policy for what actions in the VM process (on any thread) should be detected, as
1841 * well as the penalty if such actions occur.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001842 *
1843 * @param policy the policy to put into place
1844 */
1845 public static void setVmPolicy(final VmPolicy policy) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001846 synchronized (StrictMode.class) {
1847 sVmPolicy = policy;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001848 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001849
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001850 Looper looper = Looper.getMainLooper();
1851 if (looper != null) {
1852 MessageQueue mq = looper.mQueue;
Kurt Nelson46974a22017-08-30 13:30:26 -07001853 if (policy.classInstanceLimit.size() == 0
Kurt Nelson2c883f32017-09-01 10:52:45 -07001854 || (sVmPolicy.mask & VM_PENALTY_MASK) == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001855 mq.removeIdleHandler(sProcessIdleHandler);
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001856 sIsIdlerRegistered = false;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001857 } else if (!sIsIdlerRegistered) {
1858 mq.addIdleHandler(sProcessIdleHandler);
1859 sIsIdlerRegistered = true;
1860 }
1861 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08001862
1863 int networkPolicy = NETWORK_POLICY_ACCEPT;
Kurt Nelson2c883f32017-09-01 10:52:45 -07001864 if ((sVmPolicy.mask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
1865 if ((sVmPolicy.mask & PENALTY_DEATH) != 0
1866 || (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
Jeff Sharkey605eb792014-11-04 13:34:06 -08001867 networkPolicy = NETWORK_POLICY_REJECT;
1868 } else {
1869 networkPolicy = NETWORK_POLICY_LOG;
1870 }
1871 }
1872
Kurt Nelson46974a22017-08-30 13:30:26 -07001873 final INetworkManagementService netd =
1874 INetworkManagementService.Stub.asInterface(
1875 ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
Jeff Sharkey605eb792014-11-04 13:34:06 -08001876 if (netd != null) {
1877 try {
1878 netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
1879 } catch (RemoteException ignored) {
1880 }
1881 } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
1882 Log.w(TAG, "Dropping requested network policy due to missing service!");
1883 }
Narayan Kamathad1b2a92018-03-28 11:29:40 +01001884
1885
1886 if ((sVmPolicy.mask & DETECT_VM_NON_SDK_API_USAGE) != 0) {
1887 VMRuntime.setNonSdkApiUsageConsumer(sNonSdkApiUsageConsumer);
1888 } else {
1889 VMRuntime.setNonSdkApiUsageConsumer(null);
1890 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001891 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001892 }
1893
Kurt Nelson46974a22017-08-30 13:30:26 -07001894 /** Gets the current VM policy. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001895 public static VmPolicy getVmPolicy() {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001896 synchronized (StrictMode.class) {
1897 return sVmPolicy;
1898 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001899 }
1900
1901 /**
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001902 * Enable the recommended StrictMode defaults, with violations just being logged.
1903 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001904 * <p>This catches disk and network access on the main thread, as well as leaked SQLite cursors
1905 * and unclosed resources. This is simply a wrapper around {@link #setVmPolicy} and {@link
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001906 * #setThreadPolicy}.
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001907 */
1908 public static void enableDefaults() {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001909 setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
1910 setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001911 }
1912
Kurt Nelson46974a22017-08-30 13:30:26 -07001913 /** @hide */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001914 public static boolean vmSqliteObjectLeaksEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001915 return (sVmPolicy.mask & DETECT_VM_CURSOR_LEAKS) != 0;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001916 }
1917
Kurt Nelson46974a22017-08-30 13:30:26 -07001918 /** @hide */
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001919 public static boolean vmClosableObjectLeaksEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001920 return (sVmPolicy.mask & DETECT_VM_CLOSABLE_LEAKS) != 0;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001921 }
1922
Kurt Nelson46974a22017-08-30 13:30:26 -07001923 /** @hide */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001924 public static boolean vmRegistrationLeaksEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001925 return (sVmPolicy.mask & DETECT_VM_REGISTRATION_LEAKS) != 0;
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001926 }
1927
Kurt Nelson46974a22017-08-30 13:30:26 -07001928 /** @hide */
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001929 public static boolean vmFileUriExposureEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001930 return (sVmPolicy.mask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001931 }
1932
Kurt Nelson46974a22017-08-30 13:30:26 -07001933 /** @hide */
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -07001934 public static boolean vmCleartextNetworkEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001935 return (sVmPolicy.mask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07001936 }
1937
Kurt Nelson46974a22017-08-30 13:30:26 -07001938 /** @hide */
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -07001939 public static boolean vmContentUriWithoutPermissionEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001940 return (sVmPolicy.mask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
Jeff Sharkey605eb792014-11-04 13:34:06 -08001941 }
1942
Kurt Nelson46974a22017-08-30 13:30:26 -07001943 /** @hide */
Jeff Sharkey619a5112017-01-19 11:55:54 -07001944 public static boolean vmUntaggedSocketEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001945 return (sVmPolicy.mask & DETECT_VM_UNTAGGED_SOCKET) != 0;
Jeff Sharkey619a5112017-01-19 11:55:54 -07001946 }
1947
Kurt Nelson46974a22017-08-30 13:30:26 -07001948 /** @hide */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001949 public static void onSqliteObjectLeaked(String message, Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001950 onVmPolicyViolation(new SqliteObjectLeakedViolation(message, originStack));
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001951 }
1952
Kurt Nelson46974a22017-08-30 13:30:26 -07001953 /** @hide */
Steve Block08d584c2011-05-17 19:05:03 +01001954 public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001955 onVmPolicyViolation(new WebViewMethodCalledOnWrongThreadViolation(originStack));
Steve Block08d584c2011-05-17 19:05:03 +01001956 }
1957
Kurt Nelson46974a22017-08-30 13:30:26 -07001958 /** @hide */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001959 public static void onIntentReceiverLeaked(Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001960 onVmPolicyViolation(new IntentReceiverLeakedViolation(originStack));
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001961 }
1962
Kurt Nelson46974a22017-08-30 13:30:26 -07001963 /** @hide */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001964 public static void onServiceConnectionLeaked(Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001965 onVmPolicyViolation(new ServiceConnectionLeakedViolation(originStack));
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001966 }
1967
Kurt Nelson46974a22017-08-30 13:30:26 -07001968 /** @hide */
Jeff Sharkey344744b2016-01-28 19:03:30 -07001969 public static void onFileUriExposed(Uri uri, String location) {
1970 final String message = uri + " exposed beyond app through " + location;
Kurt Nelson2c883f32017-09-01 10:52:45 -07001971 if ((sVmPolicy.mask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
Jeff Sharkey344744b2016-01-28 19:03:30 -07001972 throw new FileUriExposedException(message);
1973 } else {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001974 onVmPolicyViolation(new FileUriExposedViolation(message));
Jeff Sharkey344744b2016-01-28 19:03:30 -07001975 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08001976 }
1977
Kurt Nelson46974a22017-08-30 13:30:26 -07001978 /** @hide */
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07001979 public static void onContentUriWithoutPermission(Uri uri, String location) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001980 onVmPolicyViolation(new ContentUriWithoutPermissionViolation(uri, location));
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07001981 }
1982
Kurt Nelson46974a22017-08-30 13:30:26 -07001983 /** @hide */
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -07001984 public static final String CLEARTEXT_DETECTED_MSG =
1985 "Detected cleartext network traffic from UID ";
1986
1987 /** @hide */
Jeff Sharkey605eb792014-11-04 13:34:06 -08001988 public static void onCleartextNetworkDetected(byte[] firstPacket) {
1989 byte[] rawAddr = null;
1990 if (firstPacket != null) {
1991 if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
1992 // IPv4
1993 rawAddr = new byte[4];
1994 System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
1995 } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
1996 // IPv6
1997 rawAddr = new byte[16];
1998 System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
1999 }
2000 }
2001
2002 final int uid = android.os.Process.myUid();
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -07002003 String msg = CLEARTEXT_DETECTED_MSG + uid;
Jeff Sharkey605eb792014-11-04 13:34:06 -08002004 if (rawAddr != null) {
2005 try {
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -07002006 msg += " to " + InetAddress.getByAddress(rawAddr);
Jeff Sharkey605eb792014-11-04 13:34:06 -08002007 } catch (UnknownHostException ignored) {
2008 }
2009 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002010 msg += HexDump.dumpHexString(firstPacket).trim() + " ";
Kurt Nelson2c883f32017-09-01 10:52:45 -07002011 final boolean forceDeath = (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002012 onVmPolicyViolation(new CleartextNetworkViolation(msg), forceDeath);
Jeff Sharkeya14acd22013-04-02 18:27:45 -07002013 }
2014
Kurt Nelson46974a22017-08-30 13:30:26 -07002015 /** @hide */
Jeff Sharkey619a5112017-01-19 11:55:54 -07002016 public static void onUntaggedSocket() {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002017 onVmPolicyViolation(new UntaggedSocketViolation());
Jeff Sharkey619a5112017-01-19 11:55:54 -07002018 }
2019
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002020 // Map from VM violation fingerprint to uptime millis.
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002021 private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<>();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002022
Kurt Nelson46974a22017-08-30 13:30:26 -07002023 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002024 public static void onVmPolicyViolation(Violation originStack) {
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002025 onVmPolicyViolation(originStack, false);
Jeff Sharkey605eb792014-11-04 13:34:06 -08002026 }
2027
Kurt Nelson46974a22017-08-30 13:30:26 -07002028 /** @hide */
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002029 public static void onVmPolicyViolation(Violation violation, boolean forceDeath) {
Kurt Nelson2c883f32017-09-01 10:52:45 -07002030 final boolean penaltyDropbox = (sVmPolicy.mask & PENALTY_DROPBOX) != 0;
2031 final boolean penaltyDeath = ((sVmPolicy.mask & PENALTY_DEATH) != 0) || forceDeath;
2032 final boolean penaltyLog = (sVmPolicy.mask & PENALTY_LOG) != 0;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002033 final ViolationInfo info = new ViolationInfo(violation, sVmPolicy.mask);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002034
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002035 // Erase stuff not relevant for process-wide violations
2036 info.numAnimationsRunning = 0;
2037 info.tags = null;
2038 info.broadcastIntentAction = null;
2039
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002040 final Integer fingerprint = info.hashCode();
2041 final long now = SystemClock.uptimeMillis();
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002042 long lastViolationTime;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002043 long timeSinceLastViolationMillis = Long.MAX_VALUE;
2044 synchronized (sLastVmViolationTime) {
2045 if (sLastVmViolationTime.containsKey(fingerprint)) {
2046 lastViolationTime = sLastVmViolationTime.get(fingerprint);
2047 timeSinceLastViolationMillis = now - lastViolationTime;
2048 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002049 if (timeSinceLastViolationMillis > MIN_VM_INTERVAL_MS) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002050 sLastVmViolationTime.put(fingerprint, now);
2051 }
2052 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002053 if (timeSinceLastViolationMillis <= MIN_VM_INTERVAL_MS) {
2054 // Rate limit all penalties.
2055 return;
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -06002056 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002057
2058 if (penaltyLog && sLogger != null && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07002059 sLogger.log(info);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002060 }
2061
Kurt Nelson2c883f32017-09-01 10:52:45 -07002062 int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicy.mask);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08002063
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002064 if (penaltyDropbox) {
2065 if (penaltyDeath) {
2066 handleApplicationStrictModeViolation(violationMaskSubset, info);
2067 } else {
2068 // Common case for userdebug/eng builds. If no death and
2069 // just dropboxing, we can do the ActivityManager call
2070 // asynchronously.
2071 dropboxViolationAsync(violationMaskSubset, info);
2072 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002073 }
2074
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08002075 if (penaltyDeath) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002076 System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
2077 Process.killProcess(Process.myPid());
2078 System.exit(10);
2079 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002080
2081 // If penaltyDeath, we can't guarantee this callback finishes before the process dies for
2082 // all executors. penaltyDeath supersedes penaltyCallback.
2083 if (sVmPolicy.mListener != null && sVmPolicy.mCallbackExecutor != null) {
2084 final OnVmViolationListener listener = sVmPolicy.mListener;
2085 try {
2086 sVmPolicy.mCallbackExecutor.execute(
2087 () -> {
2088 // Lift violated policy to prevent infinite recursion.
2089 VmPolicy oldPolicy = allowVmViolations();
2090 try {
2091 listener.onVmViolation(violation);
2092 } finally {
2093 setVmPolicy(oldPolicy);
2094 }
2095 });
2096 } catch (RejectedExecutionException e) {
2097 Log.e(TAG, "VmPolicy penaltyCallback failed", e);
2098 }
2099 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002100 }
2101
Kurt Nelson46974a22017-08-30 13:30:26 -07002102 /** Called from Parcel.writeNoException() */
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002103 /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002104 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002105 if (violations == null) {
2106 p.writeInt(0);
2107 } else {
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002108 // To avoid taking up too much transaction space, only include
2109 // details for the first 3 violations. Deep inside, CrashInfo
2110 // will truncate each stack trace to ~20kB.
2111 final int size = Math.min(violations.size(), 3);
2112 p.writeInt(size);
2113 for (int i = 0; i < size; i++) {
2114 violations.get(i).writeToParcel(p, 0);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002115 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002116 }
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002117 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002118 }
2119
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002120 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002121 * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, we here
2122 * read back all the encoded violations.
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002123 */
2124 /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002125 Throwable localCallSite = new Throwable();
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002126 final int policyMask = getThreadPolicyMask();
2127 final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002128
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002129 final int size = p.readInt();
2130 for (int i = 0; i < size; i++) {
2131 final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
Kurt Nelson0918c932017-09-07 10:56:56 -07002132 info.addLocalStack(localCallSite);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002133 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2134 if (policy instanceof AndroidBlockGuardPolicy) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002135 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002136 }
2137 }
2138 }
2139
2140 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002141 * Called from android_util_Binder.cpp's android_os_Parcel_enforceInterface when an incoming
2142 * Binder call requires changing the StrictMode policy mask. The role of this function is to ask
2143 * Binder for its current (native) thread-local policy value and synchronize it to libcore's
2144 * (Java) thread-local policy value.
Brad Fitzpatrick727de402010-07-07 16:06:39 -07002145 */
2146 private static void onBinderStrictModePolicyChange(int newPolicy) {
2147 setBlockGuardPolicy(newPolicy);
2148 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002149
2150 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002151 * A tracked, critical time span. (e.g. during an animation.)
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002152 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002153 * <p>The object itself is a linked list node, to avoid any allocations during rapid span
2154 * entries and exits.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002155 *
2156 * @hide
2157 */
2158 public static class Span {
2159 private String mName;
2160 private long mCreateMillis;
2161 private Span mNext;
Kurt Nelson46974a22017-08-30 13:30:26 -07002162 private Span mPrev; // not used when in freeList, only active
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002163 private final ThreadSpanState mContainerState;
2164
2165 Span(ThreadSpanState threadState) {
2166 mContainerState = threadState;
2167 }
2168
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002169 // Empty constructor for the NO_OP_SPAN
2170 protected Span() {
2171 mContainerState = null;
2172 }
2173
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002174 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002175 * To be called when the critical span is complete (i.e. the animation is done animating).
2176 * This can be called on any thread (even a different one from where the animation was
2177 * taking place), but that's only a defensive implementation measure. It really makes no
2178 * sense for you to call this on thread other than that where you created it.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002179 *
2180 * @hide
2181 */
2182 public void finish() {
2183 ThreadSpanState state = mContainerState;
2184 synchronized (state) {
2185 if (mName == null) {
2186 // Duplicate finish call. Ignore.
2187 return;
2188 }
2189
2190 // Remove ourselves from the active list.
2191 if (mPrev != null) {
2192 mPrev.mNext = mNext;
2193 }
2194 if (mNext != null) {
2195 mNext.mPrev = mPrev;
2196 }
2197 if (state.mActiveHead == this) {
2198 state.mActiveHead = mNext;
2199 }
2200
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002201 state.mActiveSize--;
2202
2203 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
2204
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002205 this.mCreateMillis = -1;
2206 this.mName = null;
2207 this.mPrev = null;
2208 this.mNext = null;
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002209
2210 // Add ourselves to the freeList, if it's not already
2211 // too big.
2212 if (state.mFreeListSize < 5) {
2213 this.mNext = state.mFreeListHead;
2214 state.mFreeListHead = this;
2215 state.mFreeListSize++;
2216 }
2217 }
2218 }
2219 }
2220
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002221 // The no-op span that's used in user builds.
Kurt Nelson46974a22017-08-30 13:30:26 -07002222 private static final Span NO_OP_SPAN =
2223 new Span() {
2224 public void finish() {
2225 // Do nothing.
2226 }
2227 };
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002228
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002229 /**
2230 * Linked lists of active spans and a freelist.
2231 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002232 * <p>Locking notes: there's one of these structures per thread and all members of this
2233 * structure (as well as the Span nodes under it) are guarded by the ThreadSpanState object
2234 * instance. While in theory there'd be no locking required because it's all local per-thread,
2235 * the finish() method above is defensive against people calling it on a different thread from
2236 * where they created the Span, hence the locking.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002237 */
2238 private static class ThreadSpanState {
Kurt Nelson46974a22017-08-30 13:30:26 -07002239 public Span mActiveHead; // doubly-linked list.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002240 public int mActiveSize;
Kurt Nelson46974a22017-08-30 13:30:26 -07002241 public Span mFreeListHead; // singly-linked list. only changes at head.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002242 public int mFreeListSize;
2243 }
2244
2245 private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
2246 new ThreadLocal<ThreadSpanState>() {
Kurt Nelson46974a22017-08-30 13:30:26 -07002247 @Override
2248 protected ThreadSpanState initialValue() {
2249 return new ThreadSpanState();
2250 }
2251 };
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002252
Kurt Nelson46974a22017-08-30 13:30:26 -07002253 private static Singleton<IWindowManager> sWindowManager =
2254 new Singleton<IWindowManager>() {
2255 protected IWindowManager create() {
2256 return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
2257 }
2258 };
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08002259
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002260 /**
2261 * Enter a named critical span (e.g. an animation)
2262 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002263 * <p>The name is an arbitary label (or tag) that will be applied to any strictmode violation
2264 * that happens while this span is active. You must call finish() on the span when done.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002265 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002266 * <p>This will never return null, but on devices without debugging enabled, this may return a
2267 * dummy object on which the finish() method is a no-op.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002268 *
2269 * <p>TODO: add CloseGuard to this, verifying callers call finish.
2270 *
2271 * @hide
2272 */
2273 public static Span enterCriticalSpan(String name) {
Jeff Sharkey5ab02432017-06-27 11:01:36 -06002274 if (Build.IS_USER) {
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002275 return NO_OP_SPAN;
2276 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002277 if (name == null || name.isEmpty()) {
2278 throw new IllegalArgumentException("name must be non-null and non-empty");
2279 }
2280 ThreadSpanState state = sThisThreadSpanState.get();
2281 Span span = null;
2282 synchronized (state) {
2283 if (state.mFreeListHead != null) {
2284 span = state.mFreeListHead;
2285 state.mFreeListHead = span.mNext;
2286 state.mFreeListSize--;
2287 } else {
2288 // Shouldn't have to do this often.
2289 span = new Span(state);
2290 }
2291 span.mName = name;
2292 span.mCreateMillis = SystemClock.uptimeMillis();
2293 span.mNext = state.mActiveHead;
2294 span.mPrev = null;
2295 state.mActiveHead = span;
2296 state.mActiveSize++;
2297 if (span.mNext != null) {
2298 span.mNext.mPrev = span;
2299 }
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002300 if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002301 }
2302 return span;
2303 }
2304
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002305 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002306 * For code to note that it's slow. This is a no-op unless the current thread's {@link
2307 * android.os.StrictMode.ThreadPolicy} has {@link
2308 * android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls} enabled.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002309 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002310 * @param name a short string for the exception stack trace that's built if when this fires.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002311 */
2312 public static void noteSlowCall(String name) {
2313 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2314 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2315 // StrictMode not enabled.
2316 return;
2317 }
2318 ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
2319 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002320
2321 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002322 * For code to note that a resource was obtained using a type other than its defined type. This
2323 * is a no-op unless the current thread's {@link android.os.StrictMode.ThreadPolicy} has {@link
2324 * android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()} enabled.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08002325 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002326 * @param tag an object for the exception stack trace that's built if when this fires.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08002327 * @hide
2328 */
2329 public static void noteResourceMismatch(Object tag) {
2330 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2331 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2332 // StrictMode not enabled.
2333 return;
2334 }
2335 ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag);
2336 }
2337
Kurt Nelson46974a22017-08-30 13:30:26 -07002338 /** @hide */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01002339 public static void noteUnbufferedIO() {
2340 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2341 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2342 // StrictMode not enabled.
2343 return;
2344 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002345 policy.onUnbufferedIO();
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01002346 }
2347
Kurt Nelson46974a22017-08-30 13:30:26 -07002348 /** @hide */
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002349 public static void noteDiskRead() {
2350 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002351 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2352 // StrictMode not enabled.
2353 return;
2354 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002355 policy.onReadFromDisk();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002356 }
2357
Kurt Nelson46974a22017-08-30 13:30:26 -07002358 /** @hide */
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002359 public static void noteDiskWrite() {
2360 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2361 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2362 // StrictMode not enabled.
2363 return;
2364 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002365 policy.onWriteToDisk();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002366 }
2367
Kurt Nelson1981f422017-10-25 13:49:26 -07002368 @GuardedBy("StrictMode.class")
2369 private static final HashMap<Class, Integer> sExpectedActivityInstanceCount = new HashMap<>();
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002370
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002371 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002372 * Returns an object that is used to track instances of activites. The activity should store a
2373 * reference to the tracker object in one of its fields.
2374 *
Jeff Brown7e442832011-06-10 18:00:16 -07002375 * @hide
2376 */
2377 public static Object trackActivity(Object instance) {
2378 return new InstanceTracker(instance);
2379 }
2380
Kurt Nelson46974a22017-08-30 13:30:26 -07002381 /** @hide */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002382 public static void incrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002383 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002384 return;
2385 }
Jeff Brown7e442832011-06-10 18:00:16 -07002386
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002387 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002388 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2389 return;
2390 }
2391
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002392 Integer expected = sExpectedActivityInstanceCount.get(klass);
2393 Integer newExpected = expected == null ? 1 : expected + 1;
2394 sExpectedActivityInstanceCount.put(klass, newExpected);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002395 }
2396 }
2397
Kurt Nelson46974a22017-08-30 13:30:26 -07002398 /** @hide */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002399 public static void decrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002400 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002401 return;
2402 }
Jeff Brown7e442832011-06-10 18:00:16 -07002403
2404 final int limit;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002405 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002406 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2407 return;
2408 }
2409
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002410 Integer expected = sExpectedActivityInstanceCount.get(klass);
Jeff Brown7e442832011-06-10 18:00:16 -07002411 int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002412 if (newExpected == 0) {
2413 sExpectedActivityInstanceCount.remove(klass);
2414 } else {
2415 sExpectedActivityInstanceCount.put(klass, newExpected);
2416 }
Jeff Brown7e442832011-06-10 18:00:16 -07002417
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002418 // Note: adding 1 here to give some breathing room during
2419 // orientation changes. (shouldn't be necessary, though?)
Jeff Brown7e442832011-06-10 18:00:16 -07002420 limit = newExpected + 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002421 }
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002422
Jeff Brown7e442832011-06-10 18:00:16 -07002423 // Quick check.
2424 int actual = InstanceTracker.getInstanceCount(klass);
2425 if (actual <= limit) {
2426 return;
2427 }
2428
2429 // Do a GC and explicit count to double-check.
2430 // This is the work that we are trying to avoid by tracking the object instances
2431 // explicity. Running an explicit GC can be expensive (80ms) and so can walking
2432 // the heap to count instance (30ms). This extra work can make the system feel
2433 // noticeably less responsive during orientation changes when activities are
2434 // being restarted. Granted, it is only a problem when StrictMode is enabled
2435 // but it is annoying.
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08002436
2437 System.gc();
2438 System.runFinalization();
2439 System.gc();
Jeff Brown7e442832011-06-10 18:00:16 -07002440
2441 long instances = VMDebug.countInstancesOfClass(klass, false);
2442 if (instances > limit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002443 onVmPolicyViolation(new InstanceCountViolation(klass, instances, limit));
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002444 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002445 }
2446
2447 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002448 * Parcelable that gets sent in Binder call headers back to callers to report violations that
2449 * happened during a cross-process call.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002450 *
2451 * @hide
2452 */
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07002453 @TestApi
2454 public static final class ViolationInfo implements Parcelable {
Kurt Nelson0918c932017-09-07 10:56:56 -07002455 /** Stack and violation details. */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002456 private final Violation mViolation;
Kurt Nelson0918c932017-09-07 10:56:56 -07002457
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002458 /** Path leading to a violation that occurred across binder. */
2459 private final Deque<StackTraceElement[]> mBinderStack = new ArrayDeque<>();
Kurt Nelson0918c932017-09-07 10:56:56 -07002460
2461 /** Memoized stack trace of full violation. */
2462 @Nullable private String mStackTrace;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002463
Kurt Nelson46974a22017-08-30 13:30:26 -07002464 /** The strict mode policy mask at the time of violation. */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002465 private final int mPolicy;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002466
Kurt Nelson46974a22017-08-30 13:30:26 -07002467 /** The wall time duration of the violation, when known. -1 when not known. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002468 public int durationMillis = -1;
2469
Kurt Nelson46974a22017-08-30 13:30:26 -07002470 /** The number of animations currently running. */
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002471 public int numAnimationsRunning = 0;
2472
Kurt Nelson46974a22017-08-30 13:30:26 -07002473 /** List of tags from active Span instances during this violation, or null for none. */
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002474 public String[] tags;
2475
2476 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002477 * Which violation number this was (1-based) since the last Looper loop, from the
2478 * perspective of the root caller (if it crossed any processes via Binder calls). The value
2479 * is 0 if the root caller wasn't on a Looper thread.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002480 */
2481 public int violationNumThisLoop;
2482
Kurt Nelson46974a22017-08-30 13:30:26 -07002483 /** The time (in terms of SystemClock.uptimeMillis()) that the violation occurred. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002484 public long violationUptimeMillis;
2485
2486 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002487 * The action of the Intent being broadcast to somebody's onReceive on this thread right
2488 * now, or null.
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002489 */
2490 public String broadcastIntentAction;
2491
Kurt Nelson46974a22017-08-30 13:30:26 -07002492 /** If this is a instance count violation, the number of instances in memory, else -1. */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002493 public long numInstances = -1;
2494
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002495 /** Create an instance of ViolationInfo initialized from an exception. */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002496 ViolationInfo(Violation tr, int policy) {
2497 this.mViolation = tr;
2498 this.mPolicy = policy;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002499 violationUptimeMillis = SystemClock.uptimeMillis();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002500 this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002501 Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2502 if (broadcastIntent != null) {
2503 broadcastIntentAction = broadcastIntent.getAction();
2504 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002505 ThreadSpanState state = sThisThreadSpanState.get();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002506 if (tr instanceof InstanceCountViolation) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002507 this.numInstances = ((InstanceCountViolation) tr).getNumberOfInstances();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002508 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002509 synchronized (state) {
2510 int spanActiveCount = state.mActiveSize;
2511 if (spanActiveCount > MAX_SPAN_TAGS) {
2512 spanActiveCount = MAX_SPAN_TAGS;
2513 }
2514 if (spanActiveCount != 0) {
2515 this.tags = new String[spanActiveCount];
2516 Span iter = state.mActiveHead;
2517 int index = 0;
2518 while (iter != null && index < spanActiveCount) {
2519 this.tags[index] = iter.mName;
2520 index++;
2521 iter = iter.mNext;
2522 }
2523 }
2524 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002525 }
2526
Kurt Nelson0918c932017-09-07 10:56:56 -07002527 /** Equivalent output to {@link ApplicationErrorReport.CrashInfo#stackTrace}. */
2528 public String getStackTrace() {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002529 if (mStackTrace == null) {
Kurt Nelson0918c932017-09-07 10:56:56 -07002530 StringWriter sw = new StringWriter();
2531 PrintWriter pw = new FastPrintWriter(sw, false, 256);
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002532 mViolation.printStackTrace(pw);
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002533 for (StackTraceElement[] traces : mBinderStack) {
Kurt Nelson0918c932017-09-07 10:56:56 -07002534 pw.append("# via Binder call with stack:\n");
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002535 for (StackTraceElement traceElement : traces) {
2536 pw.append("\tat ");
2537 pw.append(traceElement.toString());
2538 pw.append('\n');
2539 }
Kurt Nelson0918c932017-09-07 10:56:56 -07002540 }
2541 pw.flush();
2542 pw.close();
2543 mStackTrace = sw.toString();
2544 }
2545 return mStackTrace;
2546 }
2547
2548 /**
2549 * Optional message describing this violation.
2550 *
2551 * @hide
2552 */
2553 @TestApi
2554 public String getViolationDetails() {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002555 return mViolation.getMessage();
Kurt Nelson0918c932017-09-07 10:56:56 -07002556 }
2557
2558 /**
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002559 * Policy mask at time of violation.
Kurt Nelson0918c932017-09-07 10:56:56 -07002560 *
2561 * @hide
2562 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002563 @TestApi
2564 public int getPolicyMask() {
2565 return mPolicy;
2566 }
2567
2568 boolean penaltyEnabled(int p) {
2569 return (mPolicy & p) != 0;
Kurt Nelson0918c932017-09-07 10:56:56 -07002570 }
2571
2572 /**
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002573 * Add a {@link Throwable} from the current process that caused the underlying violation. We
2574 * only preserve the stack trace elements.
Kurt Nelson0918c932017-09-07 10:56:56 -07002575 *
2576 * @hide
2577 */
2578 void addLocalStack(Throwable t) {
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002579 mBinderStack.addFirst(t.getStackTrace());
Kurt Nelson0918c932017-09-07 10:56:56 -07002580 }
2581
2582 /**
2583 * Retrieve the type of StrictMode violation.
2584 *
2585 * @hide
2586 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002587 @TestApi
2588 public int getViolationBit() {
2589 if (mViolation instanceof DiskWriteViolation) {
2590 return DETECT_DISK_WRITE;
2591 } else if (mViolation instanceof DiskReadViolation) {
2592 return DETECT_DISK_READ;
2593 } else if (mViolation instanceof NetworkViolation) {
2594 return DETECT_NETWORK;
2595 } else if (mViolation instanceof CustomViolation) {
2596 return DETECT_CUSTOM;
2597 } else if (mViolation instanceof ResourceMismatchViolation) {
2598 return DETECT_RESOURCE_MISMATCH;
Kurt Nelson0e612802017-11-09 17:25:40 -08002599 } else if (mViolation instanceof UnbufferedIoViolation) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002600 return DETECT_UNBUFFERED_IO;
2601 } else if (mViolation instanceof SqliteObjectLeakedViolation) {
2602 return DETECT_VM_CURSOR_LEAKS;
2603 } else if (mViolation instanceof LeakedClosableViolation) {
2604 return DETECT_VM_CLOSABLE_LEAKS;
2605 } else if (mViolation instanceof InstanceCountViolation) {
2606 return DETECT_VM_INSTANCE_LEAKS;
2607 } else if (mViolation instanceof IntentReceiverLeakedViolation) {
2608 return DETECT_VM_REGISTRATION_LEAKS;
2609 } else if (mViolation instanceof ServiceConnectionLeakedViolation) {
2610 return DETECT_VM_REGISTRATION_LEAKS;
2611 } else if (mViolation instanceof FileUriExposedViolation) {
2612 return DETECT_VM_FILE_URI_EXPOSURE;
2613 } else if (mViolation instanceof CleartextNetworkViolation) {
2614 return DETECT_VM_CLEARTEXT_NETWORK;
2615 } else if (mViolation instanceof ContentUriWithoutPermissionViolation) {
2616 return DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION;
2617 } else if (mViolation instanceof UntaggedSocketViolation) {
2618 return DETECT_VM_UNTAGGED_SOCKET;
Narayan Kamathad1b2a92018-03-28 11:29:40 +01002619 } else if (mViolation instanceof NonSdkApiUsedViolation) {
2620 return DETECT_VM_NON_SDK_API_USAGE;
Kurt Nelson0918c932017-09-07 10:56:56 -07002621 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002622 throw new IllegalStateException("missing violation bit");
Kurt Nelson0918c932017-09-07 10:56:56 -07002623 }
2624
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002625 @Override
2626 public int hashCode() {
2627 int result = 17;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002628 if (mViolation != null) {
2629 result = 37 * result + mViolation.hashCode();
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002630 }
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002631 if (numAnimationsRunning != 0) {
2632 result *= 37;
2633 }
2634 if (broadcastIntentAction != null) {
2635 result = 37 * result + broadcastIntentAction.hashCode();
2636 }
2637 if (tags != null) {
2638 for (String tag : tags) {
2639 result = 37 * result + tag.hashCode();
2640 }
2641 }
2642 return result;
2643 }
2644
Kurt Nelson46974a22017-08-30 13:30:26 -07002645 /** Create an instance of ViolationInfo initialized from a Parcel. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002646 public ViolationInfo(Parcel in) {
2647 this(in, false);
2648 }
2649
2650 /**
2651 * Create an instance of ViolationInfo initialized from a Parcel.
2652 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002653 * @param unsetGatheringBit if true, the caller is the root caller and the gathering penalty
2654 * should be removed.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002655 */
2656 public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002657 mViolation = (Violation) in.readSerializable();
Kurt Nelson0918c932017-09-07 10:56:56 -07002658 int binderStackSize = in.readInt();
2659 for (int i = 0; i < binderStackSize; i++) {
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002660 StackTraceElement[] traceElements = new StackTraceElement[in.readInt()];
2661 for (int j = 0; j < traceElements.length; j++) {
2662 StackTraceElement element =
2663 new StackTraceElement(
2664 in.readString(),
2665 in.readString(),
2666 in.readString(),
2667 in.readInt());
2668 traceElements[j] = element;
2669 }
2670 mBinderStack.add(traceElements);
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002671 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002672 int rawPolicy = in.readInt();
2673 if (unsetGatheringBit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002674 mPolicy = rawPolicy & ~PENALTY_GATHER;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002675 } else {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002676 mPolicy = rawPolicy;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002677 }
2678 durationMillis = in.readInt();
2679 violationNumThisLoop = in.readInt();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002680 numAnimationsRunning = in.readInt();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002681 violationUptimeMillis = in.readLong();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002682 numInstances = in.readLong();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002683 broadcastIntentAction = in.readString();
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002684 tags = in.readStringArray();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002685 }
2686
Kurt Nelson46974a22017-08-30 13:30:26 -07002687 /** Save a ViolationInfo instance to a parcel. */
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07002688 @Override
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002689 public void writeToParcel(Parcel dest, int flags) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002690 dest.writeSerializable(mViolation);
Kurt Nelson0918c932017-09-07 10:56:56 -07002691 dest.writeInt(mBinderStack.size());
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002692 for (StackTraceElement[] traceElements : mBinderStack) {
2693 dest.writeInt(traceElements.length);
2694 for (StackTraceElement element : traceElements) {
2695 dest.writeString(element.getClassName());
2696 dest.writeString(element.getMethodName());
2697 dest.writeString(element.getFileName());
2698 dest.writeInt(element.getLineNumber());
2699 }
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002700 }
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002701 int start = dest.dataPosition();
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002702 dest.writeInt(mPolicy);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002703 dest.writeInt(durationMillis);
2704 dest.writeInt(violationNumThisLoop);
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002705 dest.writeInt(numAnimationsRunning);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002706 dest.writeLong(violationUptimeMillis);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002707 dest.writeLong(numInstances);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002708 dest.writeString(broadcastIntentAction);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002709 dest.writeStringArray(tags);
Kurt Nelson46974a22017-08-30 13:30:26 -07002710 int total = dest.dataPosition() - start;
2711 if (Binder.CHECK_PARCEL_SIZE && total > 10 * 1024) {
2712 Slog.d(
2713 TAG,
2714 "VIO: policy="
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002715 + mPolicy
Kurt Nelson46974a22017-08-30 13:30:26 -07002716 + " dur="
2717 + durationMillis
2718 + " numLoop="
2719 + violationNumThisLoop
2720 + " anim="
2721 + numAnimationsRunning
2722 + " uptime="
2723 + violationUptimeMillis
2724 + " numInst="
2725 + numInstances);
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002726 Slog.d(TAG, "VIO: action=" + broadcastIntentAction);
2727 Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags));
Kurt Nelson46974a22017-08-30 13:30:26 -07002728 Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition() - start));
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002729 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002730 }
2731
Kurt Nelson46974a22017-08-30 13:30:26 -07002732 /** Dump a ViolationInfo instance to a Printer. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002733 public void dump(Printer pw, String prefix) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002734 pw.println(prefix + "stackTrace: " + getStackTrace());
2735 pw.println(prefix + "policy: " + mPolicy);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002736 if (durationMillis != -1) {
2737 pw.println(prefix + "durationMillis: " + durationMillis);
2738 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002739 if (numInstances != -1) {
2740 pw.println(prefix + "numInstances: " + numInstances);
2741 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002742 if (violationNumThisLoop != 0) {
2743 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2744 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002745 if (numAnimationsRunning != 0) {
2746 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2747 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002748 pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002749 if (broadcastIntentAction != null) {
2750 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2751 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002752 if (tags != null) {
2753 int index = 0;
2754 for (String tag : tags) {
2755 pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2756 }
2757 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002758 }
2759
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07002760 @Override
2761 public int describeContents() {
2762 return 0;
2763 }
2764
2765 public static final Parcelable.Creator<ViolationInfo> CREATOR =
2766 new Parcelable.Creator<ViolationInfo>() {
2767 @Override
2768 public ViolationInfo createFromParcel(Parcel in) {
2769 return new ViolationInfo(in);
2770 }
2771
2772 @Override
2773 public ViolationInfo[] newArray(int size) {
2774 return new ViolationInfo[size];
2775 }
2776 };
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002777 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002778
Jeff Brown7e442832011-06-10 18:00:16 -07002779 private static final class InstanceTracker {
2780 private static final HashMap<Class<?>, Integer> sInstanceCounts =
2781 new HashMap<Class<?>, Integer>();
2782
2783 private final Class<?> mKlass;
2784
2785 public InstanceTracker(Object instance) {
2786 mKlass = instance.getClass();
2787
2788 synchronized (sInstanceCounts) {
2789 final Integer value = sInstanceCounts.get(mKlass);
2790 final int newValue = value != null ? value + 1 : 1;
2791 sInstanceCounts.put(mKlass, newValue);
2792 }
2793 }
2794
2795 @Override
2796 protected void finalize() throws Throwable {
2797 try {
2798 synchronized (sInstanceCounts) {
2799 final Integer value = sInstanceCounts.get(mKlass);
2800 if (value != null) {
2801 final int newValue = value - 1;
2802 if (newValue > 0) {
2803 sInstanceCounts.put(mKlass, newValue);
2804 } else {
2805 sInstanceCounts.remove(mKlass);
2806 }
2807 }
2808 }
2809 } finally {
2810 super.finalize();
2811 }
2812 }
2813
2814 public static int getInstanceCount(Class<?> klass) {
2815 synchronized (sInstanceCounts) {
2816 final Integer value = sInstanceCounts.get(klass);
2817 return value != null ? value : 0;
2818 }
2819 }
2820 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07002821}