StrictMode.java revision 599ca29986235e07f532c7b112507f6c39b5dba9
1438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick/* 2438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Copyright (C) 2010 The Android Open Source Project 3438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * 4438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Licensed under the Apache License, Version 2.0 (the "License"); 5438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * you may not use this file except in compliance with the License. 6438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * You may obtain a copy of the License at 7438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * 8438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * http://www.apache.org/licenses/LICENSE-2.0 9438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * 10438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Unless required by applicable law or agreed to in writing, software 11438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * distributed under the License is distributed on an "AS IS" BASIS, 12438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * See the License for the specific language governing permissions and 14438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * limitations under the License. 15438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 16438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickpackage android.os; 17438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 18599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrickimport android.animation.ValueAnimator; 19438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport android.app.ActivityManagerNative; 20438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport android.app.ApplicationErrorReport; 21438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport android.util.Log; 22cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrickimport android.util.Printer; 23438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 24438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport com.android.internal.os.RuntimeInit; 25438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 26438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport dalvik.system.BlockGuard; 27438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 285b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrickimport java.io.PrintWriter; 295b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrickimport java.io.StringWriter; 305b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrickimport java.util.ArrayList; 3146d42387464a651268648659e91d022566d4844cBrad Fitzpatrickimport java.util.HashMap; 3246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 33438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick/** 3432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>StrictMode is a developer tool which detects things you might be 3532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * doing by accident and brings them to your attention so you can fix 3632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * them. 3715ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * 3815ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * <p>StrictMode is most commonly used to catch accidental disk or 3915ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * network access on the application's main thread, where UI 4015ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * operations are received and animations take place. Keeping disk 4115ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * and network operations off the main thread makes for much smoother, 429fc2fc5757a3d28d098bd2b0ad0f869a3cf3fa14Brad Fitzpatrick * more responsive applications. By keeping your application's main thread 439fc2fc5757a3d28d098bd2b0ad0f869a3cf3fa14Brad Fitzpatrick * responsive, you also prevent 449fc2fc5757a3d28d098bd2b0ad0f869a3cf3fa14Brad Fitzpatrick * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a> 459fc2fc5757a3d28d098bd2b0ad0f869a3cf3fa14Brad Fitzpatrick * from being shown to users. 4615ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * 4715ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * <p class="note">Note that even though an Android device's disk is 4815ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * often on flash memory, many devices run a filesystem on top of that 4915ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * memory with very limited concurrency. It's often the case that 5015ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * almost all disk accesses are fast, but may in individual cases be 5115ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * dramatically slower when certain I/O is happening in the background 5215ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * from other processes. If possible, it's best to assume that such 5315ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * things are not fast.</p> 5415ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * 5515ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * <p>Example code to enable from early in your 5615ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * {@link android.app.Application}, {@link android.app.Activity}, or 5715ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * other application component's 5815ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * {@link android.app.Application#onCreate} method: 5915ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * 6015ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * <pre> 6115ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * public void onCreate() { 6215ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * if (DEVELOPER_MODE) { 6332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}() 6432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .detectDiskReads() 6532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .detectDiskWrites() 6632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .detectNetwork() // or .detectAll() for all detectable problems 6732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .penaltyLog() 6832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .build()); 6932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}() 7062a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick * .detectLeakedSqlLiteObjects() 7132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .penaltyLog() 7232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .penaltyDeath() 7332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .build()); 7415ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * } 7515ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * super.onCreate(); 7615ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * } 7715ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * </pre> 7815ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * 7932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>You can decide what should happen when a violation is detected. 8032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can 8132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * watch the output of <code>adb logcat</code> while you use your 8232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * application to see the violations as they happen. 8315ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * 8415ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * <p>If you find violations that you feel are problematic, there are 8515ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * a variety of tools to help solve them: threads, {@link android.os.Handler}, 8615ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc. 8715ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * But don't feel compelled to fix everything that StrictMode finds. In particular, 8832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * many cases of disk access are often necessary during the normal activity lifecycle. Use 8932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * StrictMode to find things you did by accident. Network requests on the UI thread 9015ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * are almost always a problem, though. 9115ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * 9215ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * <p class="note">StrictMode is not a security mechanism and is not 9315ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * guaranteed to find all disk or network accesses. While it does 9415ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * propagate its state across process boundaries when doing 9515ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * {@link android.os.Binder} calls, it's still ultimately a best 9615ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * effort mechanism. Notably, disk or network access from JNI calls 9715ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * won't necessarily trigger it. Future versions of Android may catch 9815ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * more (or fewer) operations, so you should never leave StrictMode 9915ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * enabled in shipping applications on the Android Market. 100438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 101438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickpublic final class StrictMode { 102438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private static final String TAG = "StrictMode"; 1035b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static final boolean LOG_V = false; 104438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 10546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Only log a duplicate stack trace to the logs every second. 10646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick private static final long MIN_LOG_INTERVAL_MS = 1000; 10746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 10846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Only show an annoying dialog at most every 30 seconds 10946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick private static final long MIN_DIALOG_INTERVAL_MS = 30000; 11046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 111191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick // How many offending stacks to keep track of (and time) per loop 112191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick // of the Looper. 113191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick private static final int MAX_OFFENSES_PER_LOOP = 10; 114191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick 11532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // Thread-policy: 116438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 11715ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick /** 11832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 11915ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick */ 12032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy 12115ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick 12215ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick /** 12332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 12415ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick */ 12532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy 12615ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick 12715ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick /** 12832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 12915ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick */ 13032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy 131438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 13232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // Process-policy: 133438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 134438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 13532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Note, a "VM_" bit, not thread. 13632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 13732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 13832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final int DETECT_VM_CURSOR_LEAKS = 0x200; // for ProcessPolicy 13932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 14032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 14132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 142438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 143438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_LOG = 0x10; // normal android.util.Log 144438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 14532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // Used for both process and thread policy: 14632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 147438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 14832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 149438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 150438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_DIALOG = 0x20; 151438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 152438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 15332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 154438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 155438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_DEATH = 0x40; 156438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 157438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 15832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 159438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 160438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_DROPBOX = 0x80; 161438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 162727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick /** 163727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * Non-public penalty mode which overrides all the other penalty 164727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * bits and signals that we're in a Binder call and we should 165727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * ignore the other penalty bits and instead serialize back all 166727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * our offending stack traces to the caller to ultimately handle 167727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * in the originating process. 168727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * 169703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * This must be kept in sync with the constant in libs/binder/Parcel.cpp 170703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * 171727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * @hide 172727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick */ 173727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick public static final int PENALTY_GATHER = 0x100; 174727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 17532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 17632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * The current VmPolicy in effect. 17732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 17832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private static volatile int sVmPolicyMask = 0; 17932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 18032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private StrictMode() {} 18132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 18232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 18332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * {@link StrictMode} policy applied to a certain thread. 18432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 18532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy 18632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * can be retrieved with {@link #getThreadPolicy}. 18732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 18832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>Note that multiple penalties may be provided and they're run 18932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * in order from least to most severe (logging before process 19032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * death, for example). There's currently no mechanism to choose 19132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * different penalties for different detected actions. 19232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 19332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final class ThreadPolicy { 19432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 19532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * The default, lax policy which doesn't catch anything. 19632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 19732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final ThreadPolicy LAX = new ThreadPolicy(0); 19832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 19932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick final int mask; 20032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 20132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private ThreadPolicy(int mask) { 20232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick this.mask = mask; 20332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 20432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 20532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick @Override 20632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public String toString() { 20732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return "[StrictMode.ThreadPolicy; mask=" + mask + "]"; 20832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 20932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 21032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 21132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Creates ThreadPolicy instances. Methods whose names start 21232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * with {@code detect} specify what problems we should look 21332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * for. Methods whose names start with {@code penalty} specify what 21432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * we should do when we detect a problem. 21532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 21632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>You can call as many {@code detect} and {@code penalty} 21732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * methods as you like. Currently order is insignificant: all 21832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * penalties apply to all detected problems. 21932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 22032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>For example, detect everything and log anything that's found: 22132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <pre> 22232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder() 22332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .detectAll() 22432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .penaltyLog() 22532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .build(); 22632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * StrictMode.setVmPolicy(policy); 22732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * </pre> 22832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 22932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final class Builder { 23032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private int mMask = 0; 23132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 23232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 23332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Create a Builder that detects nothing and has no 23432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * violations. (but note that {@link #build} will default 23532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * to enabling {@link #penaltyLog} if no other penalties 23632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * are specified) 23732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 23832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder() { 23932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick mMask = 0; 24032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 24132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 24232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 24332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Initialize a Builder from an existing ThreadPolicy. 24432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 24532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder(ThreadPolicy policy) { 24632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick mMask = policy.mask; 24732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 24832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 24932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 25032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Detect everything that's potentially suspect. 25132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 25232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>As of the Gingerbread release this includes network and 25332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * disk operations but will likely expand in future releases. 25432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 25532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder detectAll() { 25632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK); 25732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 25832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 25932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 26032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Disable the detection of everything. 26132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 26232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder permitAll() { 26332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return disable(DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK); 26432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 26532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 26632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 26732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Enable detection of network operations. 26832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 26932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder detectNetwork() { 27032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(DETECT_NETWORK); 27132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 27232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 27332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 27432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Disable detection of network operations. 27532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 27632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder permitNetwork() { 27732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return disable(DETECT_NETWORK); 27832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 27932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 28032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 28132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Enable detection of disk reads. 28232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 28332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder detectDiskReads() { 28432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(DETECT_DISK_READ); 28532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 28632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 28732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 28832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Disable detection of disk reads. 28932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 29032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder permitDiskReads() { 29132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return disable(DETECT_DISK_READ); 29232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 29332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 29432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 29532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Enable detection of disk writes. 29632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 29732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder detectDiskWrites() { 29832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(DETECT_DISK_WRITE); 29932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 30032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 30132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 30232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Disable detection of disk writes. 30332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 30432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder permitDiskWrites() { 30532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return disable(DETECT_DISK_WRITE); 30632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 30732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 30832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 30932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Show an annoying dialog to the developer on detected 31032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * violations, rate-limited to be only a little annoying. 31132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 31232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder penaltyDialog() { 31332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(PENALTY_DIALOG); 31432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 31532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 31632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 31732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Crash the whole process on violation. This penalty runs at 31832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * the end of all enabled penalties so you'll still get 31932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * see logging or other violations before the process dies. 32032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 32132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder penaltyDeath() { 32232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(PENALTY_DEATH); 32332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 32432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 32532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 32632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Log detected violations to the system log. 32732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 32832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder penaltyLog() { 32932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(PENALTY_LOG); 33032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 33132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 33232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 33332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Enable detected violations log a stacktrace and timing data 33432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * to the {@link android.os.DropBoxManager DropBox} on policy 33532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * violation. Intended mostly for platform integrators doing 33632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * beta user field data collection. 33732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 33832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder penaltyDropBox() { 33932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(PENALTY_DROPBOX); 34032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 34132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 34232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private Builder enable(int bit) { 34332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick mMask |= bit; 34432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return this; 34532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 34632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 34732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private Builder disable(int bit) { 34832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick mMask &= ~bit; 34932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return this; 35032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 35132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 35232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 35332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Construct the ThreadPolicy instance. 35432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 35532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>Note: if no penalties are enabled before calling 35632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <code>build</code>, {@link #penaltyLog} is implicitly 35732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * set. 35832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 35932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public ThreadPolicy build() { 36032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // If there are detection bits set but no violation bits 36132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // set, enable simple logging. 36232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if (mMask != 0 && 36332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick (mMask & (PENALTY_DEATH | PENALTY_LOG | 36432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) { 36532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick penaltyLog(); 36632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 36732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return new ThreadPolicy(mMask); 36832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 36932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 37032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 37132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 37232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 37332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * {@link StrictMode} policy applied to all threads in the virtual machine's process. 37432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 37532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>The policy is enabled by {@link #setVmPolicy}. 37632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 37732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final class VmPolicy { 37832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 37932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * The default, lax policy which doesn't catch anything. 38032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 38132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final VmPolicy LAX = new VmPolicy(0); 38232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 38332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick final int mask; 38432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 38532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private VmPolicy(int mask) { 38632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick this.mask = mask; 38732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 38832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 38932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick @Override 39032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public String toString() { 39132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return "[StrictMode.VmPolicy; mask=" + mask + "]"; 39232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 39332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 39432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 39532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Creates {@link VmPolicy} instances. Methods whose names start 39632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * with {@code detect} specify what problems we should look 39732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * for. Methods whose names start with {@code penalty} specify what 39832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * we should do when we detect a problem. 39932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 40032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>You can call as many {@code detect} and {@code penalty} 40132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * methods as you like. Currently order is insignificant: all 40232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * penalties apply to all detected problems. 40332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 40432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>For example, detect everything and log anything that's found: 40532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <pre> 40632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder() 40732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .detectAll() 40832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .penaltyLog() 40932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * .build(); 41032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * StrictMode.setVmPolicy(policy); 41132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * </pre> 41232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 41332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static final class Builder { 41432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private int mMask; 41532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 41632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 41732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Detect everything that's potentially suspect. 41832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 41932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>As of the Gingerbread release this only includes 42032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * SQLite cursor leaks but will likely expand in future 42132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * releases. 42232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 42332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder detectAll() { 42432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(DETECT_VM_CURSOR_LEAKS); 42532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 42632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 42732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 42832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Detect when an 42932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * {@link android.database.sqlite.SQLiteCursor} or other 43032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * SQLite object is finalized without having been closed. 43132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 43232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>You always want to explicitly close your SQLite 43332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * cursors to avoid unnecessary database contention and 43432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * temporary memory leaks. 43532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 43632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder detectLeakedSqlLiteObjects() { 43732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(DETECT_VM_CURSOR_LEAKS); 43832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 43932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 44032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 44132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Crashes the whole process on violation. This penalty runs at 44232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * the end of all enabled penalties so yo you'll still get 44332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * your logging or other violations before the process dies. 44432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 44532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder penaltyDeath() { 44632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(PENALTY_DEATH); 44732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 44832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 44932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 45032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Log detected violations to the system log. 45132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 45232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder penaltyLog() { 45332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(PENALTY_LOG); 45432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 45532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 45632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 45732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Enable detected violations log a stacktrace and timing data 45832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * to the {@link android.os.DropBoxManager DropBox} on policy 45932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * violation. Intended mostly for platform integrators doing 46032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * beta user field data collection. 46132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 46232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public Builder penaltyDropBox() { 46332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return enable(PENALTY_DROPBOX); 46432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 46532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 46632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private Builder enable(int bit) { 46732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick mMask |= bit; 46832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return this; 46932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 47032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 47132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 47232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Construct the VmPolicy instance. 47332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 47432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>Note: if no penalties are enabled before calling 47532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <code>build</code>, {@link #penaltyLog} is implicitly 47632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * set. 47732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 47832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public VmPolicy build() { 47932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // If there are detection bits set but no violation bits 48032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // set, enable simple logging. 48132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if (mMask != 0 && 48232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick (mMask & (PENALTY_DEATH | PENALTY_LOG | 48332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) { 48432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick penaltyLog(); 48532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 48632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return new VmPolicy(mMask); 48732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 48832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 48932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 490438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 491438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 4925b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Log of strict mode violation stack traces that have occurred 4935b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * during a Binder call, to be serialized back later to the caller 4945b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * via Parcel.writeNoException() (amusingly) where the caller can 4955b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * choose how to react. 4965b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 497cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations = 498cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick new ThreadLocal<ArrayList<ViolationInfo>>() { 499cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick @Override protected ArrayList<ViolationInfo> initialValue() { 500703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick // Starts null to avoid unnecessary allocations when 501703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick // checking whether there are any violations or not in 502703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick // hasGatheredViolations() below. 503703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick return null; 5045b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5055b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick }; 5065b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 5075b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 50832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Sets the policy for what actions on the current thread should 50932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * be detected, as well as the penalty if such actions occur. 51015ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * 51132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * <p>Internally this sets a thread-local variable which is 51215ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * propagated across cross-process IPC calls, meaning you can 51315ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * catch violations when a system service or another process 51415ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * accesses the disk or network on your behalf. 515438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * 51632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @param policy the policy to put into place 517438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 51832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static void setThreadPolicy(final ThreadPolicy policy) { 51932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick setThreadPolicyMask(policy.mask); 52032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 52132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 52232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick private static void setThreadPolicyMask(final int policyMask) { 523727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // In addition to the Java-level thread-local in Dalvik's 524727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // BlockGuard, we also need to keep a native thread-local in 525727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // Binder in order to propagate the value across Binder calls, 526727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // even across native-only processes. The two are kept in 527727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // sync via the callback to onStrictModePolicyChange, below. 528727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setBlockGuardPolicy(policyMask); 529727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 530727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // And set the Android native version... 531727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick Binder.setThreadStrictModePolicy(policyMask); 532727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } 533727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 534727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // Sets the policy in Dalvik/libcore (BlockGuard) 535727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick private static void setBlockGuardPolicy(final int policyMask) { 53646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if (policyMask == 0) { 53746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY); 53846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick return; 53946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 540438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); 541438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if (!(policy instanceof AndroidBlockGuardPolicy)) { 542438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick BlockGuard.setThreadPolicy(new AndroidBlockGuardPolicy(policyMask)); 543438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } else { 544438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick AndroidBlockGuardPolicy androidPolicy = (AndroidBlockGuardPolicy) policy; 545438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick androidPolicy.setPolicyMask(policyMask); 546438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 547438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 548438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 5495b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class StrictModeNetworkViolation extends BlockGuard.BlockGuardPolicyException { 5505b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public StrictModeNetworkViolation(int policyMask) { 55132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick super(policyMask, DETECT_NETWORK); 5525b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5535b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5545b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 5555b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class StrictModeDiskReadViolation extends BlockGuard.BlockGuardPolicyException { 5565b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public StrictModeDiskReadViolation(int policyMask) { 55732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick super(policyMask, DETECT_DISK_READ); 5585b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5595b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5605b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 5615b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class StrictModeDiskWriteViolation extends BlockGuard.BlockGuardPolicyException { 5625b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public StrictModeDiskWriteViolation(int policyMask) { 56332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick super(policyMask, DETECT_DISK_WRITE); 5645b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5655b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5665b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 567438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 56815ba4061116e088d62a7e05a0037f294f31dff06Brad Fitzpatrick * Returns the bitmask of the current thread's policy. 569438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * 57032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled 57132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 57232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 573438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 57432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static int getThreadPolicyMask() { 575438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return BlockGuard.getThreadPolicy().getPolicyMask(); 576438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 577438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 5785b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 57932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Returns the current thread's policy. 58032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 58132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static ThreadPolicy getThreadPolicy() { 58232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return new ThreadPolicy(getThreadPolicyMask()); 58332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 58432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 58532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 58632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * A convenience wrapper that takes the current 58732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it 58832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * to permit both disk reads & writes, and sets the new policy 58932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * with {@link #setThreadPolicy}, returning the old policy so you 59032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * can restore it at the end of a block. 59197461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick * 59232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @return the old policy, to be passed to {@link #setThreadPolicy} to 59332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * restore the policy at the end of a block 59497461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick */ 59532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static ThreadPolicy allowThreadDiskWrites() { 59632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick int oldPolicyMask = getThreadPolicyMask(); 59732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ); 59832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if (newPolicyMask != oldPolicyMask) { 59932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick setThreadPolicyMask(newPolicyMask); 60097461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick } 60132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return new ThreadPolicy(oldPolicyMask); 60297461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick } 60397461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick 60497461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick /** 60532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * A convenience wrapper that takes the current 60632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it 60732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * to permit disk reads, and sets the new policy 60832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * with {@link #setThreadPolicy}, returning the old policy so you 60932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * can restore it at the end of a block. 61097461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick * 61132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @return the old policy, to be passed to setThreadPolicy to 61297461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick * restore the policy. 61397461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick */ 61432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static ThreadPolicy allowThreadDiskReads() { 61532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick int oldPolicyMask = getThreadPolicyMask(); 61632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ); 61732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if (newPolicyMask != oldPolicyMask) { 61832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick setThreadPolicyMask(newPolicyMask); 61997461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick } 62032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return new ThreadPolicy(oldPolicyMask); 62197461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick } 62297461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick 62397461bd25c3821f3fb6af9705f0612259c6b4492Brad Fitzpatrick /** 62450d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick * Enable DropBox logging for debug phone builds. 62550d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick * 62650d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick * @hide 62750d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick */ 62850d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick public static boolean conditionallyEnableDebugLogging() { 62950d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick // For debug builds, log event loop stalls to dropbox for analysis. 63050d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick // Similar logic also appears in ActivityThread.java for system apps. 63150d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick if ("user".equals(Build.TYPE)) { 63250d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick return false; 63350d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick } 63432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick StrictMode.setThreadPolicyMask( 63532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick StrictMode.DETECT_DISK_WRITE | 63632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick StrictMode.DETECT_DISK_READ | 63732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick StrictMode.DETECT_NETWORK | 63850d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick StrictMode.PENALTY_DROPBOX); 63932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick sVmPolicyMask = StrictMode.DETECT_VM_CURSOR_LEAKS | 64032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick StrictMode.PENALTY_DROPBOX | 64132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick StrictMode.PENALTY_LOG; 64250d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick return true; 64350d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick } 64450d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick 64550d66f9fcdac84b2af65a82be56728f54b1a7ef0Brad Fitzpatrick /** 6465b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Parses the BlockGuard policy mask out from the Exception's 6475b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * getMessage() String value. Kinda gross, but least 6485b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * invasive. :/ 6495b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * 6505b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Input is of form "policy=137 violation=64" 6515b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * 6525b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Returns 0 on failure, which is a valid policy, but not a 6535b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * valid policy during a violation (else there must've been 6545b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * some policy in effect to violate). 6555b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 6565b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static int parsePolicyFromMessage(String message) { 6575b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (message == null || !message.startsWith("policy=")) { 6585b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 6595b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 6605b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int spaceIndex = message.indexOf(' '); 6615b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (spaceIndex == -1) { 6625b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 6635b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 6645b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick String policyString = message.substring(7, spaceIndex); 6655b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick try { 6665b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return Integer.valueOf(policyString).intValue(); 6675b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } catch (NumberFormatException e) { 6685b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 6695b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 6705b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 6715b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 6725b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 6735b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Like parsePolicyFromMessage(), but returns the violation. 6745b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 6755b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static int parseViolationFromMessage(String message) { 6765b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (message == null) { 6775b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 6785b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 6795b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int violationIndex = message.indexOf("violation="); 6805b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (violationIndex == -1) { 6815b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 6825b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 6835b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick String violationString = message.substring(violationIndex + 10); 6845b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick try { 6855b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return Integer.valueOf(violationString).intValue(); 6865b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } catch (NumberFormatException e) { 6875b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 6885b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 6895b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 6905b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 691191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed = 692191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick new ThreadLocal<ArrayList<ViolationInfo>>() { 693191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick @Override protected ArrayList<ViolationInfo> initialValue() { 694191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick return new ArrayList<ViolationInfo>(); 695191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick } 696191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick }; 697191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick 698191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick private static boolean tooManyViolationsThisLoop() { 699191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP; 700191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick } 701191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick 702438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private static class AndroidBlockGuardPolicy implements BlockGuard.Policy { 703438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private int mPolicyMask; 70446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 70546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Map from violation stacktrace hashcode -> uptimeMillis of 70646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // last violation. No locking needed, as this is only 70746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // accessed by the same thread. 70846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>(); 709438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 710438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public AndroidBlockGuardPolicy(final int policyMask) { 711438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick mPolicyMask = policyMask; 712438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 713438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 7145b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick @Override 7155b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public String toString() { 7165b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask; 7175b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 7185b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 719438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 720438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public int getPolicyMask() { 721438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return mPolicyMask; 722438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 723438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 724438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 725438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void onWriteToDisk() { 72632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if ((mPolicyMask & DETECT_DISK_WRITE) == 0) { 727438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return; 728438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 729191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick if (tooManyViolationsThisLoop()) { 730191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick return; 731191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick } 732cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask); 733cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick e.fillInStackTrace(); 734cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick startHandlingViolationException(e); 735438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 736438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 737438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 738438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void onReadFromDisk() { 73932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if ((mPolicyMask & DETECT_DISK_READ) == 0) { 740438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return; 741438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 742191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick if (tooManyViolationsThisLoop()) { 743191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick return; 744191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick } 745cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask); 746cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick e.fillInStackTrace(); 747cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick startHandlingViolationException(e); 748438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 749438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 750438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 751438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void onNetwork() { 75232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if ((mPolicyMask & DETECT_NETWORK) == 0) { 753438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return; 754438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 755191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick if (tooManyViolationsThisLoop()) { 756191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick return; 757191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick } 758cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask); 759cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick e.fillInStackTrace(); 760cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick startHandlingViolationException(e); 761438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 762438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 763438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void setPolicyMask(int policyMask) { 764438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick mPolicyMask = policyMask; 765438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 766438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 7675b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Start handling a violation that just started and hasn't 7685b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // actually run yet (e.g. no disk write or network operation 7695b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // has yet occurred). This sees if we're in an event loop 7705b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // thread and, if so, uses it to roughly measure how long the 7715b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // violation took. 7725b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) { 773cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick final ViolationInfo info = new ViolationInfo(e, e.getPolicy()); 774cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info.violationUptimeMillis = SystemClock.uptimeMillis(); 775cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick handleViolationWithTimingAttempt(info); 776cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 777438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 778cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // Attempts to fill in the provided ViolationInfo's 779cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // durationMillis field if this thread has a Looper we can use 780cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // to measure with. We measure from the time of violation 781cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // until the time the looper is idle again (right before 782cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // the next epoll_wait) 783cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick void handleViolationWithTimingAttempt(final ViolationInfo info) { 784438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick Looper looper = Looper.myLooper(); 785cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 786cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // Without a Looper, we're unable to time how long the 787cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // violation takes place. This case should be rare, as 788cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // most users will care about timing violations that 789cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // happen on their main UI thread. Note that this case is 790cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // also hit when a violation takes place in a Binder 791cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // thread, in "gather" mode. In this case, the duration 792cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // of the violation is computed by the ultimate caller and 793cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // its Looper, if any. 794cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // TODO: if in gather mode, ignore Looper.myLooper() and always 795cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // go into this immediate mode? 796438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if (looper == null) { 797cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info.durationMillis = -1; // unknown (redundant, already set) 798cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick handleViolation(info); 799cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick return; 800438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 801438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 802cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick MessageQueue queue = Looper.myQueue(); 803cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick final ArrayList<ViolationInfo> records = violationsBeingTimed.get(); 804191cdf023c3c1ab441087a77f7881c7bb376613aBrad Fitzpatrick if (records.size() >= MAX_OFFENSES_PER_LOOP) { 805cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // Not worth measuring. Too many offenses in one loop. 806cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick return; 807cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 808cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick records.add(info); 809cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (records.size() > 1) { 810cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // There's already been a violation this loop, so we've already 811cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // registered an idle handler to process the list of violations 812cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // at the end of this Looper's loop. 813cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick return; 814cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 815cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 816cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick queue.addIdleHandler(new MessageQueue.IdleHandler() { 817cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public boolean queueIdle() { 818cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick long loopFinishTime = SystemClock.uptimeMillis(); 819cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick for (int n = 0; n < records.size(); ++n) { 820cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ViolationInfo v = records.get(n); 821cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick v.violationNumThisLoop = n + 1; 822cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick v.durationMillis = 823cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick (int) (loopFinishTime - v.violationUptimeMillis); 824cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick handleViolation(v); 825cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 826cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick records.clear(); 827cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick return false; // remove this idle handler from the array 828cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 829cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick }); 8305b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 831438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 8325b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Note: It's possible (even quite likely) that the 8335b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // thread-local policy mask has changed from the time the 8345b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // violation fired and now (after the violating code ran) due 8355b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // to people who push/pop temporary policy in regions of code, 8365b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // hence the policy being passed around. 837cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick void handleViolation(final ViolationInfo info) { 838cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) { 839cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick Log.wtf(TAG, "unexpected null stacktrace"); 8405b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return; 8415b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 842438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 843cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy); 84446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 845cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_GATHER) != 0) { 846cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ArrayList<ViolationInfo> violations = gatheredViolations.get(); 847703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick if (violations == null) { 848cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violations = new ArrayList<ViolationInfo>(1); 849703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick gatheredViolations.set(violations); 850703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } else if (violations.size() >= 5) { 8515b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Too many. In a loop or something? Don't gather them all. 8525b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return; 8535b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 854cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick for (ViolationInfo previous : violations) { 855cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) { 8565b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Duplicate. Don't log. 8575b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return; 8585b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 8595b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 860cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violations.add(info); 861727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick return; 862727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } 863727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 86446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Not perfect, but fast and good enough for dup suppression. 865cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick Integer crashFingerprint = info.crashInfo.stackTrace.hashCode(); 86646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick long lastViolationTime = 0; 86746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if (mLastViolationTime.containsKey(crashFingerprint)) { 86846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick lastViolationTime = mLastViolationTime.get(crashFingerprint); 86946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 87046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick long now = SystemClock.uptimeMillis(); 87146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick mLastViolationTime.put(crashFingerprint, now); 87246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick long timeSinceLastViolationMillis = lastViolationTime == 0 ? 87346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick Long.MAX_VALUE : (now - lastViolationTime); 87446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 875cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_LOG) != 0 && 87646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) { 877cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (info.durationMillis != -1) { 8785b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick Log.d(TAG, "StrictMode policy violation; ~duration=" + 879cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info.durationMillis + " ms: " + info.crashInfo.stackTrace); 880438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } else { 881cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace); 882438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 883438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 884438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 88546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // The violationMask, passed to ActivityManager, is a 88646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // subset of the original StrictMode policy bitmask, with 88746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // only the bit violated and penalty bits to be executed 88846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // by the ActivityManagerService remaining set. 889cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick int violationMaskSubset = 0; 89046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 891cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_DIALOG) != 0 && 89246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) { 893cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationMaskSubset |= PENALTY_DIALOG; 89446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 89546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 896cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) { 897cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationMaskSubset |= PENALTY_DROPBOX; 89846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 89946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 900cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (violationMaskSubset != 0) { 901cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage); 902cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationMaskSubset |= violationBit; 90332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick final int savedPolicyMask = getThreadPolicyMask(); 904438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick try { 905727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // First, remove any policy before we call into the Activity Manager, 906727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // otherwise we'll infinite recurse as we try to log policy violations 907727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // to disk, thus violating policy, thus requiring logging, etc... 908727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // We restore the current policy below, in the finally block. 90932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick setThreadPolicyMask(0); 910727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 911438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( 912438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick RuntimeInit.getApplicationObject(), 913cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationMaskSubset, 914cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info); 915438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } catch (RemoteException e) { 91646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); 917727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } finally { 918727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // Restore the policy. 91932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick setThreadPolicyMask(savedPolicyMask); 920438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 921438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 922438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 923cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_DEATH) != 0) { 924438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick System.err.println("StrictMode policy violation with POLICY_DEATH; shutting down."); 925438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick Process.killProcess(Process.myPid()); 926438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick System.exit(10); 927438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 928438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 929438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 930727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 931727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick /** 9325b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Called from Parcel.writeNoException() 9335b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 9345b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /* package */ static boolean hasGatheredViolations() { 935703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick return gatheredViolations.get() != null; 936703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } 937703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick 938703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick /** 939703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * Called from Parcel.writeException(), so we drop this memory and 940703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * don't incorrectly attribute it to the wrong caller on the next 941703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * Binder call on this thread. 942703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick */ 943703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick /* package */ static void clearGatheredViolations() { 944703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick gatheredViolations.set(null); 9455b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 9465b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 9475b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 94832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Sets the policy for what actions in the VM process (on any 94932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * thread) should be detected, as well as the penalty if such 95032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * actions occur. 95132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * 95232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @param policy the policy to put into place 95332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 95432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static void setVmPolicy(final VmPolicy policy) { 95532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick sVmPolicyMask = policy.mask; 95632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 95732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 95832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 95932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * Gets the current VM policy. 96032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 96132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static VmPolicy getVmPolicy() { 96232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return new VmPolicy(sVmPolicyMask); 96332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 96432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 96532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 96662a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick * Enable the recommended StrictMode defaults, with violations just being logged. 96762a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick * 96862a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick * <p>This catches disk and network access on the main thread, as 96962a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick * well as leaked SQLite cursors. This is simply a wrapper around 97062a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick * {@link #setVmPolicy} and {@link #setThreadPolicy}. 97162a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick */ 97262a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick public static void enableDefaults() { 97362a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() 97462a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick .detectAll() 97562a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick .penaltyLog() 97662a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick .build()); 97762a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() 97862a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick .detectLeakedSqlLiteObjects() 97962a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick .penaltyLog() 98062a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick .build()); 98162a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick } 98262a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick 98362a1eb58bfafe8744d7a65f651e11b88fdb0938dBrad Fitzpatrick /** 98432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 98532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 98632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static boolean vmSqliteObjectLeaksEnabled() { 98732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0; 98832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 98932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 99032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 99132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick * @hide 99232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick */ 99332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick public static void onSqliteObjectLeaked(String message, Throwable originStack) { 99432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if ((sVmPolicyMask & PENALTY_LOG) != 0) { 99532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick Log.e(TAG, message, originStack); 99632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 99732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 99832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if ((sVmPolicyMask & PENALTY_DROPBOX) != 0) { 99932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask); 100032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 100132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // The violationMask, passed to ActivityManager, is a 100232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // subset of the original StrictMode policy bitmask, with 100332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // only the bit violated and penalty bits to be executed 100432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // by the ActivityManagerService remaining set. 100532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick int violationMaskSubset = PENALTY_DROPBOX | DETECT_VM_CURSOR_LEAKS; 100632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick final int savedPolicyMask = getThreadPolicyMask(); 100732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick try { 100832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // First, remove any policy before we call into the Activity Manager, 100932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // otherwise we'll infinite recurse as we try to log policy violations 101032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // to disk, thus violating policy, thus requiring logging, etc... 101132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // We restore the current policy below, in the finally block. 101232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick setThreadPolicyMask(0); 101332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 101432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( 101532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick RuntimeInit.getApplicationObject(), 101632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick violationMaskSubset, 101732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick info); 101832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } catch (RemoteException e) { 101932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); 102032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } finally { 102132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick // Restore the policy. 102232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick setThreadPolicyMask(savedPolicyMask); 102332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 102432e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 102532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 102632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick if ((sVmPolicyMask & PENALTY_DEATH) != 0) { 102732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down."); 102832e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick Process.killProcess(Process.myPid()); 102932e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick System.exit(10); 103032e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 103132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick } 103232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick 103332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick /** 10345b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Called from Parcel.writeNoException() 10355b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 10365b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /* package */ static void writeGatheredViolationsToParcel(Parcel p) { 1037cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ArrayList<ViolationInfo> violations = gatheredViolations.get(); 1038703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick if (violations == null) { 1039703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick p.writeInt(0); 1040703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } else { 1041703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick p.writeInt(violations.size()); 1042703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick for (int i = 0; i < violations.size(); ++i) { 1043703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick violations.get(i).writeToParcel(p, 0 /* unused flags? */); 1044703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } 1045703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size()); 1046703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick violations.clear(); // somewhat redundant, as we're about to null the threadlocal 10475b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1048703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick gatheredViolations.set(null); 10495b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 10505b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 10515b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class LogStackTrace extends Exception {} 10525b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 10535b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 10545b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, 10555b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * we here read back all the encoded violations. 10565b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 10575b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /* package */ static void readAndHandleBinderCallViolations(Parcel p) { 10585b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Our own stack trace to append 10595b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick StringWriter sw = new StringWriter(); 1060cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick new LogStackTrace().printStackTrace(new PrintWriter(sw)); 10615b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick String ourStack = sw.toString(); 10625b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 106332e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick int policyMask = getThreadPolicyMask(); 1064cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0; 10655b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 10665b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int numViolations = p.readInt(); 10675b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick for (int i = 0; i < numViolations; ++i) { 10685b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i); 1069cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ViolationInfo info = new ViolationInfo(p, !currentlyGathering); 1070cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack; 10715b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); 10725b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (policy instanceof AndroidBlockGuardPolicy) { 1073cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info); 10745b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 10755b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 10765b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 10775b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 10785b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 1079727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * Called from android_util_Binder.cpp's 1080727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * android_os_Parcel_enforceInterface when an incoming Binder call 1081727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * requires changing the StrictMode policy mask. The role of this 1082727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * function is to ask Binder for its current (native) thread-local 1083727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * policy value and synchronize it to libcore's (Java) 1084727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * thread-local policy value. 1085727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick */ 1086727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick private static void onBinderStrictModePolicyChange(int newPolicy) { 1087727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setBlockGuardPolicy(newPolicy); 1088727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } 1089cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1090cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1091cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Parcelable that gets sent in Binder call headers back to callers 1092cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * to report violations that happened during a cross-process call. 1093cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * 1094cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * @hide 1095cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1096cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public static class ViolationInfo { 1097cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1098cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Stack and other stuff info. 1099cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1100cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public final ApplicationErrorReport.CrashInfo crashInfo; 1101cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1102cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1103cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * The strict mode policy mask at the time of violation. 1104cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1105cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public final int policy; 1106cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1107cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1108cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * The wall time duration of the violation, when known. -1 when 1109cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * not known. 1110cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1111cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public int durationMillis = -1; 1112cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1113cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1114599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick * The number of animations currently running. 1115599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick */ 1116599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick public int numAnimationsRunning = 0; 1117599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick 1118599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick /** 1119cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Which violation number this was (1-based) since the last Looper loop, 1120cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * from the perspective of the root caller (if it crossed any processes 1121cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * via Binder calls). The value is 0 if the root caller wasn't on a Looper 1122cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * thread. 1123cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1124cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public int violationNumThisLoop; 1125cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1126cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1127cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * The time (in terms of SystemClock.uptimeMillis()) that the 1128cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * violation occurred. 1129cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1130cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public long violationUptimeMillis; 1131cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1132cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1133cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Create an uninitialized instance of ViolationInfo 1134cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1135cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public ViolationInfo() { 1136cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo = null; 1137cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick policy = 0; 1138cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1139cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1140cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1141cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Create an instance of ViolationInfo initialized from an exception. 1142cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1143cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public ViolationInfo(Throwable tr, int policy) { 1144cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo = new ApplicationErrorReport.CrashInfo(tr); 1145cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationUptimeMillis = SystemClock.uptimeMillis(); 1146cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick this.policy = policy; 1147599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount(); 1148cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1149cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1150cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1151cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Create an instance of ViolationInfo initialized from a Parcel. 1152cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1153cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public ViolationInfo(Parcel in) { 1154cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick this(in, false); 1155cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1156cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1157cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1158cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Create an instance of ViolationInfo initialized from a Parcel. 1159cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * 1160cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * @param unsetGatheringBit if true, the caller is the root caller 1161cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * and the gathering penalty should be removed. 1162cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1163cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public ViolationInfo(Parcel in, boolean unsetGatheringBit) { 1164cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo = new ApplicationErrorReport.CrashInfo(in); 1165cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick int rawPolicy = in.readInt(); 1166cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (unsetGatheringBit) { 1167cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick policy = rawPolicy & ~PENALTY_GATHER; 1168cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } else { 1169cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick policy = rawPolicy; 1170cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1171cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick durationMillis = in.readInt(); 1172cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationNumThisLoop = in.readInt(); 1173599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick numAnimationsRunning = in.readInt(); 1174cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationUptimeMillis = in.readLong(); 1175cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1176cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1177cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1178cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Save a ViolationInfo instance to a parcel. 1179cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1180cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public void writeToParcel(Parcel dest, int flags) { 1181cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo.writeToParcel(dest, flags); 1182cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick dest.writeInt(policy); 1183cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick dest.writeInt(durationMillis); 1184cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick dest.writeInt(violationNumThisLoop); 1185599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick dest.writeInt(numAnimationsRunning); 1186cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick dest.writeLong(violationUptimeMillis); 1187cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1188cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1189cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1190cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 1191cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Dump a ViolationInfo instance to a Printer. 1192cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 1193cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public void dump(Printer pw, String prefix) { 1194cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo.dump(pw, prefix); 1195cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick pw.println(prefix + "policy: " + policy); 1196cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (durationMillis != -1) { 1197cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick pw.println(prefix + "durationMillis: " + durationMillis); 1198cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1199cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (violationNumThisLoop != 0) { 1200cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop); 1201cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1202599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick if (numAnimationsRunning != 0) { 1203599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning); 1204599ca29986235e07f532c7b112507f6c39b5dba9Brad Fitzpatrick } 1205cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis); 1206cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1207cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 1208cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 1209438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick} 1210