StrictMode.java revision cb9ceb1029036363a81952d8ed5dfcbc83e6ff72
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 18438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport android.app.ActivityManagerNative; 19438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport android.app.ApplicationErrorReport; 20438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport android.util.Log; 21cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrickimport android.util.Printer; 22438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 23438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport com.android.internal.os.RuntimeInit; 24438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 25438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport dalvik.system.BlockGuard; 26438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 275b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrickimport java.io.PrintWriter; 285b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrickimport java.io.StringWriter; 295b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrickimport java.util.ArrayList; 3046d42387464a651268648659e91d022566d4844cBrad Fitzpatrickimport java.util.HashMap; 3146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 32438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick/** 33438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * <p>StrictMode lets you impose stricter rules under which your 34438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * application runs.</p> 35438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 36438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickpublic final class StrictMode { 37438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private static final String TAG = "StrictMode"; 385b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static final boolean LOG_V = false; 39438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 4046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Only log a duplicate stack trace to the logs every second. 4146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick private static final long MIN_LOG_INTERVAL_MS = 1000; 4246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 4346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Only show an annoying dialog at most every 30 seconds 4446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick private static final long MIN_DIALOG_INTERVAL_MS = 30000; 4546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 46438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private StrictMode() {} 47438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 48438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int DISALLOW_DISK_WRITE = 0x01; 49438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int DISALLOW_DISK_READ = 0x02; 50438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int DISALLOW_NETWORK = 0x04; 51438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 52438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** @hide */ 53438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int DISALLOW_MASK = 54438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick DISALLOW_DISK_WRITE | DISALLOW_DISK_READ | DISALLOW_NETWORK; 55438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 56438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 57438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Flag to log to the system log. 58438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 59438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_LOG = 0x10; // normal android.util.Log 60438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 61438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 62438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Show an annoying dialog to the user. Will be rate-limited to be only 63438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * a little annoying. 64438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 65438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_DIALOG = 0x20; 66438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 67438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 68438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Crash hard if policy is violated. 69438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 70438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_DEATH = 0x40; 71438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 72438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 73438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Log a stacktrace to the DropBox on policy violation. 74438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 75438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_DROPBOX = 0x80; 76438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 77727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick /** 78727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * Non-public penalty mode which overrides all the other penalty 79727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * bits and signals that we're in a Binder call and we should 80727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * ignore the other penalty bits and instead serialize back all 81727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * our offending stack traces to the caller to ultimately handle 82727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * in the originating process. 83727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * 84703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * This must be kept in sync with the constant in libs/binder/Parcel.cpp 85703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * 86727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * @hide 87727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick */ 88727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick public static final int PENALTY_GATHER = 0x100; 89727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 90438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** @hide */ 91438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_MASK = 92438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick PENALTY_LOG | PENALTY_DIALOG | 93438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick PENALTY_DROPBOX | PENALTY_DEATH; 94438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 95438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 965b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Log of strict mode violation stack traces that have occurred 975b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * during a Binder call, to be serialized back later to the caller 985b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * via Parcel.writeNoException() (amusingly) where the caller can 995b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * choose how to react. 1005b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 101cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations = 102cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick new ThreadLocal<ArrayList<ViolationInfo>>() { 103cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick @Override protected ArrayList<ViolationInfo> initialValue() { 104703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick // Starts null to avoid unnecessary allocations when 105703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick // checking whether there are any violations or not in 106703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick // hasGatheredViolations() below. 107703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick return null; 1085b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1095b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick }; 1105b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 1115b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 112438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Sets the policy for what actions the current thread is denied, 113438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * as well as the penalty for violating the policy. 114438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * 115438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * @param policyMask a bitmask of DISALLOW_* and PENALTY_* values. 116438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 117438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static void setThreadBlockingPolicy(final int policyMask) { 118727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // In addition to the Java-level thread-local in Dalvik's 119727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // BlockGuard, we also need to keep a native thread-local in 120727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // Binder in order to propagate the value across Binder calls, 121727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // even across native-only processes. The two are kept in 122727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // sync via the callback to onStrictModePolicyChange, below. 123727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setBlockGuardPolicy(policyMask); 124727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 125727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // And set the Android native version... 126727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick Binder.setThreadStrictModePolicy(policyMask); 127727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } 128727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 129727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // Sets the policy in Dalvik/libcore (BlockGuard) 130727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick private static void setBlockGuardPolicy(final int policyMask) { 13146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if (policyMask == 0) { 13246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY); 13346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick return; 13446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 135438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); 136438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if (!(policy instanceof AndroidBlockGuardPolicy)) { 137438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick BlockGuard.setThreadPolicy(new AndroidBlockGuardPolicy(policyMask)); 138438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } else { 139438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick AndroidBlockGuardPolicy androidPolicy = (AndroidBlockGuardPolicy) policy; 140438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick androidPolicy.setPolicyMask(policyMask); 141438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 142438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 143438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 1445b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class StrictModeNetworkViolation extends BlockGuard.BlockGuardPolicyException { 1455b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public StrictModeNetworkViolation(int policyMask) { 1465b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick super(policyMask, DISALLOW_NETWORK); 1475b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1485b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1495b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 1505b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class StrictModeDiskReadViolation extends BlockGuard.BlockGuardPolicyException { 1515b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public StrictModeDiskReadViolation(int policyMask) { 1525b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick super(policyMask, DISALLOW_DISK_READ); 1535b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1545b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1555b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 1565b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class StrictModeDiskWriteViolation extends BlockGuard.BlockGuardPolicyException { 1575b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public StrictModeDiskWriteViolation(int policyMask) { 1585b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick super(policyMask, DISALLOW_DISK_WRITE); 1595b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1605b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1615b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 162438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 163438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Returns the bitmask of the current thread's blocking policy. 164438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * 165438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * @return the bitmask of all the DISALLOW_* and PENALTY_* bits currently enabled 166438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 167438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static int getThreadBlockingPolicy() { 168438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return BlockGuard.getThreadPolicy().getPolicyMask(); 169438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 170438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 1715b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 1725b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Parses the BlockGuard policy mask out from the Exception's 1735b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * getMessage() String value. Kinda gross, but least 1745b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * invasive. :/ 1755b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * 1765b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Input is of form "policy=137 violation=64" 1775b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * 1785b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Returns 0 on failure, which is a valid policy, but not a 1795b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * valid policy during a violation (else there must've been 1805b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * some policy in effect to violate). 1815b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 1825b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static int parsePolicyFromMessage(String message) { 1835b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (message == null || !message.startsWith("policy=")) { 1845b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 1855b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1865b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int spaceIndex = message.indexOf(' '); 1875b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (spaceIndex == -1) { 1885b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 1895b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1905b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick String policyString = message.substring(7, spaceIndex); 1915b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick try { 1925b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return Integer.valueOf(policyString).intValue(); 1935b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } catch (NumberFormatException e) { 1945b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 1955b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1965b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1975b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 1985b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 1995b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Like parsePolicyFromMessage(), but returns the violation. 2005b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 2015b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static int parseViolationFromMessage(String message) { 2025b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (message == null) { 2035b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 2045b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2055b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int violationIndex = message.indexOf("violation="); 2065b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (violationIndex == -1) { 2075b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 2085b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2095b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick String violationString = message.substring(violationIndex + 10); 2105b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick try { 2115b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return Integer.valueOf(violationString).intValue(); 2125b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } catch (NumberFormatException e) { 2135b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 2145b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2155b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2165b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 217438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private static class AndroidBlockGuardPolicy implements BlockGuard.Policy { 218438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private int mPolicyMask; 21946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 22046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Map from violation stacktrace hashcode -> uptimeMillis of 22146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // last violation. No locking needed, as this is only 22246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // accessed by the same thread. 22346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>(); 224438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 225438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public AndroidBlockGuardPolicy(final int policyMask) { 226438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick mPolicyMask = policyMask; 227438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 228438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 2295b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick @Override 2305b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public String toString() { 2315b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask; 2325b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2335b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 234438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 235438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public int getPolicyMask() { 236438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return mPolicyMask; 237438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 238438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 239438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 240438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void onWriteToDisk() { 241438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if ((mPolicyMask & DISALLOW_DISK_WRITE) == 0) { 242438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return; 243438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 244cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask); 245cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick e.fillInStackTrace(); 246cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick startHandlingViolationException(e); 247438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 248438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 249438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 250438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void onReadFromDisk() { 251438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if ((mPolicyMask & DISALLOW_DISK_READ) == 0) { 252438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return; 253438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 254cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask); 255cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick e.fillInStackTrace(); 256cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick startHandlingViolationException(e); 257438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 258438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 259438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 260438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void onNetwork() { 261438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if ((mPolicyMask & DISALLOW_NETWORK) == 0) { 262438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return; 263438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 264cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask); 265cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick e.fillInStackTrace(); 266cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick startHandlingViolationException(e); 267438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 268438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 269438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void setPolicyMask(int policyMask) { 270438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick mPolicyMask = policyMask; 271438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 272438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 2735b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Start handling a violation that just started and hasn't 2745b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // actually run yet (e.g. no disk write or network operation 2755b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // has yet occurred). This sees if we're in an event loop 2765b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // thread and, if so, uses it to roughly measure how long the 2775b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // violation took. 2785b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) { 279cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick final ViolationInfo info = new ViolationInfo(e, e.getPolicy()); 280cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info.violationUptimeMillis = SystemClock.uptimeMillis(); 281cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick handleViolationWithTimingAttempt(info); 282cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 283438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 284cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed = 285cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick new ThreadLocal<ArrayList<ViolationInfo>>() { 286cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick @Override protected ArrayList<ViolationInfo> initialValue() { 287cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick return new ArrayList<ViolationInfo>(); 288cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 289cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick }; 290cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 291cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // Attempts to fill in the provided ViolationInfo's 292cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // durationMillis field if this thread has a Looper we can use 293cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // to measure with. We measure from the time of violation 294cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // until the time the looper is idle again (right before 295cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // the next epoll_wait) 296cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick void handleViolationWithTimingAttempt(final ViolationInfo info) { 297438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick Looper looper = Looper.myLooper(); 298cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 299cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // Without a Looper, we're unable to time how long the 300cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // violation takes place. This case should be rare, as 301cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // most users will care about timing violations that 302cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // happen on their main UI thread. Note that this case is 303cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // also hit when a violation takes place in a Binder 304cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // thread, in "gather" mode. In this case, the duration 305cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // of the violation is computed by the ultimate caller and 306cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // its Looper, if any. 307cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // TODO: if in gather mode, ignore Looper.myLooper() and always 308cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // go into this immediate mode? 309438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if (looper == null) { 310cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info.durationMillis = -1; // unknown (redundant, already set) 311cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick handleViolation(info); 312cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick return; 313438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 314438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 315cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick MessageQueue queue = Looper.myQueue(); 316cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick final ArrayList<ViolationInfo> records = violationsBeingTimed.get(); 317cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (records.size() >= 10) { 318cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // Not worth measuring. Too many offenses in one loop. 319cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick return; 320cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 321cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick records.add(info); 322cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (records.size() > 1) { 323cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // There's already been a violation this loop, so we've already 324cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // registered an idle handler to process the list of violations 325cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick // at the end of this Looper's loop. 326cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick return; 327cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 328cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 329cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick queue.addIdleHandler(new MessageQueue.IdleHandler() { 330cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public boolean queueIdle() { 331cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick long loopFinishTime = SystemClock.uptimeMillis(); 332cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick for (int n = 0; n < records.size(); ++n) { 333cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ViolationInfo v = records.get(n); 334cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick v.violationNumThisLoop = n + 1; 335cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick v.durationMillis = 336cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick (int) (loopFinishTime - v.violationUptimeMillis); 337cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick handleViolation(v); 338cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 339cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick records.clear(); 340cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick return false; // remove this idle handler from the array 341cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 342cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick }); 3435b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 344438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 3455b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Note: It's possible (even quite likely) that the 3465b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // thread-local policy mask has changed from the time the 3475b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // violation fired and now (after the violating code ran) due 3485b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // to people who push/pop temporary policy in regions of code, 3495b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // hence the policy being passed around. 350cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick void handleViolation(final ViolationInfo info) { 351cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) { 352cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick Log.wtf(TAG, "unexpected null stacktrace"); 3535b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return; 3545b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 355438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 356cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy); 35746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 358cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_GATHER) != 0) { 359cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ArrayList<ViolationInfo> violations = gatheredViolations.get(); 360703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick if (violations == null) { 361cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violations = new ArrayList<ViolationInfo>(1); 362703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick gatheredViolations.set(violations); 363703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } else if (violations.size() >= 5) { 3645b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Too many. In a loop or something? Don't gather them all. 3655b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return; 3665b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 367cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick for (ViolationInfo previous : violations) { 368cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) { 3695b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Duplicate. Don't log. 3705b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return; 3715b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 3725b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 373cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violations.add(info); 374727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick return; 375727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } 376727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 37746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Not perfect, but fast and good enough for dup suppression. 378cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick Integer crashFingerprint = info.crashInfo.stackTrace.hashCode(); 37946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick long lastViolationTime = 0; 38046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if (mLastViolationTime.containsKey(crashFingerprint)) { 38146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick lastViolationTime = mLastViolationTime.get(crashFingerprint); 38246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 38346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick long now = SystemClock.uptimeMillis(); 38446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick mLastViolationTime.put(crashFingerprint, now); 38546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick long timeSinceLastViolationMillis = lastViolationTime == 0 ? 38646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick Long.MAX_VALUE : (now - lastViolationTime); 38746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 388cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_LOG) != 0 && 38946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) { 390cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (info.durationMillis != -1) { 3915b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick Log.d(TAG, "StrictMode policy violation; ~duration=" + 392cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info.durationMillis + " ms: " + info.crashInfo.stackTrace); 393438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } else { 394cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace); 395438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 396438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 397438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 39846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // The violationMask, passed to ActivityManager, is a 39946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // subset of the original StrictMode policy bitmask, with 40046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // only the bit violated and penalty bits to be executed 40146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // by the ActivityManagerService remaining set. 402cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick int violationMaskSubset = 0; 40346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 404cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_DIALOG) != 0 && 40546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) { 406cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationMaskSubset |= PENALTY_DIALOG; 40746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 40846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 409cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) { 410cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationMaskSubset |= PENALTY_DROPBOX; 41146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 41246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 413cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (violationMaskSubset != 0) { 414cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage); 415cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationMaskSubset |= violationBit; 416727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick final int savedPolicy = getThreadBlockingPolicy(); 417438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick try { 418727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // First, remove any policy before we call into the Activity Manager, 419727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // otherwise we'll infinite recurse as we try to log policy violations 420727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // to disk, thus violating policy, thus requiring logging, etc... 421727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // We restore the current policy below, in the finally block. 422727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setThreadBlockingPolicy(0); 423727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 424438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( 425438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick RuntimeInit.getApplicationObject(), 426cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationMaskSubset, 427cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info); 428438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } catch (RemoteException e) { 42946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); 430727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } finally { 431727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // Restore the policy. 432727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setThreadBlockingPolicy(savedPolicy); 433438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 434438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 435438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 436cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if ((info.policy & PENALTY_DEATH) != 0) { 437438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick System.err.println("StrictMode policy violation with POLICY_DEATH; shutting down."); 438438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick Process.killProcess(Process.myPid()); 439438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick System.exit(10); 440438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 441438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 442438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 443727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 444727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick /** 4455b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Called from Parcel.writeNoException() 4465b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 4475b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /* package */ static boolean hasGatheredViolations() { 448703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick return gatheredViolations.get() != null; 449703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } 450703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick 451703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick /** 452703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * Called from Parcel.writeException(), so we drop this memory and 453703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * don't incorrectly attribute it to the wrong caller on the next 454703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * Binder call on this thread. 455703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick */ 456703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick /* package */ static void clearGatheredViolations() { 457703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick gatheredViolations.set(null); 4585b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 4595b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4605b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 4615b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Called from Parcel.writeNoException() 4625b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 4635b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /* package */ static void writeGatheredViolationsToParcel(Parcel p) { 464cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ArrayList<ViolationInfo> violations = gatheredViolations.get(); 465703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick if (violations == null) { 466703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick p.writeInt(0); 467703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } else { 468703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick p.writeInt(violations.size()); 469703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick for (int i = 0; i < violations.size(); ++i) { 470703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick violations.get(i).writeToParcel(p, 0 /* unused flags? */); 471703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } 472703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size()); 473703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick violations.clear(); // somewhat redundant, as we're about to null the threadlocal 4745b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 475703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick gatheredViolations.set(null); 4765b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 4775b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4785b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class LogStackTrace extends Exception {} 4795b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4805b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 4815b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, 4825b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * we here read back all the encoded violations. 4835b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 4845b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /* package */ static void readAndHandleBinderCallViolations(Parcel p) { 4855b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Our own stack trace to append 4865b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick StringWriter sw = new StringWriter(); 487cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick new LogStackTrace().printStackTrace(new PrintWriter(sw)); 4885b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick String ourStack = sw.toString(); 4895b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4905b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int policyMask = getThreadBlockingPolicy(); 491cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0; 4925b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4935b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int numViolations = p.readInt(); 4945b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick for (int i = 0; i < numViolations; ++i) { 4955b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i); 496cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ViolationInfo info = new ViolationInfo(p, !currentlyGathering); 497cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack; 4985b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); 4995b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (policy instanceof AndroidBlockGuardPolicy) { 500cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info); 5015b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5025b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5035b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 5045b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 5055b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 506727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * Called from android_util_Binder.cpp's 507727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * android_os_Parcel_enforceInterface when an incoming Binder call 508727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * requires changing the StrictMode policy mask. The role of this 509727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * function is to ask Binder for its current (native) thread-local 510727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * policy value and synchronize it to libcore's (Java) 511727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * thread-local policy value. 512727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick */ 513727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick private static void onBinderStrictModePolicyChange(int newPolicy) { 514727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setBlockGuardPolicy(newPolicy); 515727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } 516cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 517cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 518cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Parcelable that gets sent in Binder call headers back to callers 519cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * to report violations that happened during a cross-process call. 520cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * 521cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * @hide 522cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 523cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public static class ViolationInfo { 524cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 525cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Stack and other stuff info. 526cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 527cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public final ApplicationErrorReport.CrashInfo crashInfo; 528cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 529cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 530cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * The strict mode policy mask at the time of violation. 531cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 532cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public final int policy; 533cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 534cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 535cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * The wall time duration of the violation, when known. -1 when 536cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * not known. 537cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 538cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public int durationMillis = -1; 539cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 540cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 541cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Which violation number this was (1-based) since the last Looper loop, 542cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * from the perspective of the root caller (if it crossed any processes 543cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * via Binder calls). The value is 0 if the root caller wasn't on a Looper 544cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * thread. 545cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 546cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public int violationNumThisLoop; 547cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 548cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 549cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * The time (in terms of SystemClock.uptimeMillis()) that the 550cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * violation occurred. 551cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 552cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public long violationUptimeMillis; 553cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 554cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 555cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Create an uninitialized instance of ViolationInfo 556cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 557cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public ViolationInfo() { 558cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo = null; 559cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick policy = 0; 560cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 561cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 562cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 563cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Create an instance of ViolationInfo initialized from an exception. 564cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 565cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public ViolationInfo(Throwable tr, int policy) { 566cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo = new ApplicationErrorReport.CrashInfo(tr); 567cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationUptimeMillis = SystemClock.uptimeMillis(); 568cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick this.policy = policy; 569cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 570cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 571cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 572cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Create an instance of ViolationInfo initialized from a Parcel. 573cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 574cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public ViolationInfo(Parcel in) { 575cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick this(in, false); 576cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 577cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 578cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 579cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Create an instance of ViolationInfo initialized from a Parcel. 580cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * 581cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * @param unsetGatheringBit if true, the caller is the root caller 582cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * and the gathering penalty should be removed. 583cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 584cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public ViolationInfo(Parcel in, boolean unsetGatheringBit) { 585cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo = new ApplicationErrorReport.CrashInfo(in); 586cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick int rawPolicy = in.readInt(); 587cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (unsetGatheringBit) { 588cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick policy = rawPolicy & ~PENALTY_GATHER; 589cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } else { 590cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick policy = rawPolicy; 591cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 592cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick durationMillis = in.readInt(); 593cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationNumThisLoop = in.readInt(); 594cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick violationUptimeMillis = in.readLong(); 595cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 596cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 597cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 598cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Save a ViolationInfo instance to a parcel. 599cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 600cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public void writeToParcel(Parcel dest, int flags) { 601cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo.writeToParcel(dest, flags); 602cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick dest.writeInt(policy); 603cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick dest.writeInt(durationMillis); 604cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick dest.writeInt(violationNumThisLoop); 605cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick dest.writeLong(violationUptimeMillis); 606cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 607cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 608cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 609cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick /** 610cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick * Dump a ViolationInfo instance to a Printer. 611cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick */ 612cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick public void dump(Printer pw, String prefix) { 613cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick crashInfo.dump(pw, prefix); 614cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick pw.println(prefix + "policy: " + policy); 615cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (durationMillis != -1) { 616cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick pw.println(prefix + "durationMillis: " + durationMillis); 617cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 618cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick if (violationNumThisLoop != 0) { 619cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop); 620cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 621cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis); 622cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 623cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick 624cb9ceb1029036363a81952d8ed5dfcbc83e6ff72Brad Fitzpatrick } 625438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick} 626