blob: 16d5be4e0c45f1a45231d39f3e1d203f9e62e845 [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;
Pete Gillin22316b42018-02-15 17:17:27 +000037import android.os.strictmode.ExplicitGcViolation;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -070038import android.os.strictmode.FileUriExposedViolation;
39import android.os.strictmode.InstanceCountViolation;
40import android.os.strictmode.IntentReceiverLeakedViolation;
41import android.os.strictmode.LeakedClosableViolation;
42import android.os.strictmode.NetworkViolation;
Narayan Kamathad1b2a92018-03-28 11:29:40 +010043import android.os.strictmode.NonSdkApiUsedViolation;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -070044import android.os.strictmode.ResourceMismatchViolation;
45import android.os.strictmode.ServiceConnectionLeakedViolation;
46import android.os.strictmode.SqliteObjectLeakedViolation;
Kurt Nelson0e612802017-11-09 17:25:40 -080047import android.os.strictmode.UnbufferedIoViolation;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -070048import android.os.strictmode.UntaggedSocketViolation;
49import android.os.strictmode.Violation;
50import android.os.strictmode.WebViewMethodCalledOnWrongThreadViolation;
Dianne Hackborn390517b2013-05-30 15:03:32 -070051import android.util.ArrayMap;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070052import android.util.Log;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070053import android.util.Printer;
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -080054import android.util.Singleton;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070055import android.util.Slog;
Brad Fitzpatrick68044332010-11-22 18:19:48 -080056import android.view.IWindowManager;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070057
Kurt Nelson1981f422017-10-25 13:49:26 -070058import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -070059import com.android.internal.os.BackgroundThread;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070060import com.android.internal.os.RuntimeInit;
Dianne Hackborn8c841092013-06-24 13:46:13 -070061import com.android.internal.util.FastPrintWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080062import com.android.internal.util.HexDump;
63
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070064import dalvik.system.BlockGuard;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -070065import dalvik.system.CloseGuard;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -080066import dalvik.system.VMDebug;
Jeff Sharkey0b558702017-01-26 16:48:01 -070067import dalvik.system.VMRuntime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070068
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070069import java.io.PrintWriter;
70import java.io.StringWriter;
Jeff Sharkey605eb792014-11-04 13:34:06 -080071import java.net.InetAddress;
72import java.net.UnknownHostException;
Kurt Nelson0918c932017-09-07 10:56:56 -070073import java.util.ArrayDeque;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070074import java.util.ArrayList;
Dianne Hackborn73d6a822014-09-29 10:52:47 -070075import java.util.Arrays;
Kurt Nelson0918c932017-09-07 10:56:56 -070076import java.util.Deque;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070077import java.util.HashMap;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -070078import java.util.concurrent.Executor;
79import java.util.concurrent.RejectedExecutionException;
Brad Fitzpatrickbee24872010-11-20 12:09:10 -080080import java.util.concurrent.atomic.AtomicInteger;
Narayan Kamathad1b2a92018-03-28 11:29:40 +010081import java.util.function.Consumer;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070082
Brad Fitzpatrick438d0592010-06-10 12:19:19 -070083/**
Kurt Nelson46974a22017-08-30 13:30:26 -070084 * StrictMode is a developer tool which detects things you might be doing by accident and brings
85 * them to your attention so you can fix them.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070086 *
Kurt Nelson46974a22017-08-30 13:30:26 -070087 * <p>StrictMode is most commonly used to catch accidental disk or network access on the
88 * application's main thread, where UI operations are received and animations take place. Keeping
89 * disk and network operations off the main thread makes for much smoother, more responsive
90 * applications. By keeping your application's main thread responsive, you also prevent <a
91 * href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a> from being shown to
92 * users.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070093 *
Kurt Nelson46974a22017-08-30 13:30:26 -070094 * <p class="note">Note that even though an Android device's disk is often on flash memory, many
95 * devices run a filesystem on top of that memory with very limited concurrency. It's often the case
96 * that almost all disk accesses are fast, but may in individual cases be dramatically slower when
97 * certain I/O is happening in the background from other processes. If possible, it's best to assume
98 * that such things are not fast.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -070099 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700100 * <p>Example code to enable from early in your {@link android.app.Application}, {@link
101 * android.app.Activity}, or other application component's {@link android.app.Application#onCreate}
102 * method:
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700103 *
104 * <pre>
105 * public void onCreate() {
106 * if (DEVELOPER_MODE) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700107 * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
108 * .detectDiskReads()
109 * .detectDiskWrites()
110 * .detectNetwork() // or .detectAll() for all detectable problems
111 * .penaltyLog()
112 * .build());
113 * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -0700114 * .detectLeakedSqlLiteObjects()
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700115 * .detectLeakedClosableObjects()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700116 * .penaltyLog()
117 * .penaltyDeath()
118 * .build());
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700119 * }
120 * super.onCreate();
121 * }
122 * </pre>
123 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700124 * <p>You can decide what should happen when a violation is detected. For example, using {@link
125 * ThreadPolicy.Builder#penaltyLog} you can watch the output of <code>adb logcat</code> while you
126 * use your application to see the violations as they happen.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700127 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700128 * <p>If you find violations that you feel are problematic, there are a variety of tools to help
129 * solve them: threads, {@link android.os.Handler}, {@link android.os.AsyncTask}, {@link
130 * android.app.IntentService}, etc. But don't feel compelled to fix everything that StrictMode
131 * finds. In particular, many cases of disk access are often necessary during the normal activity
132 * lifecycle. Use StrictMode to find things you did by accident. Network requests on the UI thread
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700133 * are almost always a problem, though.
134 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700135 * <p class="note">StrictMode is not a security mechanism and is not guaranteed to find all disk or
136 * network accesses. While it does propagate its state across process boundaries when doing {@link
137 * android.os.Binder} calls, it's still ultimately a best effort mechanism. Notably, disk or network
138 * access from JNI calls won't necessarily trigger it. Future versions of Android may catch more (or
139 * fewer) operations, so you should never leave StrictMode enabled in applications distributed on
140 * Google Play.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700141 */
142public final class StrictMode {
143 private static final String TAG = "StrictMode";
Brad Fitzpatrick82829ef2010-11-18 18:25:08 -0800144 private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700145
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800146 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700147 * Boolean system property to disable strict mode checks outright. Set this to 'true' to force
148 * disable; 'false' has no effect on other enable/disable policy.
149 *
Christopher Tatebc6f0ce2011-11-03 12:18:43 -0700150 * @hide
151 */
152 public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
153
154 /**
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -0800155 * The boolean system property to control screen flashes on violations.
156 *
157 * @hide
158 */
159 public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
160
Jeff Sharkey605eb792014-11-04 13:34:06 -0800161 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700162 * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK} in {@link
163 * VmPolicy.Builder#detectAll()}. Apps can still always opt-into detection using {@link
164 * VmPolicy.Builder#detectCleartextNetwork()}.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800165 */
Jeff Sharkey2e571642015-01-22 11:51:43 -0700166 private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.clear";
Jeff Sharkey605eb792014-11-04 13:34:06 -0800167
Jeff Sharkey89182982017-11-01 19:02:56 -0600168 /**
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700169 * Quick feature-flag that can be used to disable the defaults provided by {@link
170 * #initThreadDefaults(ApplicationInfo)} and {@link #initVmDefaults(ApplicationInfo)}.
Jeff Sharkey89182982017-11-01 19:02:56 -0600171 */
Jeff Sharkey617e1132017-11-03 17:28:45 -0600172 private static final boolean DISABLE = false;
Jeff Sharkey89182982017-11-01 19:02:56 -0600173
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700174 // Only apply VM penalties for the same violation at this interval.
175 private static final long MIN_VM_INTERVAL_MS = 1000;
176
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700177 // Only log a duplicate stack trace to the logs every second.
178 private static final long MIN_LOG_INTERVAL_MS = 1000;
179
180 // Only show an annoying dialog at most every 30 seconds
181 private static final long MIN_DIALOG_INTERVAL_MS = 30000;
182
Brad Fitzpatricke7520d82010-11-10 18:08:36 -0800183 // How many Span tags (e.g. animations) to report.
184 private static final int MAX_SPAN_TAGS = 20;
185
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -0700186 // How many offending stacks to keep track of (and time) per loop
187 // of the Looper.
188 private static final int MAX_OFFENSES_PER_LOOP = 10;
189
Jeff Sharkey605eb792014-11-04 13:34:06 -0800190 // Byte 1: Thread-policy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700191
Kurt Nelson46974a22017-08-30 13:30:26 -0700192 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700193 @TestApi public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700194
Kurt Nelson46974a22017-08-30 13:30:26 -0700195 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700196 @TestApi public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -0700197
Kurt Nelson46974a22017-08-30 13:30:26 -0700198 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700199 @TestApi public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700200
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800201 /**
202 * For StrictMode.noteSlowCall()
203 *
204 * @hide
205 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700206 @TestApi public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800207
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800208 /**
209 * For StrictMode.noteResourceMismatch()
210 *
211 * @hide
212 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700213 @TestApi public static final int DETECT_RESOURCE_MISMATCH = 0x10; // for ThreadPolicy
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800214
Kurt Nelson46974a22017-08-30 13:30:26 -0700215 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700216 @TestApi public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100217
Pete Gillin22316b42018-02-15 17:17:27 +0000218 /** @hide */
219 public static final int DETECT_EXPLICIT_GC = 0x40; // for ThreadPolicy
220
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800221 private static final int ALL_THREAD_DETECT_BITS =
Kurt Nelson46974a22017-08-30 13:30:26 -0700222 DETECT_DISK_WRITE
223 | DETECT_DISK_READ
224 | DETECT_NETWORK
225 | DETECT_CUSTOM
226 | DETECT_RESOURCE_MISMATCH
Pete Gillin22316b42018-02-15 17:17:27 +0000227 | DETECT_UNBUFFERED_IO
228 | DETECT_EXPLICIT_GC;
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800229
Jeff Sharkey605eb792014-11-04 13:34:06 -0800230 // Byte 2: Process-policy
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700231
232 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700233 * Note, a "VM_" bit, not thread.
Kurt Nelson46974a22017-08-30 13:30:26 -0700234 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700235 * @hide
236 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700237 @TestApi public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8; // for VmPolicy
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700238
239 /**
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700240 * Note, a "VM_" bit, not thread.
Kurt Nelson46974a22017-08-30 13:30:26 -0700241 *
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700242 * @hide
243 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700244 @TestApi public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8; // for VmPolicy
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800245
246 /**
247 * Note, a "VM_" bit, not thread.
Kurt Nelson46974a22017-08-30 13:30:26 -0700248 *
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800249 * @hide
250 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700251 @TestApi public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8; // for VmPolicy
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700252
Kurt Nelson46974a22017-08-30 13:30:26 -0700253 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700254 @TestApi public static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8; // for VmPolicy
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800255
Kurt Nelson46974a22017-08-30 13:30:26 -0700256 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700257 @TestApi public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8; // for VmPolicy
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800258
Kurt Nelson46974a22017-08-30 13:30:26 -0700259 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700260 @TestApi public static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8; // for VmPolicy
Jeff Sharkey605eb792014-11-04 13:34:06 -0800261
Kurt Nelson46974a22017-08-30 13:30:26 -0700262 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700263 @TestApi public static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8; // for VmPolicy
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700264
Kurt Nelson46974a22017-08-30 13:30:26 -0700265 /** @hide */
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -0700266 @TestApi
267 public static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -0700268
Kurt Nelson46974a22017-08-30 13:30:26 -0700269 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700270 @TestApi public static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy
Jeff Sharkey619a5112017-01-19 11:55:54 -0700271
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100272 /** @hide */
273 @TestApi public static final int DETECT_VM_NON_SDK_API_USAGE = 0x40 << 24; // for VmPolicy
274
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800275 private static final int ALL_VM_DETECT_BITS =
Kurt Nelson46974a22017-08-30 13:30:26 -0700276 DETECT_VM_CURSOR_LEAKS
277 | DETECT_VM_CLOSABLE_LEAKS
278 | DETECT_VM_ACTIVITY_LEAKS
279 | DETECT_VM_INSTANCE_LEAKS
280 | DETECT_VM_REGISTRATION_LEAKS
281 | DETECT_VM_FILE_URI_EXPOSURE
282 | DETECT_VM_CLEARTEXT_NETWORK
283 | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100284 | DETECT_VM_UNTAGGED_SOCKET
285 | DETECT_VM_NON_SDK_API_USAGE;
286
Jeff Sharkey605eb792014-11-04 13:34:06 -0800287
288 // Byte 3: Penalty
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800289
Jeff Sharkey344744b2016-01-28 19:03:30 -0700290 /** {@hide} */
Kurt Nelson46974a22017-08-30 13:30:26 -0700291 public static final int PENALTY_LOG = 0x01 << 16; // normal android.util.Log
Jeff Sharkey344744b2016-01-28 19:03:30 -0700292 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800293 public static final int PENALTY_DIALOG = 0x02 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700294 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800295 public static final int PENALTY_DEATH = 0x04 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700296 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800297 public static final int PENALTY_FLASH = 0x10 << 16;
Jeff Sharkey344744b2016-01-28 19:03:30 -0700298 /** {@hide} */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800299 public static final int PENALTY_DROPBOX = 0x20 << 16;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700300
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700301 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700302 * Non-public penalty mode which overrides all the other penalty bits and signals that we're in
303 * a Binder call and we should ignore the other penalty bits and instead serialize back all our
304 * offending stack traces to the caller to ultimately handle in the originating process.
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700305 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700306 * <p>This must be kept in sync with the constant in libs/binder/Parcel.cpp
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -0700307 *
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700308 * @hide
309 */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800310 public static final int PENALTY_GATHER = 0x40 << 16;
311
Jeff Sharkey344744b2016-01-28 19:03:30 -0700312 // Byte 4: Special cases
313
314 /**
315 * Death when network traffic is detected on main thread.
316 *
317 * @hide
318 */
319 public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
320
Jeff Sharkey605eb792014-11-04 13:34:06 -0800321 /**
322 * Death when cleartext network traffic is detected.
323 *
324 * @hide
325 */
Jeff Sharkey344744b2016-01-28 19:03:30 -0700326 public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
327
328 /**
329 * Death when file exposure is detected.
330 *
331 * @hide
332 */
333 public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
Brad Fitzpatrick727de402010-07-07 16:06:39 -0700334
Jeff Sharkey619a5112017-01-19 11:55:54 -0700335 // CAUTION: we started stealing the top bits of Byte 4 for VM above
336
Kurt Nelson46974a22017-08-30 13:30:26 -0700337 /** Mask of all the penalty bits valid for thread policies. */
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800338 private static final int THREAD_PENALTY_MASK =
Kurt Nelson46974a22017-08-30 13:30:26 -0700339 PENALTY_LOG
340 | PENALTY_DIALOG
341 | PENALTY_DEATH
342 | PENALTY_DROPBOX
343 | PENALTY_GATHER
344 | PENALTY_DEATH_ON_NETWORK
345 | PENALTY_FLASH;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -0700346
Kurt Nelson46974a22017-08-30 13:30:26 -0700347 /** Mask of all the penalty bits valid for VM policies. */
348 private static final int VM_PENALTY_MASK =
349 PENALTY_LOG
350 | PENALTY_DEATH
351 | PENALTY_DROPBOX
352 | PENALTY_DEATH_ON_CLEARTEXT_NETWORK
353 | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800354
Jeff Sharkey605eb792014-11-04 13:34:06 -0800355 /** {@hide} */
356 public static final int NETWORK_POLICY_ACCEPT = 0;
357 /** {@hide} */
358 public static final int NETWORK_POLICY_LOG = 1;
359 /** {@hide} */
360 public static final int NETWORK_POLICY_REJECT = 2;
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -0800361
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800362 // TODO: wrap in some ImmutableHashMap thing.
363 // Note: must be before static initialization of sVmPolicy.
Kurt Nelson46974a22017-08-30 13:30:26 -0700364 private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP =
365 new HashMap<Class, Integer>();
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800366
Kurt Nelson2c883f32017-09-01 10:52:45 -0700367 /** The current VmPolicy in effect. */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800368 private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700369
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600370 /** {@hide} */
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -0600371 @TestApi
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700372 public interface ViolationLogger {
373
374 /** Called when penaltyLog is enabled and a violation needs logging. */
375 void log(ViolationInfo info);
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600376 }
377
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700378 private static final ViolationLogger LOGCAT_LOGGER =
379 info -> {
380 String msg;
381 if (info.durationMillis != -1) {
382 msg = "StrictMode policy violation; ~duration=" + info.durationMillis + " ms:";
383 } else {
384 msg = "StrictMode policy violation:";
385 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -0700386 Log.d(TAG, msg + " " + info.getStackTrace());
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700387 };
388
389 private static volatile ViolationLogger sLogger = LOGCAT_LOGGER;
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600390
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700391 private static final ThreadLocal<OnThreadViolationListener> sThreadViolationListener =
392 new ThreadLocal<>();
393 private static final ThreadLocal<Executor> sThreadViolationExecutor = new ThreadLocal<>();
394
395 /**
396 * When #{@link ThreadPolicy.Builder#penaltyListener} is enabled, the listener is called on the
397 * provided executor when a Thread violation occurs.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700398 */
399 public interface OnThreadViolationListener {
400 /** Called on a thread policy violation. */
401 void onThreadViolation(Violation v);
402 }
403
404 /**
405 * When #{@link VmPolicy.Builder#penaltyListener} is enabled, the listener is called on the
406 * provided executor when a VM violation occurs.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700407 */
408 public interface OnVmViolationListener {
409 /** Called on a VM policy violation. */
410 void onVmViolation(Violation v);
411 }
412
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600413 /** {@hide} */
Jeff Sharkeyddc3bfd2017-06-26 19:38:56 -0600414 @TestApi
Kurt Nelson7d5c07a2017-09-07 16:43:45 -0700415 public static void setViolationLogger(ViolationLogger listener) {
416 if (listener == null) {
417 listener = LOGCAT_LOGGER;
418 }
419 sLogger = listener;
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -0600420 }
421
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800422 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700423 * The number of threads trying to do an async dropbox write. Just to limit ourselves out of
424 * paranoia.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -0800425 */
426 private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
427
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100428 /**
429 * Callback supplied to dalvik / libcore to get informed of usages of java API that are not
430 * a part of the public SDK.
431 */
432 private static final Consumer<String> sNonSdkApiUsageConsumer =
433 message -> onVmPolicyViolation(new NonSdkApiUsedViolation(message));
434
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700435 private StrictMode() {}
436
437 /**
438 * {@link StrictMode} policy applied to a certain thread.
439 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700440 * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy can be retrieved
441 * with {@link #getThreadPolicy}.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700442 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700443 * <p>Note that multiple penalties may be provided and they're run in order from least to most
444 * severe (logging before process death, for example). There's currently no mechanism to choose
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700445 * different penalties for different detected actions.
446 */
447 public static final class ThreadPolicy {
Kurt Nelson46974a22017-08-30 13:30:26 -0700448 /** The default, lax policy which doesn't catch anything. */
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700449 public static final ThreadPolicy LAX = new ThreadPolicy(0, null, null);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700450
451 final int mask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700452 final OnThreadViolationListener mListener;
453 final Executor mCallbackExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700454
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700455 private ThreadPolicy(int mask, OnThreadViolationListener listener, Executor executor) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700456 this.mask = mask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700457 mListener = listener;
458 mCallbackExecutor = executor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700459 }
460
461 @Override
462 public String toString() {
463 return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
464 }
465
466 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700467 * Creates {@link ThreadPolicy} instances. Methods whose names start with {@code detect}
468 * specify what problems we should look for. Methods whose names start with {@code penalty}
469 * specify what we should do when we detect a problem.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700470 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700471 * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently
472 * order is insignificant: all penalties apply to all detected problems.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700473 *
474 * <p>For example, detect everything and log anything that's found:
Kurt Nelson46974a22017-08-30 13:30:26 -0700475 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700476 * <pre>
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800477 * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700478 * .detectAll()
479 * .penaltyLog()
480 * .build();
Brad Fitzpatrick320274c2010-12-13 14:07:39 -0800481 * StrictMode.setThreadPolicy(policy);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700482 * </pre>
483 */
484 public static final class Builder {
485 private int mMask = 0;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700486 private OnThreadViolationListener mListener;
487 private Executor mExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700488
489 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700490 * Create a Builder that detects nothing and has no violations. (but note that {@link
491 * #build} will default to enabling {@link #penaltyLog} if no other penalties are
492 * specified)
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700493 */
494 public Builder() {
495 mMask = 0;
496 }
497
Kurt Nelson46974a22017-08-30 13:30:26 -0700498 /** Initialize a Builder from an existing ThreadPolicy. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700499 public Builder(ThreadPolicy policy) {
500 mMask = policy.mask;
Kurt Nelson7a8804a2018-02-27 16:45:27 -0800501 mListener = policy.mListener;
502 mExecutor = policy.mCallbackExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700503 }
504
505 /**
506 * Detect everything that's potentially suspect.
507 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700508 * <p>As of the Gingerbread release this includes network and disk operations but will
509 * likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700510 */
511 public Builder detectAll() {
Jeff Sharkey0b558702017-01-26 16:48:01 -0700512 detectDiskReads();
513 detectDiskWrites();
514 detectNetwork();
515
516 final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
517 if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
518 detectCustomSlowCalls();
519 }
520 if (targetSdk >= Build.VERSION_CODES.M) {
521 detectResourceMismatches();
522 }
523 if (targetSdk >= Build.VERSION_CODES.O) {
524 detectUnbufferedIo();
525 }
526 return this;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700527 }
528
Kurt Nelson46974a22017-08-30 13:30:26 -0700529 /** Disable the detection of everything. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700530 public Builder permitAll() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800531 return disable(ALL_THREAD_DETECT_BITS);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700532 }
533
Kurt Nelson46974a22017-08-30 13:30:26 -0700534 /** Enable detection of network operations. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700535 public Builder detectNetwork() {
536 return enable(DETECT_NETWORK);
537 }
538
Kurt Nelson46974a22017-08-30 13:30:26 -0700539 /** Disable detection of network operations. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700540 public Builder permitNetwork() {
541 return disable(DETECT_NETWORK);
542 }
543
Kurt Nelson46974a22017-08-30 13:30:26 -0700544 /** Enable detection of disk reads. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700545 public Builder detectDiskReads() {
546 return enable(DETECT_DISK_READ);
547 }
548
Kurt Nelson46974a22017-08-30 13:30:26 -0700549 /** Disable detection of disk reads. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700550 public Builder permitDiskReads() {
551 return disable(DETECT_DISK_READ);
552 }
553
Kurt Nelson46974a22017-08-30 13:30:26 -0700554 /** Enable detection of slow calls. */
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800555 public Builder detectCustomSlowCalls() {
556 return enable(DETECT_CUSTOM);
557 }
558
Kurt Nelson46974a22017-08-30 13:30:26 -0700559 /** Disable detection of slow calls. */
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800560 public Builder permitCustomSlowCalls() {
Qi Wang097fbf22012-07-13 09:26:03 +0800561 return disable(DETECT_CUSTOM);
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -0800562 }
563
Kurt Nelson46974a22017-08-30 13:30:26 -0700564 /** Disable detection of mismatches between defined resource types and getter calls. */
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800565 public Builder permitResourceMismatches() {
566 return disable(DETECT_RESOURCE_MISMATCH);
567 }
568
Kurt Nelson46974a22017-08-30 13:30:26 -0700569 /** Detect unbuffered input/output operations. */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100570 public Builder detectUnbufferedIo() {
571 return enable(DETECT_UNBUFFERED_IO);
572 }
573
Kurt Nelson46974a22017-08-30 13:30:26 -0700574 /** Disable detection of unbuffered input/output operations. */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +0100575 public Builder permitUnbufferedIo() {
576 return disable(DETECT_UNBUFFERED_IO);
577 }
578
579 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700580 * Enables detection of mismatches between defined resource types and getter calls.
581 *
582 * <p>This helps detect accidental type mismatches and potentially expensive type
583 * conversions when obtaining typed resources.
584 *
585 * <p>For example, a strict mode violation would be thrown when calling {@link
586 * android.content.res.TypedArray#getInt(int, int)} on an index that contains a
587 * String-type resource. If the string value can be parsed as an integer, this method
588 * call will return a value without crashing; however, the developer should format the
589 * resource as an integer to avoid unnecessary type conversion.
Alan Viverette6bbb47b2015-01-05 18:12:44 -0800590 */
591 public Builder detectResourceMismatches() {
592 return enable(DETECT_RESOURCE_MISMATCH);
593 }
594
Kurt Nelson46974a22017-08-30 13:30:26 -0700595 /** Enable detection of disk writes. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700596 public Builder detectDiskWrites() {
597 return enable(DETECT_DISK_WRITE);
598 }
599
Kurt Nelson46974a22017-08-30 13:30:26 -0700600 /** Disable detection of disk writes. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700601 public Builder permitDiskWrites() {
602 return disable(DETECT_DISK_WRITE);
603 }
604
605 /**
Pete Gillin22316b42018-02-15 17:17:27 +0000606 * Detect explicit GC requests, i.e. calls to Runtime.gc().
607 *
608 * @hide
609 */
610 public Builder detectExplicitGc() {
611 // TODO(b/3400644): Un-hide this for next API update
612 // TODO(b/3400644): Un-hide ExplicitGcViolation for next API update
613 // TODO(b/3400644): Make DETECT_EXPLICIT_GC a @TestApi for next API update
614 // TODO(b/3400644): Call this from detectAll in next API update
615 return enable(DETECT_EXPLICIT_GC);
616 }
617
618 /**
619 * Disable detection of explicit GC requests, i.e. calls to Runtime.gc().
620 *
621 * @hide
622 */
623 public Builder permitExplicitGc() {
624 // TODO(b/3400644): Un-hide this for next API update
625 return disable(DETECT_EXPLICIT_GC);
626 }
627
628 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700629 * Show an annoying dialog to the developer on detected violations, rate-limited to be
630 * only a little annoying.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700631 */
632 public Builder penaltyDialog() {
633 return enable(PENALTY_DIALOG);
634 }
635
636 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700637 * Crash the whole process on violation. This penalty runs at the end of all enabled
638 * penalties so you'll still get see logging or other violations before the process
639 * dies.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700640 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700641 * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies to disk reads, disk writes,
642 * and network usage if their corresponding detect flags are set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700643 */
644 public Builder penaltyDeath() {
645 return enable(PENALTY_DEATH);
646 }
647
648 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700649 * Crash the whole process on any network usage. Unlike {@link #penaltyDeath}, this
650 * penalty runs <em>before</em> anything else. You must still have called {@link
651 * #detectNetwork} to enable this.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -0700652 *
653 * <p>In the Honeycomb or later SDKs, this is on by default.
654 */
655 public Builder penaltyDeathOnNetwork() {
656 return enable(PENALTY_DEATH_ON_NETWORK);
657 }
658
Kurt Nelson46974a22017-08-30 13:30:26 -0700659 /** Flash the screen during a violation. */
Brad Fitzpatrick68044332010-11-22 18:19:48 -0800660 public Builder penaltyFlashScreen() {
661 return enable(PENALTY_FLASH);
662 }
663
Kurt Nelson46974a22017-08-30 13:30:26 -0700664 /** Log detected violations to the system log. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700665 public Builder penaltyLog() {
666 return enable(PENALTY_LOG);
667 }
668
669 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700670 * Enable detected violations log a stacktrace and timing data to the {@link
671 * android.os.DropBoxManager DropBox} on policy violation. Intended mostly for platform
672 * integrators doing beta user field data collection.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700673 */
674 public Builder penaltyDropBox() {
675 return enable(PENALTY_DROPBOX);
676 }
677
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700678 /**
679 * Call #{@link OnThreadViolationListener#onThreadViolation(Violation)} on specified
680 * executor every violation.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700681 */
682 public Builder penaltyListener(
Kurt Nelson72534b72018-02-22 11:21:15 -0800683 @NonNull Executor executor, @NonNull OnThreadViolationListener listener) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700684 if (executor == null) {
685 throw new NullPointerException("executor must not be null");
686 }
687 mListener = listener;
688 mExecutor = executor;
689 return this;
690 }
691
Kurt Nelson72534b72018-02-22 11:21:15 -0800692 /** @removed */
693 public Builder penaltyListener(
694 @NonNull OnThreadViolationListener listener, @NonNull Executor executor) {
695 return penaltyListener(executor, listener);
696 }
697
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700698 private Builder enable(int bit) {
699 mMask |= bit;
700 return this;
701 }
702
703 private Builder disable(int bit) {
704 mMask &= ~bit;
705 return this;
706 }
707
708 /**
709 * Construct the ThreadPolicy instance.
710 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700711 * <p>Note: if no penalties are enabled before calling <code>build</code>, {@link
712 * #penaltyLog} is implicitly set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700713 */
714 public ThreadPolicy build() {
715 // If there are detection bits set but no violation bits
716 // set, enable simple logging.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700717 if (mListener == null
718 && mMask != 0
Kurt Nelson46974a22017-08-30 13:30:26 -0700719 && (mMask
720 & (PENALTY_DEATH
721 | PENALTY_LOG
722 | PENALTY_DROPBOX
723 | PENALTY_DIALOG))
724 == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700725 penaltyLog();
726 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700727 return new ThreadPolicy(mMask, mListener, mExecutor);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700728 }
729 }
730 }
731
732 /**
733 * {@link StrictMode} policy applied to all threads in the virtual machine's process.
734 *
735 * <p>The policy is enabled by {@link #setVmPolicy}.
736 */
737 public static final class VmPolicy {
Kurt Nelson46974a22017-08-30 13:30:26 -0700738 /** The default, lax policy which doesn't catch anything. */
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700739 public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP, null, null);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700740
741 final int mask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700742 final OnVmViolationListener mListener;
743 final Executor mCallbackExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700744
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800745 // Map from class to max number of allowed instances in memory.
746 final HashMap<Class, Integer> classInstanceLimit;
747
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700748 private VmPolicy(
749 int mask,
750 HashMap<Class, Integer> classInstanceLimit,
751 OnVmViolationListener listener,
752 Executor executor) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800753 if (classInstanceLimit == null) {
754 throw new NullPointerException("classInstanceLimit == null");
755 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700756 this.mask = mask;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800757 this.classInstanceLimit = classInstanceLimit;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700758 mListener = listener;
759 mCallbackExecutor = executor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700760 }
761
762 @Override
763 public String toString() {
764 return "[StrictMode.VmPolicy; mask=" + mask + "]";
765 }
766
767 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700768 * Creates {@link VmPolicy} instances. Methods whose names start with {@code detect} specify
769 * what problems we should look for. Methods whose names start with {@code penalty} specify
770 * what we should do when we detect a problem.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700771 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700772 * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently
773 * order is insignificant: all penalties apply to all detected problems.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700774 *
775 * <p>For example, detect everything and log anything that's found:
Kurt Nelson46974a22017-08-30 13:30:26 -0700776 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700777 * <pre>
778 * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
779 * .detectAll()
780 * .penaltyLog()
781 * .build();
782 * StrictMode.setVmPolicy(policy);
783 * </pre>
784 */
785 public static final class Builder {
786 private int mMask;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700787 private OnVmViolationListener mListener;
788 private Executor mExecutor;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700789
Kurt Nelson46974a22017-08-30 13:30:26 -0700790 private HashMap<Class, Integer> mClassInstanceLimit; // null until needed
791 private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800792
793 public Builder() {
794 mMask = 0;
795 }
796
Kurt Nelson46974a22017-08-30 13:30:26 -0700797 /** Build upon an existing VmPolicy. */
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800798 public Builder(VmPolicy base) {
799 mMask = base.mask;
800 mClassInstanceLimitNeedCow = true;
801 mClassInstanceLimit = base.classInstanceLimit;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -0700802 mListener = base.mListener;
803 mExecutor = base.mCallbackExecutor;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800804 }
805
806 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700807 * Set an upper bound on how many instances of a class can be in memory at once. Helps
808 * to prevent object leaks.
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800809 */
810 public Builder setClassInstanceLimit(Class klass, int instanceLimit) {
811 if (klass == null) {
812 throw new NullPointerException("klass == null");
813 }
814 if (mClassInstanceLimitNeedCow) {
Kurt Nelson46974a22017-08-30 13:30:26 -0700815 if (mClassInstanceLimit.containsKey(klass)
816 && mClassInstanceLimit.get(klass) == instanceLimit) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800817 // no-op; don't break COW
818 return this;
819 }
820 mClassInstanceLimitNeedCow = false;
821 mClassInstanceLimit = (HashMap<Class, Integer>) mClassInstanceLimit.clone();
822 } else if (mClassInstanceLimit == null) {
823 mClassInstanceLimit = new HashMap<Class, Integer>();
824 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800825 mMask |= DETECT_VM_INSTANCE_LEAKS;
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800826 mClassInstanceLimit.put(klass, instanceLimit);
827 return this;
828 }
829
Kurt Nelson46974a22017-08-30 13:30:26 -0700830 /** Detect leaks of {@link android.app.Activity} subclasses. */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -0800831 public Builder detectActivityLeaks() {
Brad Fitzpatrick75803572011-01-13 14:21:03 -0800832 return enable(DETECT_VM_ACTIVITY_LEAKS);
833 }
834
Jeff Sharkey89182982017-11-01 19:02:56 -0600835 /** @hide */
836 public Builder permitActivityLeaks() {
837 return disable(DETECT_VM_ACTIVITY_LEAKS);
838 }
839
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700840 /**
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100841 * Detect reflective usage of APIs that are not part of the public Android SDK.
842 */
843 public Builder detectNonSdkApiUsage() {
844 return enable(DETECT_VM_NON_SDK_API_USAGE);
845 }
846
847 /**
848 * Permit reflective usage of APIs that are not part of the public Android SDK. Note
849 * that this <b>only</b> affects {@code StrictMode}, the underlying runtime may
850 * continue to restrict or warn on access to methods that are not part of the
851 * public SDK.
852 */
853 public Builder permitNonSdkApiUsage() {
854 return disable(DETECT_VM_NON_SDK_API_USAGE);
855 }
856
857 /**
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700858 * Detect everything that's potentially suspect.
859 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700860 * <p>In the Honeycomb release this includes leaks of SQLite cursors, Activities, and
861 * other closable objects but will likely expand in future releases.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700862 */
863 public Builder detectAll() {
Jeff Sharkey0b558702017-01-26 16:48:01 -0700864 detectLeakedSqlLiteObjects();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800865
Jeff Sharkey0b558702017-01-26 16:48:01 -0700866 final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
867 if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
868 detectActivityLeaks();
869 detectLeakedClosableObjects();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800870 }
Jeff Sharkey0b558702017-01-26 16:48:01 -0700871 if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) {
872 detectLeakedRegistrationObjects();
873 }
874 if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
875 detectFileUriExposure();
876 }
877 if (targetSdk >= Build.VERSION_CODES.M) {
878 // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have
879 // facility for apps to mark sockets that should be ignored
880 if (SystemProperties.getBoolean(CLEARTEXT_PROPERTY, false)) {
881 detectCleartextNetwork();
882 }
883 }
884 if (targetSdk >= Build.VERSION_CODES.O) {
885 detectContentUriWithoutPermission();
886 detectUntaggedSockets();
887 }
Narayan Kamathad1b2a92018-03-28 11:29:40 +0100888
889 // TODO: Decide whether to detect non SDK API usage beyond a certain API level.
Jeff Sharkey0b558702017-01-26 16:48:01 -0700890 return this;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700891 }
892
893 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700894 * Detect when an {@link android.database.sqlite.SQLiteCursor} or other SQLite object is
895 * finalized without having been closed.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700896 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700897 * <p>You always want to explicitly close your SQLite cursors to avoid unnecessary
898 * database contention and temporary memory leaks.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -0700899 */
900 public Builder detectLeakedSqlLiteObjects() {
901 return enable(DETECT_VM_CURSOR_LEAKS);
902 }
903
904 /**
Kurt Nelsond25bd9f2017-09-14 11:36:34 -0700905 * Detect when an {@link java.io.Closeable} or other object with an explicit termination
Kurt Nelson46974a22017-08-30 13:30:26 -0700906 * method is finalized without having been closed.
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700907 *
Kurt Nelson46974a22017-08-30 13:30:26 -0700908 * <p>You always want to explicitly close such objects to avoid unnecessary resources
909 * leaks.
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700910 */
911 public Builder detectLeakedClosableObjects() {
912 return enable(DETECT_VM_CLOSABLE_LEAKS);
913 }
914
915 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700916 * Detect when a {@link BroadcastReceiver} or {@link ServiceConnection} is leaked during
917 * {@link Context} teardown.
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800918 */
919 public Builder detectLeakedRegistrationObjects() {
920 return enable(DETECT_VM_REGISTRATION_LEAKS);
921 }
922
923 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700924 * Detect when the calling application exposes a {@code file://} {@link android.net.Uri}
925 * to another app.
926 *
927 * <p>This exposure is discouraged since the receiving app may not have access to the
928 * shared path. For example, the receiving app may not have requested the {@link
929 * android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime permission, or the
930 * platform may be sharing the {@link android.net.Uri} across user profile boundaries.
931 *
932 * <p>Instead, apps should use {@code content://} Uris so the platform can extend
933 * temporary permission for the receiving app to access the resource.
Jeff Sharkey344744b2016-01-28 19:03:30 -0700934 *
935 * @see android.support.v4.content.FileProvider
936 * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
Jeff Sharkeya14acd22013-04-02 18:27:45 -0700937 */
938 public Builder detectFileUriExposure() {
939 return enable(DETECT_VM_FILE_URI_EXPOSURE);
940 }
941
942 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700943 * Detect any network traffic from the calling app which is not wrapped in SSL/TLS. This
944 * can help you detect places that your app is inadvertently sending cleartext data
945 * across the network.
946 *
947 * <p>Using {@link #penaltyDeath()} or {@link #penaltyDeathOnCleartextNetwork()} will
948 * block further traffic on that socket to prevent accidental data leakage, in addition
949 * to crashing your process.
950 *
951 * <p>Using {@link #penaltyDropBox()} will log the raw contents of the packet that
952 * triggered the violation.
953 *
954 * <p>This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it may be subject to
955 * false positives, such as when STARTTLS protocols or HTTP proxies are used.
Jeff Sharkey605eb792014-11-04 13:34:06 -0800956 */
957 public Builder detectCleartextNetwork() {
958 return enable(DETECT_VM_CLEARTEXT_NETWORK);
959 }
960
961 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700962 * Detect when the calling application sends a {@code content://} {@link
963 * android.net.Uri} to another app without setting {@link
964 * Intent#FLAG_GRANT_READ_URI_PERMISSION} or {@link
965 * Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
966 *
967 * <p>Forgetting to include one or more of these flags when sending an intent is
968 * typically an app bug.
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -0700969 *
970 * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
971 * @see Intent#FLAG_GRANT_WRITE_URI_PERMISSION
972 */
973 public Builder detectContentUriWithoutPermission() {
974 return enable(DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION);
975 }
976
977 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700978 * Detect any sockets in the calling app which have not been tagged using {@link
979 * TrafficStats}. Tagging sockets can help you investigate network usage inside your
980 * app, such as a narrowing down heavy usage to a specific library or component.
981 *
982 * <p>This currently does not detect sockets created in native code.
Jeff Sharkey619a5112017-01-19 11:55:54 -0700983 *
984 * @see TrafficStats#setThreadStatsTag(int)
985 * @see TrafficStats#tagSocket(java.net.Socket)
986 * @see TrafficStats#tagDatagramSocket(java.net.DatagramSocket)
987 */
988 public Builder detectUntaggedSockets() {
989 return enable(DETECT_VM_UNTAGGED_SOCKET);
990 }
991
Jeff Sharkey89182982017-11-01 19:02:56 -0600992 /** @hide */
993 public Builder permitUntaggedSockets() {
994 return disable(DETECT_VM_UNTAGGED_SOCKET);
995 }
996
Jeff Sharkey619a5112017-01-19 11:55:54 -0700997 /**
Kurt Nelson46974a22017-08-30 13:30:26 -0700998 * Crashes the whole process on violation. This penalty runs at the end of all enabled
999 * penalties so you'll still get your logging or other violations before the process
1000 * dies.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001001 */
1002 public Builder penaltyDeath() {
1003 return enable(PENALTY_DEATH);
1004 }
1005
1006 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001007 * Crashes the whole process when cleartext network traffic is detected.
Jeff Sharkey605eb792014-11-04 13:34:06 -08001008 *
1009 * @see #detectCleartextNetwork()
Jeff Sharkey605eb792014-11-04 13:34:06 -08001010 */
1011 public Builder penaltyDeathOnCleartextNetwork() {
1012 return enable(PENALTY_DEATH_ON_CLEARTEXT_NETWORK);
1013 }
1014
1015 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001016 * Crashes the whole process when a {@code file://} {@link android.net.Uri} is exposed
1017 * beyond this app.
Jeff Sharkey344744b2016-01-28 19:03:30 -07001018 *
1019 * @see #detectFileUriExposure()
1020 */
1021 public Builder penaltyDeathOnFileUriExposure() {
1022 return enable(PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
1023 }
1024
Kurt Nelson46974a22017-08-30 13:30:26 -07001025 /** Log detected violations to the system log. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001026 public Builder penaltyLog() {
1027 return enable(PENALTY_LOG);
1028 }
1029
1030 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001031 * Enable detected violations log a stacktrace and timing data to the {@link
1032 * android.os.DropBoxManager DropBox} on policy violation. Intended mostly for platform
1033 * integrators doing beta user field data collection.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001034 */
1035 public Builder penaltyDropBox() {
1036 return enable(PENALTY_DROPBOX);
1037 }
1038
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001039 /**
1040 * Call #{@link OnVmViolationListener#onVmViolation(Violation)} on every violation.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001041 */
1042 public Builder penaltyListener(
Kurt Nelson72534b72018-02-22 11:21:15 -08001043 @NonNull Executor executor, @NonNull OnVmViolationListener listener) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001044 if (executor == null) {
1045 throw new NullPointerException("executor must not be null");
1046 }
1047 mListener = listener;
1048 mExecutor = executor;
1049 return this;
1050 }
1051
Kurt Nelson72534b72018-02-22 11:21:15 -08001052 /** @removed */
1053 public Builder penaltyListener(
1054 @NonNull OnVmViolationListener listener, @NonNull Executor executor) {
1055 return penaltyListener(executor, listener);
1056 }
1057
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001058 private Builder enable(int bit) {
1059 mMask |= bit;
1060 return this;
1061 }
1062
Mathieu Chartierca8c1052017-06-19 18:42:57 -07001063 Builder disable(int bit) {
1064 mMask &= ~bit;
1065 return this;
1066 }
1067
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001068 /**
1069 * Construct the VmPolicy instance.
1070 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001071 * <p>Note: if no penalties are enabled before calling <code>build</code>, {@link
1072 * #penaltyLog} is implicitly set.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001073 */
1074 public VmPolicy build() {
1075 // If there are detection bits set but no violation bits
1076 // set, enable simple logging.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001077 if (mListener == null
1078 && mMask != 0
Kurt Nelson46974a22017-08-30 13:30:26 -07001079 && (mMask
1080 & (PENALTY_DEATH
1081 | PENALTY_LOG
1082 | PENALTY_DROPBOX
1083 | PENALTY_DIALOG))
1084 == 0) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001085 penaltyLog();
1086 }
Kurt Nelson46974a22017-08-30 13:30:26 -07001087 return new VmPolicy(
1088 mMask,
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001089 mClassInstanceLimit != null ? mClassInstanceLimit : EMPTY_CLASS_LIMIT_MAP,
1090 mListener,
1091 mExecutor);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001092 }
1093 }
1094 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001095
1096 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001097 * Log of strict mode violation stack traces that have occurred during a Binder call, to be
1098 * serialized back later to the caller via Parcel.writeNoException() (amusingly) where the
1099 * caller can choose how to react.
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001100 */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001101 private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
1102 new ThreadLocal<ArrayList<ViolationInfo>>() {
Kurt Nelson46974a22017-08-30 13:30:26 -07001103 @Override
1104 protected ArrayList<ViolationInfo> initialValue() {
1105 // Starts null to avoid unnecessary allocations when
1106 // checking whether there are any violations or not in
1107 // hasGatheredViolations() below.
1108 return null;
1109 }
1110 };
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001111
1112 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001113 * Sets the policy for what actions on the current thread should be detected, as well as the
1114 * penalty if such actions occur.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001115 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001116 * <p>Internally this sets a thread-local variable which is propagated across cross-process IPC
1117 * calls, meaning you can catch violations when a system service or another process accesses the
1118 * disk or network on your behalf.
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -07001119 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001120 * @param policy the policy to put into place
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001121 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001122 public static void setThreadPolicy(final ThreadPolicy policy) {
1123 setThreadPolicyMask(policy.mask);
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001124 sThreadViolationListener.set(policy.mListener);
1125 sThreadViolationExecutor.set(policy.mCallbackExecutor);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001126 }
1127
Jeff Sharkey89182982017-11-01 19:02:56 -06001128 /** @hide */
1129 public static void setThreadPolicyMask(final int policyMask) {
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001130 // In addition to the Java-level thread-local in Dalvik's
1131 // BlockGuard, we also need to keep a native thread-local in
1132 // Binder in order to propagate the value across Binder calls,
1133 // even across native-only processes. The two are kept in
1134 // sync via the callback to onStrictModePolicyChange, below.
1135 setBlockGuardPolicy(policyMask);
1136
1137 // And set the Android native version...
1138 Binder.setThreadStrictModePolicy(policyMask);
1139 }
1140
1141 // Sets the policy in Dalvik/libcore (BlockGuard)
1142 private static void setBlockGuardPolicy(final int policyMask) {
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001143 if (policyMask == 0) {
1144 BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
1145 return;
1146 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001147 final BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
1148 final AndroidBlockGuardPolicy androidPolicy;
1149 if (policy instanceof AndroidBlockGuardPolicy) {
1150 androidPolicy = (AndroidBlockGuardPolicy) policy;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001151 } else {
Kurt Nelson46974a22017-08-30 13:30:26 -07001152 androidPolicy = THREAD_ANDROID_POLICY.get();
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001153 BlockGuard.setThreadPolicy(androidPolicy);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001154 }
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001155 androidPolicy.setPolicyMask(policyMask);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001156 }
1157
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001158 // Sets up CloseGuard in Dalvik/libcore
1159 private static void setCloseGuardEnabled(boolean enabled) {
Brad Fitzpatrick7c2ae652010-11-14 11:00:05 -08001160 if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001161 CloseGuard.setReporter(new AndroidCloseGuardReporter());
1162 }
1163 CloseGuard.setEnabled(enabled);
1164 }
1165
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001166 /**
Brad Fitzpatrick15ba4062010-09-22 13:53:57 -07001167 * Returns the bitmask of the current thread's policy.
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001168 *
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001169 * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001170 * @hide
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001171 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001172 public static int getThreadPolicyMask() {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001173 return BlockGuard.getThreadPolicy().getPolicyMask();
1174 }
1175
Kurt Nelson46974a22017-08-30 13:30:26 -07001176 /** Returns the current thread's policy. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001177 public static ThreadPolicy getThreadPolicy() {
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001178 // TODO: this was a last minute Gingerbread API change (to
1179 // introduce VmPolicy cleanly) but this isn't particularly
1180 // optimal for users who might call this method often. This
1181 // should be in a thread-local and not allocate on each call.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001182 return new ThreadPolicy(
1183 getThreadPolicyMask(),
1184 sThreadViolationListener.get(),
1185 sThreadViolationExecutor.get());
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001186 }
1187
1188 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001189 * A convenience wrapper that takes the current {@link ThreadPolicy} from {@link
1190 * #getThreadPolicy}, modifies it to permit both disk reads &amp; writes, and sets the new
1191 * policy with {@link #setThreadPolicy}, returning the old policy so you can restore it at the
1192 * end of a block.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001193 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001194 * @return the old policy, to be passed to {@link #setThreadPolicy} to restore the policy at the
1195 * end of a block
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001196 */
1197 public static ThreadPolicy allowThreadDiskWrites() {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001198 return new ThreadPolicy(
1199 allowThreadDiskWritesMask(),
1200 sThreadViolationListener.get(),
1201 sThreadViolationExecutor.get());
Jeff Sharkey89182982017-11-01 19:02:56 -06001202 }
1203
1204 /** @hide */
1205 public static int allowThreadDiskWritesMask() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001206 int oldPolicyMask = getThreadPolicyMask();
1207 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
1208 if (newPolicyMask != oldPolicyMask) {
1209 setThreadPolicyMask(newPolicyMask);
1210 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001211 return oldPolicyMask;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001212 }
1213
1214 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001215 * A convenience wrapper that takes the current {@link ThreadPolicy} from {@link
1216 * #getThreadPolicy}, modifies it to permit disk reads, and sets the new policy with {@link
1217 * #setThreadPolicy}, returning the old policy so you can restore it at the end of a block.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001218 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001219 * @return the old policy, to be passed to setThreadPolicy to restore the policy.
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001220 */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001221 public static ThreadPolicy allowThreadDiskReads() {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001222 return new ThreadPolicy(
1223 allowThreadDiskReadsMask(),
1224 sThreadViolationListener.get(),
1225 sThreadViolationExecutor.get());
Jeff Sharkey89182982017-11-01 19:02:56 -06001226 }
1227
1228 /** @hide */
1229 public static int allowThreadDiskReadsMask() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001230 int oldPolicyMask = getThreadPolicyMask();
1231 int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
1232 if (newPolicyMask != oldPolicyMask) {
1233 setThreadPolicyMask(newPolicyMask);
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001234 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001235 return oldPolicyMask;
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001236 }
1237
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001238 private static ThreadPolicy allowThreadViolations() {
1239 ThreadPolicy oldPolicy = getThreadPolicy();
1240 setThreadPolicyMask(0);
1241 return oldPolicy;
1242 }
1243
1244 private static VmPolicy allowVmViolations() {
1245 VmPolicy oldPolicy = getVmPolicy();
1246 sVmPolicy = VmPolicy.LAX;
1247 return oldPolicy;
1248 }
1249
Jeff Sharkey89182982017-11-01 19:02:56 -06001250 /**
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001251 * Determine if the given app is "bundled" as part of the system image. These bundled apps are
1252 * developed in lock-step with the OS, and they aren't updated outside of an OTA, so we want to
1253 * chase any {@link StrictMode} regressions by enabling detection when running on {@link
1254 * Build#IS_USERDEBUG} or {@link Build#IS_ENG} builds.
1255 *
1256 * <p>Unbundled apps included in the system image are expected to detect and triage their own
1257 * {@link StrictMode} issues separate from the OS release process, which is why we don't enable
1258 * them here.
Jeff Sharkey89182982017-11-01 19:02:56 -06001259 *
1260 * @hide
1261 */
1262 public static boolean isBundledSystemApp(ApplicationInfo ai) {
1263 if (ai == null || ai.packageName == null) {
1264 // Probably system server
1265 return true;
1266 } else if (ai.isSystemApp()) {
1267 // Ignore unbundled apps living in the wrong namespace
1268 if (ai.packageName.equals("com.android.vending")
1269 || ai.packageName.equals("com.android.chrome")) {
1270 return false;
1271 }
Brad Fitzpatrickf5454592010-11-24 15:27:51 -08001272
Jeff Sharkey89182982017-11-01 19:02:56 -06001273 // Ignore bundled apps that are way too spammy
1274 // STOPSHIP: burn this list down to zero
1275 if (ai.packageName.equals("com.android.phone")) {
1276 return false;
1277 }
1278
1279 if (ai.packageName.equals("android")
1280 || ai.packageName.startsWith("android.")
1281 || ai.packageName.startsWith("com.android.")) {
Brad Fitzpatrickf5454592010-11-24 15:27:51 -08001282 return true;
1283 }
1284 }
1285 return false;
1286 }
1287
Brad Fitzpatrick97461bd2010-08-24 11:46:47 -07001288 /**
Jeff Sharkey89182982017-11-01 19:02:56 -06001289 * Initialize default {@link ThreadPolicy} for the current thread.
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001290 *
1291 * @hide
1292 */
Jeff Sharkey89182982017-11-01 19:02:56 -06001293 public static void initThreadDefaults(ApplicationInfo ai) {
1294 final ThreadPolicy.Builder builder = new ThreadPolicy.Builder();
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001295 final int targetSdkVersion =
1296 (ai != null) ? ai.targetSdkVersion : Build.VERSION_CODES.CUR_DEVELOPMENT;
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001297
Jeff Sharkey89182982017-11-01 19:02:56 -06001298 // Starting in HC, we don't allow network usage on the main thread
1299 if (targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
1300 builder.detectNetwork();
1301 builder.penaltyDeathOnNetwork();
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001302 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001303
Jeff Sharkey89182982017-11-01 19:02:56 -06001304 if (Build.IS_USER || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) {
1305 // Detect nothing extra
1306 } else if (Build.IS_USERDEBUG) {
1307 // Detect everything in bundled apps
1308 if (isBundledSystemApp(ai)) {
1309 builder.detectAll();
1310 builder.penaltyDropBox();
1311 if (SystemProperties.getBoolean(VISUAL_PROPERTY, false)) {
1312 builder.penaltyFlashScreen();
1313 }
Mathieu Chartierca8c1052017-06-19 18:42:57 -07001314 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001315 } else if (Build.IS_ENG) {
1316 // Detect everything in bundled apps
1317 if (isBundledSystemApp(ai)) {
1318 builder.detectAll();
1319 builder.penaltyDropBox();
1320 builder.penaltyLog();
1321 builder.penaltyFlashScreen();
Jeff Brownd5875d92011-10-09 14:59:37 -07001322 }
Brad Fitzpatrickc1a968a2010-11-24 08:56:40 -08001323 }
Jeff Sharkey89182982017-11-01 19:02:56 -06001324
1325 setThreadPolicy(builder.build());
Brad Fitzpatrick50d66f92010-09-13 21:29:05 -07001326 }
1327
1328 /**
Jeff Sharkey89182982017-11-01 19:02:56 -06001329 * Initialize default {@link VmPolicy} for the current VM.
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001330 *
1331 * @hide
1332 */
Jeff Sharkey89182982017-11-01 19:02:56 -06001333 public static void initVmDefaults(ApplicationInfo ai) {
1334 final VmPolicy.Builder builder = new VmPolicy.Builder();
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001335 final int targetSdkVersion =
1336 (ai != null) ? ai.targetSdkVersion : Build.VERSION_CODES.CUR_DEVELOPMENT;
Jeff Sharkey89182982017-11-01 19:02:56 -06001337
1338 // Starting in N, we don't allow file:// Uri exposure
1339 if (targetSdkVersion >= Build.VERSION_CODES.N) {
1340 builder.detectFileUriExposure();
1341 builder.penaltyDeathOnFileUriExposure();
1342 }
1343
1344 if (Build.IS_USER || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) {
1345 // Detect nothing extra
1346 } else if (Build.IS_USERDEBUG) {
1347 // Detect everything in bundled apps (except activity leaks, which
1348 // are expensive to track)
1349 if (isBundledSystemApp(ai)) {
1350 builder.detectAll();
1351 builder.permitActivityLeaks();
1352 builder.penaltyDropBox();
1353 }
1354 } else if (Build.IS_ENG) {
1355 // Detect everything in bundled apps
1356 if (isBundledSystemApp(ai)) {
1357 builder.detectAll();
1358 builder.penaltyDropBox();
1359 builder.penaltyLog();
1360 }
1361 }
1362
1363 setVmPolicy(builder.build());
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001364 }
1365
1366 /**
Jeff Sharkey344744b2016-01-28 19:03:30 -07001367 * Used by the framework to make file usage a fatal error.
1368 *
1369 * @hide
1370 */
1371 public static void enableDeathOnFileUriExposure() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001372 sVmPolicy =
1373 new VmPolicy(
1374 sVmPolicy.mask
1375 | DETECT_VM_FILE_URI_EXPOSURE
1376 | PENALTY_DEATH_ON_FILE_URI_EXPOSURE,
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001377 sVmPolicy.classInstanceLimit,
1378 sVmPolicy.mListener,
1379 sVmPolicy.mCallbackExecutor);
Jeff Sharkey344744b2016-01-28 19:03:30 -07001380 }
1381
1382 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001383 * Used by lame internal apps that haven't done the hard work to get themselves off file:// Uris
1384 * yet.
Jeff Sharkey344744b2016-01-28 19:03:30 -07001385 *
1386 * @hide
1387 */
1388 public static void disableDeathOnFileUriExposure() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001389 sVmPolicy =
1390 new VmPolicy(
1391 sVmPolicy.mask
1392 & ~(DETECT_VM_FILE_URI_EXPOSURE
1393 | PENALTY_DEATH_ON_FILE_URI_EXPOSURE),
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001394 sVmPolicy.classInstanceLimit,
1395 sVmPolicy.mListener,
1396 sVmPolicy.mCallbackExecutor);
Jeff Sharkey344744b2016-01-28 19:03:30 -07001397 }
1398
1399 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001400 * Parses the BlockGuard policy mask out from the Exception's getMessage() String value. Kinda
1401 * gross, but least invasive. :/
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001402 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001403 * <p>Input is of the following forms: "policy=137 violation=64" "policy=137 violation=64
1404 * msg=Arbitrary text"
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001405 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001406 * <p>Returns 0 on failure, which is a valid policy, but not a valid policy during a violation
1407 * (else there must've been some policy in effect to violate).
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001408 */
1409 private static int parsePolicyFromMessage(String message) {
1410 if (message == null || !message.startsWith("policy=")) {
1411 return 0;
1412 }
1413 int spaceIndex = message.indexOf(' ');
1414 if (spaceIndex == -1) {
1415 return 0;
1416 }
1417 String policyString = message.substring(7, spaceIndex);
1418 try {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001419 return Integer.parseInt(policyString);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001420 } catch (NumberFormatException e) {
1421 return 0;
1422 }
1423 }
1424
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001425 private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
1426 new ThreadLocal<ArrayList<ViolationInfo>>() {
Kurt Nelson46974a22017-08-30 13:30:26 -07001427 @Override
1428 protected ArrayList<ViolationInfo> initialValue() {
1429 return new ArrayList<ViolationInfo>();
1430 }
1431 };
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001432
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001433 // Note: only access this once verifying the thread has a Looper.
Kurt Nelson46974a22017-08-30 13:30:26 -07001434 private static final ThreadLocal<Handler> THREAD_HANDLER =
1435 new ThreadLocal<Handler>() {
1436 @Override
1437 protected Handler initialValue() {
1438 return new Handler();
1439 }
1440 };
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001441
Kurt Nelson46974a22017-08-30 13:30:26 -07001442 private static final ThreadLocal<AndroidBlockGuardPolicy> THREAD_ANDROID_POLICY =
1443 new ThreadLocal<AndroidBlockGuardPolicy>() {
1444 @Override
1445 protected AndroidBlockGuardPolicy initialValue() {
1446 return new AndroidBlockGuardPolicy(0);
1447 }
1448 };
Jeff Sharkeya2934d52013-06-14 14:43:18 -07001449
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001450 private static boolean tooManyViolationsThisLoop() {
1451 return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
1452 }
1453
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001454 private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
1455 private int mPolicyMask;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001456
1457 // Map from violation stacktrace hashcode -> uptimeMillis of
1458 // last violation. No locking needed, as this is only
1459 // accessed by the same thread.
Dianne Hackborn390517b2013-05-30 15:03:32 -07001460 private ArrayMap<Integer, Long> mLastViolationTime;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001461
1462 public AndroidBlockGuardPolicy(final int policyMask) {
1463 mPolicyMask = policyMask;
1464 }
1465
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001466 @Override
1467 public String toString() {
1468 return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
1469 }
1470
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001471 // Part of BlockGuard.Policy interface:
1472 public int getPolicyMask() {
1473 return mPolicyMask;
1474 }
1475
1476 // Part of BlockGuard.Policy interface:
1477 public void onWriteToDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001478 if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001479 return;
1480 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001481 if (tooManyViolationsThisLoop()) {
1482 return;
1483 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001484 startHandlingViolationException(new DiskWriteViolation());
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001485 }
1486
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001487 // Not part of BlockGuard.Policy; just part of StrictMode:
1488 void onCustomSlowCall(String name) {
1489 if ((mPolicyMask & DETECT_CUSTOM) == 0) {
1490 return;
1491 }
1492 if (tooManyViolationsThisLoop()) {
1493 return;
1494 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001495 startHandlingViolationException(new CustomViolation(name));
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08001496 }
1497
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001498 // Not part of BlockGuard.Policy; just part of StrictMode:
1499 void onResourceMismatch(Object tag) {
1500 if ((mPolicyMask & DETECT_RESOURCE_MISMATCH) == 0) {
1501 return;
1502 }
1503 if (tooManyViolationsThisLoop()) {
1504 return;
1505 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001506 startHandlingViolationException(new ResourceMismatchViolation(tag));
Alan Viverette6bbb47b2015-01-05 18:12:44 -08001507 }
1508
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001509 // Not part of BlockGuard.Policy; just part of StrictMode:
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001510 public void onUnbufferedIO() {
1511 if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
1512 return;
1513 }
1514 if (tooManyViolationsThisLoop()) {
1515 return;
1516 }
Kurt Nelson0e612802017-11-09 17:25:40 -08001517 startHandlingViolationException(new UnbufferedIoViolation());
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01001518 }
1519
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001520 // Part of BlockGuard.Policy interface:
1521 public void onReadFromDisk() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001522 if ((mPolicyMask & DETECT_DISK_READ) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001523 return;
1524 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001525 if (tooManyViolationsThisLoop()) {
1526 return;
1527 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001528 startHandlingViolationException(new DiskReadViolation());
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001529 }
1530
1531 // Part of BlockGuard.Policy interface:
1532 public void onNetwork() {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001533 if ((mPolicyMask & DETECT_NETWORK) == 0) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001534 return;
1535 }
Brad Fitzpatrickb6e18412010-10-28 14:50:05 -07001536 if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
1537 throw new NetworkOnMainThreadException();
1538 }
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001539 if (tooManyViolationsThisLoop()) {
1540 return;
1541 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001542 startHandlingViolationException(new NetworkViolation());
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001543 }
1544
Pete Gillin22316b42018-02-15 17:17:27 +00001545 // Part of BlockGuard.Policy interface:
1546 public void onExplicitGc() {
1547 if ((mPolicyMask & DETECT_EXPLICIT_GC) == 0) {
1548 return;
1549 }
1550 if (tooManyViolationsThisLoop()) {
1551 return;
1552 }
1553 startHandlingViolationException(new ExplicitGcViolation());
1554 }
1555
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001556 public void setPolicyMask(int policyMask) {
1557 mPolicyMask = policyMask;
1558 }
1559
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001560 // Start handling a violation that just started and hasn't
1561 // actually run yet (e.g. no disk write or network operation
1562 // has yet occurred). This sees if we're in an event loop
1563 // thread and, if so, uses it to roughly measure how long the
1564 // violation took.
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001565 void startHandlingViolationException(Violation e) {
1566 final ViolationInfo info = new ViolationInfo(e, mPolicyMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001567 info.violationUptimeMillis = SystemClock.uptimeMillis();
1568 handleViolationWithTimingAttempt(info);
1569 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001570
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001571 // Attempts to fill in the provided ViolationInfo's
1572 // durationMillis field if this thread has a Looper we can use
1573 // to measure with. We measure from the time of violation
1574 // until the time the looper is idle again (right before
1575 // the next epoll_wait)
1576 void handleViolationWithTimingAttempt(final ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001577 Looper looper = Looper.myLooper();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001578
1579 // Without a Looper, we're unable to time how long the
1580 // violation takes place. This case should be rare, as
1581 // most users will care about timing violations that
1582 // happen on their main UI thread. Note that this case is
1583 // also hit when a violation takes place in a Binder
1584 // thread, in "gather" mode. In this case, the duration
1585 // of the violation is computed by the ultimate caller and
1586 // its Looper, if any.
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08001587 //
1588 // Also, as a special short-cut case when the only penalty
1589 // bit is death, we die immediately, rather than timing
1590 // the violation's duration. This makes it convenient to
1591 // use in unit tests too, rather than waiting on a Looper.
1592 //
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001593 // TODO: if in gather mode, ignore Looper.myLooper() and always
1594 // go into this immediate mode?
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001595 if (looper == null || (info.mPolicy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
Kurt Nelson46974a22017-08-30 13:30:26 -07001596 info.durationMillis = -1; // unknown (redundant, already set)
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001597 onThreadPolicyViolation(info);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001598 return;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001599 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001600
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001601 final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
Brad Fitzpatrick191cdf02010-10-11 11:31:15 -07001602 if (records.size() >= MAX_OFFENSES_PER_LOOP) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001603 // Not worth measuring. Too many offenses in one loop.
1604 return;
1605 }
1606 records.add(info);
1607 if (records.size() > 1) {
1608 // There's already been a violation this loop, so we've already
1609 // registered an idle handler to process the list of violations
1610 // at the end of this Looper's loop.
1611 return;
1612 }
1613
Kurt Nelson46974a22017-08-30 13:30:26 -07001614 final IWindowManager windowManager =
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001615 info.penaltyEnabled(PENALTY_FLASH) ? sWindowManager.get() : null;
Brad Fitzpatrick68044332010-11-22 18:19:48 -08001616 if (windowManager != null) {
1617 try {
1618 windowManager.showStrictModeViolation(true);
1619 } catch (RemoteException unused) {
1620 }
1621 }
1622
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001623 // We post a runnable to a Handler (== delay 0 ms) for
1624 // measuring the end time of a violation instead of using
1625 // an IdleHandler (as was previously used) because an
1626 // IdleHandler may not run for quite a long period of time
1627 // if an ongoing animation is happening and continually
1628 // posting ASAP (0 ms) animation steps. Animations are
1629 // throttled back to 60fps via SurfaceFlinger/View
1630 // invalidates, _not_ by posting frame updates every 16
1631 // milliseconds.
Kurt Nelson46974a22017-08-30 13:30:26 -07001632 THREAD_HANDLER
1633 .get()
1634 .postAtFrontOfQueue(
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001635 () -> {
1636 long loopFinishTime = SystemClock.uptimeMillis();
Brad Fitzpatrickbea168c2010-11-30 10:56:48 -08001637
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001638 // Note: we do this early, before handling the
1639 // violation below, as handling the violation
1640 // may include PENALTY_DEATH and we don't want
1641 // to keep the red border on.
1642 if (windowManager != null) {
1643 try {
1644 windowManager.showStrictModeViolation(false);
1645 } catch (RemoteException unused) {
Kurt Nelson46974a22017-08-30 13:30:26 -07001646 }
Kurt Nelson46974a22017-08-30 13:30:26 -07001647 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001648
1649 for (int n = 0; n < records.size(); ++n) {
1650 ViolationInfo v = records.get(n);
1651 v.violationNumThisLoop = n + 1;
1652 v.durationMillis =
1653 (int) (loopFinishTime - v.violationUptimeMillis);
1654 onThreadPolicyViolation(v);
1655 }
1656 records.clear();
Kurt Nelson46974a22017-08-30 13:30:26 -07001657 });
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001658 }
1659
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001660 // Note: It's possible (even quite likely) that the
1661 // thread-local policy mask has changed from the time the
1662 // violation fired and now (after the violating code ran) due
1663 // to people who push/pop temporary policy in regions of code,
1664 // hence the policy being passed around.
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001665 void onThreadPolicyViolation(final ViolationInfo info) {
1666 if (LOG_V) Log.d(TAG, "onThreadPolicyViolation; policy=" + info.mPolicy);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001667
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001668 if (info.penaltyEnabled(PENALTY_GATHER)) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001669 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001670 if (violations == null) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001671 violations = new ArrayList<>(1);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001672 gatheredViolations.set(violations);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001673 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001674 for (ViolationInfo previous : violations) {
Kurt Nelson0918c932017-09-07 10:56:56 -07001675 if (info.getStackTrace().equals(previous.getStackTrace())) {
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001676 // Duplicate. Don't log.
1677 return;
1678 }
1679 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001680 violations.add(info);
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001681 return;
1682 }
1683
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001684 // Not perfect, but fast and good enough for dup suppression.
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08001685 Integer crashFingerprint = info.hashCode();
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001686 long lastViolationTime = 0;
Dianne Hackborn390517b2013-05-30 15:03:32 -07001687 if (mLastViolationTime != null) {
1688 Long vtime = mLastViolationTime.get(crashFingerprint);
1689 if (vtime != null) {
1690 lastViolationTime = vtime;
1691 }
1692 } else {
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07001693 mLastViolationTime = new ArrayMap<>(1);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001694 }
1695 long now = SystemClock.uptimeMillis();
1696 mLastViolationTime.put(crashFingerprint, now);
Kurt Nelson46974a22017-08-30 13:30:26 -07001697 long timeSinceLastViolationMillis =
1698 lastViolationTime == 0 ? Long.MAX_VALUE : (now - lastViolationTime);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001699
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001700 if (info.penaltyEnabled(PENALTY_LOG)
Kurt Nelson46974a22017-08-30 13:30:26 -07001701 && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07001702 sLogger.log(info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001703 }
1704
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001705 final Violation violation = info.mViolation;
1706
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001707 // The violationMaskSubset, passed to ActivityManager, is a
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001708 // subset of the original StrictMode policy bitmask, with
1709 // only the bit violated and penalty bits to be executed
1710 // by the ActivityManagerService remaining set.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001711 int violationMaskSubset = 0;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001712
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001713 if (info.penaltyEnabled(PENALTY_DIALOG)
Kurt Nelson46974a22017-08-30 13:30:26 -07001714 && timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001715 violationMaskSubset |= PENALTY_DIALOG;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001716 }
1717
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001718 if (info.penaltyEnabled(PENALTY_DROPBOX) && lastViolationTime == 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001719 violationMaskSubset |= PENALTY_DROPBOX;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07001720 }
1721
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07001722 if (violationMaskSubset != 0) {
Kurt Nelson0918c932017-09-07 10:56:56 -07001723 violationMaskSubset |= info.getViolationBit();
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001724
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001725 final boolean justDropBox = (info.mPolicy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
Brad Fitzpatrick71678dd2010-10-28 13:51:58 -07001726 if (justDropBox) {
1727 // If all we're going to ask the activity manager
1728 // to do is dropbox it (the common case during
1729 // platform development), we can avoid doing this
1730 // call synchronously which Binder data suggests
1731 // isn't always super fast, despite the implementation
1732 // in the ActivityManager trying to be mostly async.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001733 dropboxViolationAsync(violationMaskSubset, info);
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -07001734 } else {
1735 handleApplicationStrictModeViolation(violationMaskSubset, info);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001736 }
1737 }
1738
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001739 if ((info.getPolicyMask() & PENALTY_DEATH) != 0) {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001740 throw new RuntimeException("StrictMode ThreadPolicy violation", violation);
1741 }
1742
1743 // penaltyDeath will cause penaltyCallback to no-op since we cannot guarantee the
1744 // executor finishes before crashing.
1745 final OnThreadViolationListener listener = sThreadViolationListener.get();
1746 final Executor executor = sThreadViolationExecutor.get();
1747 if (listener != null && executor != null) {
1748 try {
1749 executor.execute(
1750 () -> {
1751 // Lift violated policy to prevent infinite recursion.
1752 ThreadPolicy oldPolicy = allowThreadViolations();
1753 try {
1754 listener.onThreadViolation(violation);
1755 } finally {
1756 setThreadPolicy(oldPolicy);
1757 }
1758 });
1759 } catch (RejectedExecutionException e) {
1760 Log.e(TAG, "ThreadPolicy penaltyCallback failed", e);
1761 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001762 }
1763 }
1764 }
Brad Fitzpatrick727de402010-07-07 16:06:39 -07001765
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001766 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001767 * In the common case, as set by conditionallyEnableDebugLogging, we're just dropboxing any
1768 * violations but not showing a dialog, not loggging, and not killing the process. In these
1769 * cases we don't need to do a synchronous call to the ActivityManager. This is used by both
1770 * per-thread and vm-wide violations when applicable.
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001771 */
1772 private static void dropboxViolationAsync(
1773 final int violationMaskSubset, final ViolationInfo info) {
1774 int outstanding = sDropboxCallsInFlight.incrementAndGet();
1775 if (outstanding > 20) {
1776 // What's going on? Let's not make make the situation
1777 // worse and just not log.
1778 sDropboxCallsInFlight.decrementAndGet();
1779 return;
1780 }
1781
1782 if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
1783
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -07001784 BackgroundThread.getHandler().post(() -> {
1785 handleApplicationStrictModeViolation(violationMaskSubset, info);
1786 int outstandingInner = sDropboxCallsInFlight.decrementAndGet();
1787 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstandingInner);
1788 });
1789 }
1790
1791 private static void handleApplicationStrictModeViolation(int violationMaskSubset,
1792 ViolationInfo info) {
1793 final int oldMask = getThreadPolicyMask();
1794 try {
1795 // First, remove any policy before we call into the Activity Manager,
1796 // otherwise we'll infinite recurse as we try to log policy violations
1797 // to disk, thus violating policy, thus requiring logging, etc...
1798 // We restore the current policy below, in the finally block.
1799 setThreadPolicyMask(0);
1800
1801 IActivityManager am = ActivityManager.getService();
1802 if (am == null) {
1803 Log.w(TAG, "No activity manager; failed to Dropbox violation.");
1804 } else {
1805 am.handleApplicationStrictModeViolation(
1806 RuntimeInit.getApplicationObject(), violationMaskSubset, info);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001807 }
Jeff Sharkeyda4e50f2017-11-06 15:23:03 -07001808 } catch (RemoteException e) {
1809 if (e instanceof DeadObjectException) {
1810 // System process is dead; ignore
1811 } else {
1812 Log.e(TAG, "RemoteException handling StrictMode violation", e);
1813 }
1814 } finally {
1815 setThreadPolicyMask(oldMask);
1816 }
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08001817 }
1818
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001819 private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
Jeff Sharkey605eb792014-11-04 13:34:06 -08001820 public void report(String message, Throwable allocationSite) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001821 onVmPolicyViolation(new LeakedClosableViolation(message, allocationSite));
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001822 }
1823 }
1824
Kurt Nelson46974a22017-08-30 13:30:26 -07001825 /** Called from Parcel.writeNoException() */
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001826 /* package */ static boolean hasGatheredViolations() {
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001827 return gatheredViolations.get() != null;
1828 }
1829
1830 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001831 * Called from Parcel.writeException(), so we drop this memory and don't incorrectly attribute
1832 * it to the wrong caller on the next Binder call on this thread.
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07001833 */
1834 /* package */ static void clearGatheredViolations() {
1835 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07001836 }
1837
Kurt Nelson46974a22017-08-30 13:30:26 -07001838 /** @hide */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001839 public static void conditionallyCheckInstanceCounts() {
1840 VmPolicy policy = getVmPolicy();
Mathieu Chartierd288a262015-07-10 13:44:42 -07001841 int policySize = policy.classInstanceLimit.size();
1842 if (policySize == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001843 return;
1844 }
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08001845
1846 System.gc();
1847 System.runFinalization();
1848 System.gc();
1849
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001850 // Note: classInstanceLimit is immutable, so this is lock-free
Mathieu Chartierd288a262015-07-10 13:44:42 -07001851 // Create the classes array.
1852 Class[] classes = policy.classInstanceLimit.keySet().toArray(new Class[policySize]);
1853 long[] instanceCounts = VMDebug.countInstancesOfClasses(classes, false);
1854 for (int i = 0; i < classes.length; ++i) {
1855 Class klass = classes[i];
1856 int limit = policy.classInstanceLimit.get(klass);
1857 long instances = instanceCounts[i];
1858 if (instances > limit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001859 onVmPolicyViolation(new InstanceCountViolation(klass, instances, limit));
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001860 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001861 }
1862 }
1863
1864 private static long sLastInstanceCountCheckMillis = 0;
Kurt Nelson46974a22017-08-30 13:30:26 -07001865 private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001866 private static final MessageQueue.IdleHandler sProcessIdleHandler =
1867 new MessageQueue.IdleHandler() {
1868 public boolean queueIdle() {
1869 long now = SystemClock.uptimeMillis();
1870 if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
1871 sLastInstanceCountCheckMillis = now;
1872 conditionallyCheckInstanceCounts();
1873 }
1874 return true;
1875 }
1876 };
1877
1878 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07001879 * Sets the policy for what actions in the VM process (on any thread) should be detected, as
1880 * well as the penalty if such actions occur.
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001881 *
1882 * @param policy the policy to put into place
1883 */
1884 public static void setVmPolicy(final VmPolicy policy) {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001885 synchronized (StrictMode.class) {
1886 sVmPolicy = policy;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001887 setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001888
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001889 Looper looper = Looper.getMainLooper();
1890 if (looper != null) {
1891 MessageQueue mq = looper.mQueue;
Kurt Nelson46974a22017-08-30 13:30:26 -07001892 if (policy.classInstanceLimit.size() == 0
Kurt Nelson2c883f32017-09-01 10:52:45 -07001893 || (sVmPolicy.mask & VM_PENALTY_MASK) == 0) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001894 mq.removeIdleHandler(sProcessIdleHandler);
Brad Fitzpatrickc0bb0bb2011-01-20 16:29:52 -08001895 sIsIdlerRegistered = false;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001896 } else if (!sIsIdlerRegistered) {
1897 mq.addIdleHandler(sProcessIdleHandler);
1898 sIsIdlerRegistered = true;
1899 }
1900 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08001901
1902 int networkPolicy = NETWORK_POLICY_ACCEPT;
Kurt Nelson2c883f32017-09-01 10:52:45 -07001903 if ((sVmPolicy.mask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
1904 if ((sVmPolicy.mask & PENALTY_DEATH) != 0
1905 || (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
Jeff Sharkey605eb792014-11-04 13:34:06 -08001906 networkPolicy = NETWORK_POLICY_REJECT;
1907 } else {
1908 networkPolicy = NETWORK_POLICY_LOG;
1909 }
1910 }
1911
Kurt Nelson46974a22017-08-30 13:30:26 -07001912 final INetworkManagementService netd =
1913 INetworkManagementService.Stub.asInterface(
1914 ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
Jeff Sharkey605eb792014-11-04 13:34:06 -08001915 if (netd != null) {
1916 try {
1917 netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
1918 } catch (RemoteException ignored) {
1919 }
1920 } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
1921 Log.w(TAG, "Dropping requested network policy due to missing service!");
1922 }
Narayan Kamathad1b2a92018-03-28 11:29:40 +01001923
1924
1925 if ((sVmPolicy.mask & DETECT_VM_NON_SDK_API_USAGE) != 0) {
1926 VMRuntime.setNonSdkApiUsageConsumer(sNonSdkApiUsageConsumer);
1927 } else {
1928 VMRuntime.setNonSdkApiUsageConsumer(null);
1929 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08001930 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001931 }
1932
Kurt Nelson46974a22017-08-30 13:30:26 -07001933 /** Gets the current VM policy. */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001934 public static VmPolicy getVmPolicy() {
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08001935 synchronized (StrictMode.class) {
1936 return sVmPolicy;
1937 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001938 }
1939
1940 /**
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001941 * Enable the recommended StrictMode defaults, with violations just being logged.
1942 *
Kurt Nelson46974a22017-08-30 13:30:26 -07001943 * <p>This catches disk and network access on the main thread, as well as leaked SQLite cursors
1944 * and unclosed resources. This is simply a wrapper around {@link #setVmPolicy} and {@link
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001945 * #setThreadPolicy}.
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001946 */
1947 public static void enableDefaults() {
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07001948 setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
1949 setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
Brad Fitzpatrick62a1eb52010-10-18 14:32:59 -07001950 }
1951
Kurt Nelson46974a22017-08-30 13:30:26 -07001952 /** @hide */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001953 public static boolean vmSqliteObjectLeaksEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001954 return (sVmPolicy.mask & DETECT_VM_CURSOR_LEAKS) != 0;
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001955 }
1956
Kurt Nelson46974a22017-08-30 13:30:26 -07001957 /** @hide */
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001958 public static boolean vmClosableObjectLeaksEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001959 return (sVmPolicy.mask & DETECT_VM_CLOSABLE_LEAKS) != 0;
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001960 }
1961
Kurt Nelson46974a22017-08-30 13:30:26 -07001962 /** @hide */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001963 public static boolean vmRegistrationLeaksEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001964 return (sVmPolicy.mask & DETECT_VM_REGISTRATION_LEAKS) != 0;
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001965 }
1966
Kurt Nelson46974a22017-08-30 13:30:26 -07001967 /** @hide */
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001968 public static boolean vmFileUriExposureEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001969 return (sVmPolicy.mask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001970 }
1971
Kurt Nelson46974a22017-08-30 13:30:26 -07001972 /** @hide */
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -07001973 public static boolean vmCleartextNetworkEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001974 return (sVmPolicy.mask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07001975 }
1976
Kurt Nelson46974a22017-08-30 13:30:26 -07001977 /** @hide */
Jeff Sharkeyf361f2f2016-12-21 10:48:42 -07001978 public static boolean vmContentUriWithoutPermissionEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001979 return (sVmPolicy.mask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
Jeff Sharkey605eb792014-11-04 13:34:06 -08001980 }
1981
Kurt Nelson46974a22017-08-30 13:30:26 -07001982 /** @hide */
Jeff Sharkey619a5112017-01-19 11:55:54 -07001983 public static boolean vmUntaggedSocketEnabled() {
Kurt Nelson2c883f32017-09-01 10:52:45 -07001984 return (sVmPolicy.mask & DETECT_VM_UNTAGGED_SOCKET) != 0;
Jeff Sharkey619a5112017-01-19 11:55:54 -07001985 }
1986
Kurt Nelson46974a22017-08-30 13:30:26 -07001987 /** @hide */
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07001988 public static void onSqliteObjectLeaked(String message, Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001989 onVmPolicyViolation(new SqliteObjectLeakedViolation(message, originStack));
Brian Carlstrom4b9b7c32010-11-08 10:30:40 -08001990 }
1991
Kurt Nelson46974a22017-08-30 13:30:26 -07001992 /** @hide */
Steve Block08d584c2011-05-17 19:05:03 +01001993 public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001994 onVmPolicyViolation(new WebViewMethodCalledOnWrongThreadViolation(originStack));
Steve Block08d584c2011-05-17 19:05:03 +01001995 }
1996
Kurt Nelson46974a22017-08-30 13:30:26 -07001997 /** @hide */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001998 public static void onIntentReceiverLeaked(Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07001999 onVmPolicyViolation(new IntentReceiverLeakedViolation(originStack));
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08002000 }
2001
Kurt Nelson46974a22017-08-30 13:30:26 -07002002 /** @hide */
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08002003 public static void onServiceConnectionLeaked(Throwable originStack) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002004 onVmPolicyViolation(new ServiceConnectionLeakedViolation(originStack));
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08002005 }
2006
Kurt Nelson46974a22017-08-30 13:30:26 -07002007 /** @hide */
Jeff Sharkey344744b2016-01-28 19:03:30 -07002008 public static void onFileUriExposed(Uri uri, String location) {
2009 final String message = uri + " exposed beyond app through " + location;
Kurt Nelson2c883f32017-09-01 10:52:45 -07002010 if ((sVmPolicy.mask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
Jeff Sharkey344744b2016-01-28 19:03:30 -07002011 throw new FileUriExposedException(message);
2012 } else {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002013 onVmPolicyViolation(new FileUriExposedViolation(message));
Jeff Sharkey344744b2016-01-28 19:03:30 -07002014 }
Jeff Sharkey605eb792014-11-04 13:34:06 -08002015 }
2016
Kurt Nelson46974a22017-08-30 13:30:26 -07002017 /** @hide */
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07002018 public static void onContentUriWithoutPermission(Uri uri, String location) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002019 onVmPolicyViolation(new ContentUriWithoutPermissionViolation(uri, location));
Jeff Sharkeyfb833f32016-12-01 14:59:59 -07002020 }
2021
Kurt Nelson46974a22017-08-30 13:30:26 -07002022 /** @hide */
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -07002023 public static final String CLEARTEXT_DETECTED_MSG =
2024 "Detected cleartext network traffic from UID ";
2025
2026 /** @hide */
Jeff Sharkey605eb792014-11-04 13:34:06 -08002027 public static void onCleartextNetworkDetected(byte[] firstPacket) {
2028 byte[] rawAddr = null;
2029 if (firstPacket != null) {
2030 if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
2031 // IPv4
2032 rawAddr = new byte[4];
2033 System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
2034 } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
2035 // IPv6
2036 rawAddr = new byte[16];
2037 System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
2038 }
2039 }
2040
2041 final int uid = android.os.Process.myUid();
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -07002042 String msg = CLEARTEXT_DETECTED_MSG + uid;
Jeff Sharkey605eb792014-11-04 13:34:06 -08002043 if (rawAddr != null) {
2044 try {
Kurt Nelsoncf8c4fa2017-09-19 12:26:02 -07002045 msg += " to " + InetAddress.getByAddress(rawAddr);
Jeff Sharkey605eb792014-11-04 13:34:06 -08002046 } catch (UnknownHostException ignored) {
2047 }
2048 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002049 msg += HexDump.dumpHexString(firstPacket).trim() + " ";
Kurt Nelson2c883f32017-09-01 10:52:45 -07002050 final boolean forceDeath = (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002051 onVmPolicyViolation(new CleartextNetworkViolation(msg), forceDeath);
Jeff Sharkeya14acd22013-04-02 18:27:45 -07002052 }
2053
Kurt Nelson46974a22017-08-30 13:30:26 -07002054 /** @hide */
Jeff Sharkey619a5112017-01-19 11:55:54 -07002055 public static void onUntaggedSocket() {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002056 onVmPolicyViolation(new UntaggedSocketViolation());
Jeff Sharkey619a5112017-01-19 11:55:54 -07002057 }
2058
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002059 // Map from VM violation fingerprint to uptime millis.
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002060 private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<>();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002061
Kurt Nelson46974a22017-08-30 13:30:26 -07002062 /** @hide */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002063 public static void onVmPolicyViolation(Violation originStack) {
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002064 onVmPolicyViolation(originStack, false);
Jeff Sharkey605eb792014-11-04 13:34:06 -08002065 }
2066
Kurt Nelson46974a22017-08-30 13:30:26 -07002067 /** @hide */
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002068 public static void onVmPolicyViolation(Violation violation, boolean forceDeath) {
Kurt Nelson2c883f32017-09-01 10:52:45 -07002069 final boolean penaltyDropbox = (sVmPolicy.mask & PENALTY_DROPBOX) != 0;
2070 final boolean penaltyDeath = ((sVmPolicy.mask & PENALTY_DEATH) != 0) || forceDeath;
2071 final boolean penaltyLog = (sVmPolicy.mask & PENALTY_LOG) != 0;
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002072 final ViolationInfo info = new ViolationInfo(violation, sVmPolicy.mask);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002073
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002074 // Erase stuff not relevant for process-wide violations
2075 info.numAnimationsRunning = 0;
2076 info.tags = null;
2077 info.broadcastIntentAction = null;
2078
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002079 final Integer fingerprint = info.hashCode();
2080 final long now = SystemClock.uptimeMillis();
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002081 long lastViolationTime;
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002082 long timeSinceLastViolationMillis = Long.MAX_VALUE;
2083 synchronized (sLastVmViolationTime) {
2084 if (sLastVmViolationTime.containsKey(fingerprint)) {
2085 lastViolationTime = sLastVmViolationTime.get(fingerprint);
2086 timeSinceLastViolationMillis = now - lastViolationTime;
2087 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002088 if (timeSinceLastViolationMillis > MIN_VM_INTERVAL_MS) {
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002089 sLastVmViolationTime.put(fingerprint, now);
2090 }
2091 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002092 if (timeSinceLastViolationMillis <= MIN_VM_INTERVAL_MS) {
2093 // Rate limit all penalties.
2094 return;
Jeff Sharkeyc985ffd2017-05-24 12:45:40 -06002095 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002096
2097 if (penaltyLog && sLogger != null && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07002098 sLogger.log(info);
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002099 }
2100
Kurt Nelson2c883f32017-09-01 10:52:45 -07002101 int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicy.mask);
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08002102
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002103 if (penaltyDropbox) {
2104 if (penaltyDeath) {
2105 handleApplicationStrictModeViolation(violationMaskSubset, info);
2106 } else {
2107 // Common case for userdebug/eng builds. If no death and
2108 // just dropboxing, we can do the ActivityManager call
2109 // asynchronously.
2110 dropboxViolationAsync(violationMaskSubset, info);
2111 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002112 }
2113
Brad Fitzpatrickbee24872010-11-20 12:09:10 -08002114 if (penaltyDeath) {
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002115 System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
2116 Process.killProcess(Process.myPid());
2117 System.exit(10);
2118 }
Kurt Nelsone6e0ebf2017-08-29 18:04:21 -07002119
2120 // If penaltyDeath, we can't guarantee this callback finishes before the process dies for
2121 // all executors. penaltyDeath supersedes penaltyCallback.
2122 if (sVmPolicy.mListener != null && sVmPolicy.mCallbackExecutor != null) {
2123 final OnVmViolationListener listener = sVmPolicy.mListener;
2124 try {
2125 sVmPolicy.mCallbackExecutor.execute(
2126 () -> {
2127 // Lift violated policy to prevent infinite recursion.
2128 VmPolicy oldPolicy = allowVmViolations();
2129 try {
2130 listener.onVmViolation(violation);
2131 } finally {
2132 setVmPolicy(oldPolicy);
2133 }
2134 });
2135 } catch (RejectedExecutionException e) {
2136 Log.e(TAG, "VmPolicy penaltyCallback failed", e);
2137 }
2138 }
Brad Fitzpatrick32e60c72010-09-30 16:22:36 -07002139 }
2140
Kurt Nelson46974a22017-08-30 13:30:26 -07002141 /** Called from Parcel.writeNoException() */
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002142 /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002143 ArrayList<ViolationInfo> violations = gatheredViolations.get();
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002144 if (violations == null) {
2145 p.writeInt(0);
2146 } else {
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002147 // To avoid taking up too much transaction space, only include
2148 // details for the first 3 violations. Deep inside, CrashInfo
2149 // will truncate each stack trace to ~20kB.
2150 final int size = Math.min(violations.size(), 3);
2151 p.writeInt(size);
2152 for (int i = 0; i < size; i++) {
2153 violations.get(i).writeToParcel(p, 0);
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002154 }
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002155 }
Brad Fitzpatrick703e5d32010-07-15 13:16:41 -07002156 gatheredViolations.set(null);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002157 }
2158
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002159 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002160 * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, we here
2161 * read back all the encoded violations.
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002162 */
2163 /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002164 Throwable localCallSite = new Throwable();
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002165 final int policyMask = getThreadPolicyMask();
2166 final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002167
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002168 final int size = p.readInt();
2169 for (int i = 0; i < size; i++) {
2170 final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
Kurt Nelson0918c932017-09-07 10:56:56 -07002171 info.addLocalStack(localCallSite);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002172 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2173 if (policy instanceof AndroidBlockGuardPolicy) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002174 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
Brad Fitzpatrick5b747192010-07-12 11:05:38 -07002175 }
2176 }
2177 }
2178
2179 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002180 * Called from android_util_Binder.cpp's android_os_Parcel_enforceInterface when an incoming
2181 * Binder call requires changing the StrictMode policy mask. The role of this function is to ask
2182 * Binder for its current (native) thread-local policy value and synchronize it to libcore's
2183 * (Java) thread-local policy value.
Brad Fitzpatrick727de402010-07-07 16:06:39 -07002184 */
2185 private static void onBinderStrictModePolicyChange(int newPolicy) {
2186 setBlockGuardPolicy(newPolicy);
2187 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002188
2189 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002190 * A tracked, critical time span. (e.g. during an animation.)
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002191 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002192 * <p>The object itself is a linked list node, to avoid any allocations during rapid span
2193 * entries and exits.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002194 *
2195 * @hide
2196 */
2197 public static class Span {
2198 private String mName;
2199 private long mCreateMillis;
2200 private Span mNext;
Kurt Nelson46974a22017-08-30 13:30:26 -07002201 private Span mPrev; // not used when in freeList, only active
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002202 private final ThreadSpanState mContainerState;
2203
2204 Span(ThreadSpanState threadState) {
2205 mContainerState = threadState;
2206 }
2207
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002208 // Empty constructor for the NO_OP_SPAN
2209 protected Span() {
2210 mContainerState = null;
2211 }
2212
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002213 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002214 * To be called when the critical span is complete (i.e. the animation is done animating).
2215 * This can be called on any thread (even a different one from where the animation was
2216 * taking place), but that's only a defensive implementation measure. It really makes no
2217 * sense for you to call this on thread other than that where you created it.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002218 *
2219 * @hide
2220 */
2221 public void finish() {
2222 ThreadSpanState state = mContainerState;
2223 synchronized (state) {
2224 if (mName == null) {
2225 // Duplicate finish call. Ignore.
2226 return;
2227 }
2228
2229 // Remove ourselves from the active list.
2230 if (mPrev != null) {
2231 mPrev.mNext = mNext;
2232 }
2233 if (mNext != null) {
2234 mNext.mPrev = mPrev;
2235 }
2236 if (state.mActiveHead == this) {
2237 state.mActiveHead = mNext;
2238 }
2239
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002240 state.mActiveSize--;
2241
2242 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
2243
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002244 this.mCreateMillis = -1;
2245 this.mName = null;
2246 this.mPrev = null;
2247 this.mNext = null;
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002248
2249 // Add ourselves to the freeList, if it's not already
2250 // too big.
2251 if (state.mFreeListSize < 5) {
2252 this.mNext = state.mFreeListHead;
2253 state.mFreeListHead = this;
2254 state.mFreeListSize++;
2255 }
2256 }
2257 }
2258 }
2259
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002260 // The no-op span that's used in user builds.
Kurt Nelson46974a22017-08-30 13:30:26 -07002261 private static final Span NO_OP_SPAN =
2262 new Span() {
2263 public void finish() {
2264 // Do nothing.
2265 }
2266 };
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002267
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002268 /**
2269 * Linked lists of active spans and a freelist.
2270 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002271 * <p>Locking notes: there's one of these structures per thread and all members of this
2272 * structure (as well as the Span nodes under it) are guarded by the ThreadSpanState object
2273 * instance. While in theory there'd be no locking required because it's all local per-thread,
2274 * the finish() method above is defensive against people calling it on a different thread from
2275 * where they created the Span, hence the locking.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002276 */
2277 private static class ThreadSpanState {
Kurt Nelson46974a22017-08-30 13:30:26 -07002278 public Span mActiveHead; // doubly-linked list.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002279 public int mActiveSize;
Kurt Nelson46974a22017-08-30 13:30:26 -07002280 public Span mFreeListHead; // singly-linked list. only changes at head.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002281 public int mFreeListSize;
2282 }
2283
2284 private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
2285 new ThreadLocal<ThreadSpanState>() {
Kurt Nelson46974a22017-08-30 13:30:26 -07002286 @Override
2287 protected ThreadSpanState initialValue() {
2288 return new ThreadSpanState();
2289 }
2290 };
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002291
Kurt Nelson46974a22017-08-30 13:30:26 -07002292 private static Singleton<IWindowManager> sWindowManager =
2293 new Singleton<IWindowManager>() {
2294 protected IWindowManager create() {
2295 return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
2296 }
2297 };
Brad Fitzpatrickcdcb73e2010-11-22 22:56:23 -08002298
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002299 /**
2300 * Enter a named critical span (e.g. an animation)
2301 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002302 * <p>The name is an arbitary label (or tag) that will be applied to any strictmode violation
2303 * that happens while this span is active. You must call finish() on the span when done.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002304 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002305 * <p>This will never return null, but on devices without debugging enabled, this may return a
2306 * dummy object on which the finish() method is a no-op.
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002307 *
2308 * <p>TODO: add CloseGuard to this, verifying callers call finish.
2309 *
2310 * @hide
2311 */
2312 public static Span enterCriticalSpan(String name) {
Jeff Sharkey5ab02432017-06-27 11:01:36 -06002313 if (Build.IS_USER) {
Brad Fitzpatrick1181cbb2010-11-16 12:46:16 -08002314 return NO_OP_SPAN;
2315 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002316 if (name == null || name.isEmpty()) {
2317 throw new IllegalArgumentException("name must be non-null and non-empty");
2318 }
2319 ThreadSpanState state = sThisThreadSpanState.get();
2320 Span span = null;
2321 synchronized (state) {
2322 if (state.mFreeListHead != null) {
2323 span = state.mFreeListHead;
2324 state.mFreeListHead = span.mNext;
2325 state.mFreeListSize--;
2326 } else {
2327 // Shouldn't have to do this often.
2328 span = new Span(state);
2329 }
2330 span.mName = name;
2331 span.mCreateMillis = SystemClock.uptimeMillis();
2332 span.mNext = state.mActiveHead;
2333 span.mPrev = null;
2334 state.mActiveHead = span;
2335 state.mActiveSize++;
2336 if (span.mNext != null) {
2337 span.mNext.mPrev = span;
2338 }
Brad Fitzpatrick1cc13b62010-11-16 15:35:58 -08002339 if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002340 }
2341 return span;
2342 }
2343
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002344 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002345 * For code to note that it's slow. This is a no-op unless the current thread's {@link
2346 * android.os.StrictMode.ThreadPolicy} has {@link
2347 * android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls} enabled.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002348 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002349 * @param name a short string for the exception stack trace that's built if when this fires.
Brad Fitzpatricke36f9bf2010-12-10 13:29:17 -08002350 */
2351 public static void noteSlowCall(String name) {
2352 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2353 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2354 // StrictMode not enabled.
2355 return;
2356 }
2357 ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
2358 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002359
2360 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002361 * For code to note that a resource was obtained using a type other than its defined type. This
2362 * is a no-op unless the current thread's {@link android.os.StrictMode.ThreadPolicy} has {@link
2363 * android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()} enabled.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08002364 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002365 * @param tag an object for the exception stack trace that's built if when this fires.
Alan Viverette6bbb47b2015-01-05 18:12:44 -08002366 * @hide
2367 */
2368 public static void noteResourceMismatch(Object tag) {
2369 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2370 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2371 // StrictMode not enabled.
2372 return;
2373 }
2374 ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag);
2375 }
2376
Kurt Nelson46974a22017-08-30 13:30:26 -07002377 /** @hide */
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01002378 public static void noteUnbufferedIO() {
2379 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2380 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2381 // StrictMode not enabled.
2382 return;
2383 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002384 policy.onUnbufferedIO();
Shubham Ajmera9b7184a2016-06-28 16:32:02 +01002385 }
2386
Kurt Nelson46974a22017-08-30 13:30:26 -07002387 /** @hide */
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002388 public static void noteDiskRead() {
2389 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002390 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2391 // StrictMode not enabled.
2392 return;
2393 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002394 policy.onReadFromDisk();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002395 }
2396
Kurt Nelson46974a22017-08-30 13:30:26 -07002397 /** @hide */
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002398 public static void noteDiskWrite() {
2399 BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
2400 if (!(policy instanceof AndroidBlockGuardPolicy)) {
2401 // StrictMode not enabled.
2402 return;
2403 }
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002404 policy.onWriteToDisk();
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002405 }
2406
Kurt Nelson1981f422017-10-25 13:49:26 -07002407 @GuardedBy("StrictMode.class")
2408 private static final HashMap<Class, Integer> sExpectedActivityInstanceCount = new HashMap<>();
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002409
Brad Fitzpatrick4e920f72010-12-14 11:52:13 -08002410 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002411 * Returns an object that is used to track instances of activites. The activity should store a
2412 * reference to the tracker object in one of its fields.
2413 *
Jeff Brown7e442832011-06-10 18:00:16 -07002414 * @hide
2415 */
2416 public static Object trackActivity(Object instance) {
2417 return new InstanceTracker(instance);
2418 }
2419
Kurt Nelson46974a22017-08-30 13:30:26 -07002420 /** @hide */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002421 public static void incrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002422 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002423 return;
2424 }
Jeff Brown7e442832011-06-10 18:00:16 -07002425
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002426 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002427 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2428 return;
2429 }
2430
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002431 Integer expected = sExpectedActivityInstanceCount.get(klass);
2432 Integer newExpected = expected == null ? 1 : expected + 1;
2433 sExpectedActivityInstanceCount.put(klass, newExpected);
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002434 }
2435 }
2436
Kurt Nelson46974a22017-08-30 13:30:26 -07002437 /** @hide */
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002438 public static void decrementExpectedActivityCount(Class klass) {
Jeff Brown7e442832011-06-10 18:00:16 -07002439 if (klass == null) {
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002440 return;
2441 }
Jeff Brown7e442832011-06-10 18:00:16 -07002442
2443 final int limit;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002444 synchronized (StrictMode.class) {
Jeff Brown7e442832011-06-10 18:00:16 -07002445 if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
2446 return;
2447 }
2448
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002449 Integer expected = sExpectedActivityInstanceCount.get(klass);
Jeff Brown7e442832011-06-10 18:00:16 -07002450 int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002451 if (newExpected == 0) {
2452 sExpectedActivityInstanceCount.remove(klass);
2453 } else {
2454 sExpectedActivityInstanceCount.put(klass, newExpected);
2455 }
Jeff Brown7e442832011-06-10 18:00:16 -07002456
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002457 // Note: adding 1 here to give some breathing room during
2458 // orientation changes. (shouldn't be necessary, though?)
Jeff Brown7e442832011-06-10 18:00:16 -07002459 limit = newExpected + 1;
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002460 }
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002461
Jeff Brown7e442832011-06-10 18:00:16 -07002462 // Quick check.
2463 int actual = InstanceTracker.getInstanceCount(klass);
2464 if (actual <= limit) {
2465 return;
2466 }
2467
2468 // Do a GC and explicit count to double-check.
2469 // This is the work that we are trying to avoid by tracking the object instances
2470 // explicity. Running an explicit GC can be expensive (80ms) and so can walking
2471 // the heap to count instance (30ms). This extra work can make the system feel
2472 // noticeably less responsive during orientation changes when activities are
2473 // being restarted. Granted, it is only a problem when StrictMode is enabled
2474 // but it is annoying.
Jeff Sharkey6f3a38f2014-01-16 12:46:37 -08002475
2476 System.gc();
2477 System.runFinalization();
2478 System.gc();
Jeff Brown7e442832011-06-10 18:00:16 -07002479
2480 long instances = VMDebug.countInstancesOfClass(klass, false);
2481 if (instances > limit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002482 onVmPolicyViolation(new InstanceCountViolation(klass, instances, limit));
Brad Fitzpatrick5f8b5c12011-01-20 15:12:08 -08002483 }
Brad Fitzpatrick75803572011-01-13 14:21:03 -08002484 }
2485
2486 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002487 * Parcelable that gets sent in Binder call headers back to callers to report violations that
2488 * happened during a cross-process call.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002489 *
2490 * @hide
2491 */
Kurt Nelson7d5c07a2017-09-07 16:43:45 -07002492 @TestApi
2493 public static final class ViolationInfo implements Parcelable {
Kurt Nelson0918c932017-09-07 10:56:56 -07002494 /** Stack and violation details. */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002495 private final Violation mViolation;
Kurt Nelson0918c932017-09-07 10:56:56 -07002496
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002497 /** Path leading to a violation that occurred across binder. */
2498 private final Deque<StackTraceElement[]> mBinderStack = new ArrayDeque<>();
Kurt Nelson0918c932017-09-07 10:56:56 -07002499
2500 /** Memoized stack trace of full violation. */
2501 @Nullable private String mStackTrace;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002502
Kurt Nelson46974a22017-08-30 13:30:26 -07002503 /** The strict mode policy mask at the time of violation. */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002504 private final int mPolicy;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002505
Kurt Nelson46974a22017-08-30 13:30:26 -07002506 /** The wall time duration of the violation, when known. -1 when not known. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002507 public int durationMillis = -1;
2508
Kurt Nelson46974a22017-08-30 13:30:26 -07002509 /** The number of animations currently running. */
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002510 public int numAnimationsRunning = 0;
2511
Kurt Nelson46974a22017-08-30 13:30:26 -07002512 /** List of tags from active Span instances during this violation, or null for none. */
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002513 public String[] tags;
2514
2515 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002516 * Which violation number this was (1-based) since the last Looper loop, from the
2517 * perspective of the root caller (if it crossed any processes via Binder calls). The value
2518 * is 0 if the root caller wasn't on a Looper thread.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002519 */
2520 public int violationNumThisLoop;
2521
Kurt Nelson46974a22017-08-30 13:30:26 -07002522 /** The time (in terms of SystemClock.uptimeMillis()) that the violation occurred. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002523 public long violationUptimeMillis;
2524
2525 /**
Kurt Nelson46974a22017-08-30 13:30:26 -07002526 * The action of the Intent being broadcast to somebody's onReceive on this thread right
2527 * now, or null.
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002528 */
2529 public String broadcastIntentAction;
2530
Kurt Nelson46974a22017-08-30 13:30:26 -07002531 /** If this is a instance count violation, the number of instances in memory, else -1. */
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002532 public long numInstances = -1;
2533
Kurt Nelson9bcd7e92017-10-25 13:38:06 -07002534 /** Create an instance of ViolationInfo initialized from an exception. */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002535 ViolationInfo(Violation tr, int policy) {
2536 this.mViolation = tr;
2537 this.mPolicy = policy;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002538 violationUptimeMillis = SystemClock.uptimeMillis();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002539 this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002540 Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
2541 if (broadcastIntent != null) {
2542 broadcastIntentAction = broadcastIntent.getAction();
2543 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002544 ThreadSpanState state = sThisThreadSpanState.get();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002545 if (tr instanceof InstanceCountViolation) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002546 this.numInstances = ((InstanceCountViolation) tr).getNumberOfInstances();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002547 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002548 synchronized (state) {
2549 int spanActiveCount = state.mActiveSize;
2550 if (spanActiveCount > MAX_SPAN_TAGS) {
2551 spanActiveCount = MAX_SPAN_TAGS;
2552 }
2553 if (spanActiveCount != 0) {
2554 this.tags = new String[spanActiveCount];
2555 Span iter = state.mActiveHead;
2556 int index = 0;
2557 while (iter != null && index < spanActiveCount) {
2558 this.tags[index] = iter.mName;
2559 index++;
2560 iter = iter.mNext;
2561 }
2562 }
2563 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002564 }
2565
Kurt Nelson0918c932017-09-07 10:56:56 -07002566 /** Equivalent output to {@link ApplicationErrorReport.CrashInfo#stackTrace}. */
2567 public String getStackTrace() {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002568 if (mStackTrace == null) {
Kurt Nelson0918c932017-09-07 10:56:56 -07002569 StringWriter sw = new StringWriter();
2570 PrintWriter pw = new FastPrintWriter(sw, false, 256);
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002571 mViolation.printStackTrace(pw);
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002572 for (StackTraceElement[] traces : mBinderStack) {
Kurt Nelson0918c932017-09-07 10:56:56 -07002573 pw.append("# via Binder call with stack:\n");
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002574 for (StackTraceElement traceElement : traces) {
2575 pw.append("\tat ");
2576 pw.append(traceElement.toString());
2577 pw.append('\n');
2578 }
Kurt Nelson0918c932017-09-07 10:56:56 -07002579 }
2580 pw.flush();
2581 pw.close();
2582 mStackTrace = sw.toString();
2583 }
2584 return mStackTrace;
2585 }
2586
2587 /**
2588 * Optional message describing this violation.
2589 *
2590 * @hide
2591 */
2592 @TestApi
2593 public String getViolationDetails() {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002594 return mViolation.getMessage();
Kurt Nelson0918c932017-09-07 10:56:56 -07002595 }
2596
2597 /**
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002598 * Policy mask at time of violation.
Kurt Nelson0918c932017-09-07 10:56:56 -07002599 *
2600 * @hide
2601 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002602 @TestApi
2603 public int getPolicyMask() {
2604 return mPolicy;
2605 }
2606
2607 boolean penaltyEnabled(int p) {
2608 return (mPolicy & p) != 0;
Kurt Nelson0918c932017-09-07 10:56:56 -07002609 }
2610
2611 /**
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002612 * Add a {@link Throwable} from the current process that caused the underlying violation. We
2613 * only preserve the stack trace elements.
Kurt Nelson0918c932017-09-07 10:56:56 -07002614 *
2615 * @hide
2616 */
2617 void addLocalStack(Throwable t) {
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002618 mBinderStack.addFirst(t.getStackTrace());
Kurt Nelson0918c932017-09-07 10:56:56 -07002619 }
2620
2621 /**
2622 * Retrieve the type of StrictMode violation.
2623 *
2624 * @hide
2625 */
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002626 @TestApi
2627 public int getViolationBit() {
2628 if (mViolation instanceof DiskWriteViolation) {
2629 return DETECT_DISK_WRITE;
2630 } else if (mViolation instanceof DiskReadViolation) {
2631 return DETECT_DISK_READ;
2632 } else if (mViolation instanceof NetworkViolation) {
2633 return DETECT_NETWORK;
2634 } else if (mViolation instanceof CustomViolation) {
2635 return DETECT_CUSTOM;
2636 } else if (mViolation instanceof ResourceMismatchViolation) {
2637 return DETECT_RESOURCE_MISMATCH;
Kurt Nelson0e612802017-11-09 17:25:40 -08002638 } else if (mViolation instanceof UnbufferedIoViolation) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002639 return DETECT_UNBUFFERED_IO;
2640 } else if (mViolation instanceof SqliteObjectLeakedViolation) {
2641 return DETECT_VM_CURSOR_LEAKS;
2642 } else if (mViolation instanceof LeakedClosableViolation) {
2643 return DETECT_VM_CLOSABLE_LEAKS;
2644 } else if (mViolation instanceof InstanceCountViolation) {
2645 return DETECT_VM_INSTANCE_LEAKS;
2646 } else if (mViolation instanceof IntentReceiverLeakedViolation) {
2647 return DETECT_VM_REGISTRATION_LEAKS;
2648 } else if (mViolation instanceof ServiceConnectionLeakedViolation) {
2649 return DETECT_VM_REGISTRATION_LEAKS;
2650 } else if (mViolation instanceof FileUriExposedViolation) {
2651 return DETECT_VM_FILE_URI_EXPOSURE;
2652 } else if (mViolation instanceof CleartextNetworkViolation) {
2653 return DETECT_VM_CLEARTEXT_NETWORK;
2654 } else if (mViolation instanceof ContentUriWithoutPermissionViolation) {
2655 return DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION;
2656 } else if (mViolation instanceof UntaggedSocketViolation) {
2657 return DETECT_VM_UNTAGGED_SOCKET;
Pete Gillin22316b42018-02-15 17:17:27 +00002658 } else if (mViolation instanceof ExplicitGcViolation) {
2659 return DETECT_EXPLICIT_GC;
Narayan Kamathad1b2a92018-03-28 11:29:40 +01002660 } else if (mViolation instanceof NonSdkApiUsedViolation) {
2661 return DETECT_VM_NON_SDK_API_USAGE;
Kurt Nelson0918c932017-09-07 10:56:56 -07002662 }
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002663 throw new IllegalStateException("missing violation bit");
Kurt Nelson0918c932017-09-07 10:56:56 -07002664 }
2665
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002666 @Override
2667 public int hashCode() {
2668 int result = 17;
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002669 if (mViolation != null) {
2670 result = 37 * result + mViolation.hashCode();
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002671 }
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08002672 if (numAnimationsRunning != 0) {
2673 result *= 37;
2674 }
2675 if (broadcastIntentAction != null) {
2676 result = 37 * result + broadcastIntentAction.hashCode();
2677 }
2678 if (tags != null) {
2679 for (String tag : tags) {
2680 result = 37 * result + tag.hashCode();
2681 }
2682 }
2683 return result;
2684 }
2685
Kurt Nelson46974a22017-08-30 13:30:26 -07002686 /** Create an instance of ViolationInfo initialized from a Parcel. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002687 public ViolationInfo(Parcel in) {
2688 this(in, false);
2689 }
2690
2691 /**
2692 * Create an instance of ViolationInfo initialized from a Parcel.
2693 *
Kurt Nelson46974a22017-08-30 13:30:26 -07002694 * @param unsetGatheringBit if true, the caller is the root caller and the gathering penalty
2695 * should be removed.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002696 */
2697 public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002698 mViolation = (Violation) in.readSerializable();
Kurt Nelson0918c932017-09-07 10:56:56 -07002699 int binderStackSize = in.readInt();
2700 for (int i = 0; i < binderStackSize; i++) {
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002701 StackTraceElement[] traceElements = new StackTraceElement[in.readInt()];
2702 for (int j = 0; j < traceElements.length; j++) {
2703 StackTraceElement element =
2704 new StackTraceElement(
2705 in.readString(),
2706 in.readString(),
2707 in.readString(),
2708 in.readInt());
2709 traceElements[j] = element;
2710 }
2711 mBinderStack.add(traceElements);
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002712 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002713 int rawPolicy = in.readInt();
2714 if (unsetGatheringBit) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002715 mPolicy = rawPolicy & ~PENALTY_GATHER;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002716 } else {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002717 mPolicy = rawPolicy;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002718 }
2719 durationMillis = in.readInt();
2720 violationNumThisLoop = in.readInt();
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002721 numAnimationsRunning = in.readInt();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002722 violationUptimeMillis = in.readLong();
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002723 numInstances = in.readLong();
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002724 broadcastIntentAction = in.readString();
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002725 tags = in.readStringArray();
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002726 }
2727
Kurt Nelson46974a22017-08-30 13:30:26 -07002728 /** Save a ViolationInfo instance to a parcel. */
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07002729 @Override
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002730 public void writeToParcel(Parcel dest, int flags) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002731 dest.writeSerializable(mViolation);
Kurt Nelson0918c932017-09-07 10:56:56 -07002732 dest.writeInt(mBinderStack.size());
Kurt Nelson87dd8bc2017-10-25 15:24:15 -07002733 for (StackTraceElement[] traceElements : mBinderStack) {
2734 dest.writeInt(traceElements.length);
2735 for (StackTraceElement element : traceElements) {
2736 dest.writeString(element.getClassName());
2737 dest.writeString(element.getMethodName());
2738 dest.writeString(element.getFileName());
2739 dest.writeInt(element.getLineNumber());
2740 }
Jeff Sharkey58f27b52016-12-06 16:47:00 -07002741 }
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002742 int start = dest.dataPosition();
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002743 dest.writeInt(mPolicy);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002744 dest.writeInt(durationMillis);
2745 dest.writeInt(violationNumThisLoop);
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002746 dest.writeInt(numAnimationsRunning);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002747 dest.writeLong(violationUptimeMillis);
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002748 dest.writeLong(numInstances);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002749 dest.writeString(broadcastIntentAction);
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002750 dest.writeStringArray(tags);
Kurt Nelson46974a22017-08-30 13:30:26 -07002751 int total = dest.dataPosition() - start;
2752 if (Binder.CHECK_PARCEL_SIZE && total > 10 * 1024) {
2753 Slog.d(
2754 TAG,
2755 "VIO: policy="
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002756 + mPolicy
Kurt Nelson46974a22017-08-30 13:30:26 -07002757 + " dur="
2758 + durationMillis
2759 + " numLoop="
2760 + violationNumThisLoop
2761 + " anim="
2762 + numAnimationsRunning
2763 + " uptime="
2764 + violationUptimeMillis
2765 + " numInst="
2766 + numInstances);
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002767 Slog.d(TAG, "VIO: action=" + broadcastIntentAction);
2768 Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags));
Kurt Nelson46974a22017-08-30 13:30:26 -07002769 Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition() - start));
Dianne Hackborn73d6a822014-09-29 10:52:47 -07002770 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002771 }
2772
Kurt Nelson46974a22017-08-30 13:30:26 -07002773 /** Dump a ViolationInfo instance to a Printer. */
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002774 public void dump(Printer pw, String prefix) {
Kurt Nelson1bb93bf2017-10-26 18:06:12 -07002775 pw.println(prefix + "stackTrace: " + getStackTrace());
2776 pw.println(prefix + "policy: " + mPolicy);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002777 if (durationMillis != -1) {
2778 pw.println(prefix + "durationMillis: " + durationMillis);
2779 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002780 if (numInstances != -1) {
2781 pw.println(prefix + "numInstances: " + numInstances);
2782 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002783 if (violationNumThisLoop != 0) {
2784 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
2785 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07002786 if (numAnimationsRunning != 0) {
2787 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
2788 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002789 pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07002790 if (broadcastIntentAction != null) {
2791 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
2792 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08002793 if (tags != null) {
2794 int index = 0;
2795 for (String tag : tags) {
2796 pw.println(prefix + "tag[" + (index++) + "]: " + tag);
2797 }
2798 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002799 }
2800
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07002801 @Override
2802 public int describeContents() {
2803 return 0;
2804 }
2805
2806 public static final Parcelable.Creator<ViolationInfo> CREATOR =
2807 new Parcelable.Creator<ViolationInfo>() {
2808 @Override
2809 public ViolationInfo createFromParcel(Parcel in) {
2810 return new ViolationInfo(in);
2811 }
2812
2813 @Override
2814 public ViolationInfo[] newArray(int size) {
2815 return new ViolationInfo[size];
2816 }
2817 };
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07002818 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08002819
Jeff Brown7e442832011-06-10 18:00:16 -07002820 private static final class InstanceTracker {
2821 private static final HashMap<Class<?>, Integer> sInstanceCounts =
2822 new HashMap<Class<?>, Integer>();
2823
2824 private final Class<?> mKlass;
2825
2826 public InstanceTracker(Object instance) {
2827 mKlass = instance.getClass();
2828
2829 synchronized (sInstanceCounts) {
2830 final Integer value = sInstanceCounts.get(mKlass);
2831 final int newValue = value != null ? value + 1 : 1;
2832 sInstanceCounts.put(mKlass, newValue);
2833 }
2834 }
2835
2836 @Override
2837 protected void finalize() throws Throwable {
2838 try {
2839 synchronized (sInstanceCounts) {
2840 final Integer value = sInstanceCounts.get(mKlass);
2841 if (value != null) {
2842 final int newValue = value - 1;
2843 if (newValue > 0) {
2844 sInstanceCounts.put(mKlass, newValue);
2845 } else {
2846 sInstanceCounts.remove(mKlass);
2847 }
2848 }
2849 }
2850 } finally {
2851 super.finalize();
2852 }
2853 }
2854
2855 public static int getInstanceCount(Class<?> klass) {
2856 synchronized (sInstanceCounts) {
2857 final Integer value = sInstanceCounts.get(klass);
2858 return value != null ? value : 0;
2859 }
2860 }
2861 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07002862}