StrictMode.java revision 703e5d3c7fbeb8ca0978045db01d40318f838612
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; 21438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 22438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport com.android.internal.os.RuntimeInit; 23438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 24438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickimport dalvik.system.BlockGuard; 25438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 265b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrickimport java.io.PrintWriter; 275b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrickimport java.io.StringWriter; 285b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrickimport java.util.ArrayList; 2946d42387464a651268648659e91d022566d4844cBrad Fitzpatrickimport java.util.HashMap; 3046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 31438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick/** 32438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * <p>StrictMode lets you impose stricter rules under which your 33438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * application runs.</p> 34438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 35438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrickpublic final class StrictMode { 36438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private static final String TAG = "StrictMode"; 375b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static final boolean LOG_V = false; 38438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 3946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Only log a duplicate stack trace to the logs every second. 4046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick private static final long MIN_LOG_INTERVAL_MS = 1000; 4146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 4246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Only show an annoying dialog at most every 30 seconds 4346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick private static final long MIN_DIALOG_INTERVAL_MS = 30000; 4446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 45438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private StrictMode() {} 46438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 47438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int DISALLOW_DISK_WRITE = 0x01; 48438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int DISALLOW_DISK_READ = 0x02; 49438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int DISALLOW_NETWORK = 0x04; 50438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 51438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** @hide */ 52438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int DISALLOW_MASK = 53438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick DISALLOW_DISK_WRITE | DISALLOW_DISK_READ | DISALLOW_NETWORK; 54438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 55438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 56438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Flag to log to the system log. 57438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 58438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_LOG = 0x10; // normal android.util.Log 59438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 60438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 61438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Show an annoying dialog to the user. Will be rate-limited to be only 62438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * a little annoying. 63438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 64438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_DIALOG = 0x20; 65438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 66438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 67438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Crash hard if policy is violated. 68438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 69438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_DEATH = 0x40; 70438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 71438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 72438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Log a stacktrace to the DropBox on policy violation. 73438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 74438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_DROPBOX = 0x80; 75438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 76727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick /** 77727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * Non-public penalty mode which overrides all the other penalty 78727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * bits and signals that we're in a Binder call and we should 79727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * ignore the other penalty bits and instead serialize back all 80727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * our offending stack traces to the caller to ultimately handle 81727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * in the originating process. 82727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * 83703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * This must be kept in sync with the constant in libs/binder/Parcel.cpp 84703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * 85727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * @hide 86727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick */ 87727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick public static final int PENALTY_GATHER = 0x100; 88727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 89438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** @hide */ 90438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static final int PENALTY_MASK = 91438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick PENALTY_LOG | PENALTY_DIALOG | 92438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick PENALTY_DROPBOX | PENALTY_DEATH; 93438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 94438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 955b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Log of strict mode violation stack traces that have occurred 965b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * during a Binder call, to be serialized back later to the caller 975b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * via Parcel.writeNoException() (amusingly) where the caller can 985b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * choose how to react. 995b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 1005b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static ThreadLocal<ArrayList<ApplicationErrorReport.CrashInfo>> gatheredViolations = 1015b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick new ThreadLocal<ArrayList<ApplicationErrorReport.CrashInfo>>() { 1025b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick @Override protected ArrayList<ApplicationErrorReport.CrashInfo> initialValue() { 103703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick // Starts null to avoid unnecessary allocations when 104703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick // checking whether there are any violations or not in 105703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick // hasGatheredViolations() below. 106703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick return null; 1075b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1085b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick }; 1095b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 1105b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 111438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Sets the policy for what actions the current thread is denied, 112438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * as well as the penalty for violating the policy. 113438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * 114438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * @param policyMask a bitmask of DISALLOW_* and PENALTY_* values. 115438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 116438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static void setThreadBlockingPolicy(final int policyMask) { 117727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // In addition to the Java-level thread-local in Dalvik's 118727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // BlockGuard, we also need to keep a native thread-local in 119727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // Binder in order to propagate the value across Binder calls, 120727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // even across native-only processes. The two are kept in 121727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // sync via the callback to onStrictModePolicyChange, below. 122727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setBlockGuardPolicy(policyMask); 123727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 124727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // And set the Android native version... 125727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick Binder.setThreadStrictModePolicy(policyMask); 126727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } 127727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 128727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // Sets the policy in Dalvik/libcore (BlockGuard) 129727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick private static void setBlockGuardPolicy(final int policyMask) { 13046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if (policyMask == 0) { 13146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY); 13246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick return; 13346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 134438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); 135438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if (!(policy instanceof AndroidBlockGuardPolicy)) { 136438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick BlockGuard.setThreadPolicy(new AndroidBlockGuardPolicy(policyMask)); 137438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } else { 138438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick AndroidBlockGuardPolicy androidPolicy = (AndroidBlockGuardPolicy) policy; 139438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick androidPolicy.setPolicyMask(policyMask); 140438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 141438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 142438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 1435b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class StrictModeNetworkViolation extends BlockGuard.BlockGuardPolicyException { 1445b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public StrictModeNetworkViolation(int policyMask) { 1455b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick super(policyMask, DISALLOW_NETWORK); 1465b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1475b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1485b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 1495b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class StrictModeDiskReadViolation extends BlockGuard.BlockGuardPolicyException { 1505b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public StrictModeDiskReadViolation(int policyMask) { 1515b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick super(policyMask, DISALLOW_DISK_READ); 1525b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1535b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1545b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 1555b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class StrictModeDiskWriteViolation extends BlockGuard.BlockGuardPolicyException { 1565b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public StrictModeDiskWriteViolation(int policyMask) { 1575b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick super(policyMask, DISALLOW_DISK_WRITE); 1585b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1595b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1605b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 161438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick /** 162438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * Returns the bitmask of the current thread's blocking policy. 163438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * 164438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick * @return the bitmask of all the DISALLOW_* and PENALTY_* bits currently enabled 165438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick */ 166438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public static int getThreadBlockingPolicy() { 167438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return BlockGuard.getThreadPolicy().getPolicyMask(); 168438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 169438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 1705b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 1715b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Parses the BlockGuard policy mask out from the Exception's 1725b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * getMessage() String value. Kinda gross, but least 1735b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * invasive. :/ 1745b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * 1755b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Input is of form "policy=137 violation=64" 1765b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * 1775b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Returns 0 on failure, which is a valid policy, but not a 1785b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * valid policy during a violation (else there must've been 1795b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * some policy in effect to violate). 1805b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 1815b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static int parsePolicyFromMessage(String message) { 1825b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (message == null || !message.startsWith("policy=")) { 1835b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 1845b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1855b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int spaceIndex = message.indexOf(' '); 1865b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (spaceIndex == -1) { 1875b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 1885b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1895b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick String policyString = message.substring(7, spaceIndex); 1905b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick try { 1915b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return Integer.valueOf(policyString).intValue(); 1925b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } catch (NumberFormatException e) { 1935b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 1945b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1955b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 1965b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 1975b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 1985b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Like parsePolicyFromMessage(), but returns the violation. 1995b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 2005b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static int parseViolationFromMessage(String message) { 2015b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (message == null) { 2025b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 2035b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2045b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int violationIndex = message.indexOf("violation="); 2055b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (violationIndex == -1) { 2065b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 2075b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2085b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick String violationString = message.substring(violationIndex + 10); 2095b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick try { 2105b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return Integer.valueOf(violationString).intValue(); 2115b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } catch (NumberFormatException e) { 2125b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return 0; 2135b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2145b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2155b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 216438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private static class AndroidBlockGuardPolicy implements BlockGuard.Policy { 217438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick private int mPolicyMask; 21846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 21946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Map from violation stacktrace hashcode -> uptimeMillis of 22046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // last violation. No locking needed, as this is only 22146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // accessed by the same thread. 22246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>(); 223438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 224438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public AndroidBlockGuardPolicy(final int policyMask) { 225438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick mPolicyMask = policyMask; 226438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 227438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 2285b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick @Override 2295b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick public String toString() { 2305b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask; 2315b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 2325b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 233438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 234438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public int getPolicyMask() { 235438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return mPolicyMask; 236438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 237438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 238438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 239438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void onWriteToDisk() { 240438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if ((mPolicyMask & DISALLOW_DISK_WRITE) == 0) { 241438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return; 242438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 2435b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick startHandlingViolationException(new StrictModeDiskWriteViolation(mPolicyMask)); 244438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 245438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 246438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 247438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void onReadFromDisk() { 248438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if ((mPolicyMask & DISALLOW_DISK_READ) == 0) { 249438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return; 250438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 2515b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick startHandlingViolationException(new StrictModeDiskReadViolation(mPolicyMask)); 252438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 253438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 254438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Part of BlockGuard.Policy interface: 255438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void onNetwork() { 256438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if ((mPolicyMask & DISALLOW_NETWORK) == 0) { 257438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return; 258438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 2595b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick startHandlingViolationException(new StrictModeNetworkViolation(mPolicyMask)); 260438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 261438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 262438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public void setPolicyMask(int policyMask) { 263438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick mPolicyMask = policyMask; 264438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 265438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 2665b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Start handling a violation that just started and hasn't 2675b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // actually run yet (e.g. no disk write or network operation 2685b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // has yet occurred). This sees if we're in an event loop 2695b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // thread and, if so, uses it to roughly measure how long the 2705b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // violation took. 2715b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) { 2725b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick e.fillInStackTrace(); 2735b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick final ApplicationErrorReport.CrashInfo crashInfo = new ApplicationErrorReport.CrashInfo(e); 2745b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick crashInfo.durationMillis = -1; // unknown 2755b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick final int savedPolicy = mPolicyMask; 276438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 277438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick Looper looper = Looper.myLooper(); 278438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if (looper == null) { 279438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // Without a Looper, we're unable to time how long the 280438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // violation takes place. This case should be rare, 281438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // as most users will care about timing violations 282438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick // that happen on their main UI thread. 2835b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick handleViolation(crashInfo, savedPolicy); 284438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } else { 285438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick MessageQueue queue = Looper.myQueue(); 286438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick final long violationTime = SystemClock.uptimeMillis(); 287438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick queue.addIdleHandler(new MessageQueue.IdleHandler() { 288438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick public boolean queueIdle() { 289438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick long afterViolationTime = SystemClock.uptimeMillis(); 2905b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick crashInfo.durationMillis = afterViolationTime - violationTime; 2915b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick handleViolation(crashInfo, savedPolicy); 292438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick return false; // remove this idle handler from the array 293438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 294438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick }); 295438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 296438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 2975b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 298438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 2995b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Note: It's possible (even quite likely) that the 3005b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // thread-local policy mask has changed from the time the 3015b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // violation fired and now (after the violating code ran) due 3025b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // to people who push/pop temporary policy in regions of code, 3035b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // hence the policy being passed around. 3045b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick void handleViolation( 3055b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick final ApplicationErrorReport.CrashInfo crashInfo, 3065b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int policy) { 3075b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (crashInfo.stackTrace == null) { 3085b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick Log.d(TAG, "unexpected null stacktrace"); 3095b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return; 3105b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 311438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 3125b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (LOG_V) Log.d(TAG, "handleViolation; policy=" + policy); 31346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 314727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick if ((policy & PENALTY_GATHER) != 0) { 3155b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick ArrayList<ApplicationErrorReport.CrashInfo> violations = gatheredViolations.get(); 316703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick if (violations == null) { 317703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick violations = new ArrayList<ApplicationErrorReport.CrashInfo>(1); 318703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick gatheredViolations.set(violations); 319703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } else if (violations.size() >= 5) { 3205b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Too many. In a loop or something? Don't gather them all. 3215b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return; 3225b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 3235b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick for (ApplicationErrorReport.CrashInfo previous : violations) { 3245b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (crashInfo.stackTrace.equals(previous.stackTrace)) { 3255b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Duplicate. Don't log. 3265b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick return; 3275b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 3285b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 3295b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick violations.add(crashInfo); 330727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick return; 331727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } 332727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 33346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // Not perfect, but fast and good enough for dup suppression. 33446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick Integer crashFingerprint = crashInfo.stackTrace.hashCode(); 33546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick long lastViolationTime = 0; 33646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if (mLastViolationTime.containsKey(crashFingerprint)) { 33746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick lastViolationTime = mLastViolationTime.get(crashFingerprint); 33846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 33946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick long now = SystemClock.uptimeMillis(); 34046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick mLastViolationTime.put(crashFingerprint, now); 34146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick long timeSinceLastViolationMillis = lastViolationTime == 0 ? 34246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick Long.MAX_VALUE : (now - lastViolationTime); 34346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 34446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if ((policy & PENALTY_LOG) != 0 && 34546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) { 3465b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (crashInfo.durationMillis != -1) { 3475b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick Log.d(TAG, "StrictMode policy violation; ~duration=" + 3485b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick crashInfo.durationMillis + " ms: " + crashInfo.stackTrace); 349438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } else { 3505b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick Log.d(TAG, "StrictMode policy violation: " + crashInfo.stackTrace); 351438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 352438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 353438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 35446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // The violationMask, passed to ActivityManager, is a 35546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // subset of the original StrictMode policy bitmask, with 35646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // only the bit violated and penalty bits to be executed 35746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick // by the ActivityManagerService remaining set. 35846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick int violationMask = 0; 35946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 36046d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if ((policy & PENALTY_DIALOG) != 0 && 36146d42387464a651268648659e91d022566d4844cBrad Fitzpatrick timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) { 36246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick violationMask |= PENALTY_DIALOG; 36346d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 36446d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 36546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if ((policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) { 36646d42387464a651268648659e91d022566d4844cBrad Fitzpatrick violationMask |= PENALTY_DROPBOX; 36746d42387464a651268648659e91d022566d4844cBrad Fitzpatrick } 36846d42387464a651268648659e91d022566d4844cBrad Fitzpatrick 36946d42387464a651268648659e91d022566d4844cBrad Fitzpatrick if (violationMask != 0) { 3705b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int violationBit = parseViolationFromMessage(crashInfo.exceptionMessage); 3715b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick violationMask |= violationBit; 372727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick final int savedPolicy = getThreadBlockingPolicy(); 373438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick try { 374727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // First, remove any policy before we call into the Activity Manager, 375727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // otherwise we'll infinite recurse as we try to log policy violations 376727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // to disk, thus violating policy, thus requiring logging, etc... 377727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // We restore the current policy below, in the finally block. 378727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setThreadBlockingPolicy(0); 379727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 380438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( 381438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick RuntimeInit.getApplicationObject(), 38246d42387464a651268648659e91d022566d4844cBrad Fitzpatrick violationMask, 3835b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick crashInfo); 384438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } catch (RemoteException e) { 38546d42387464a651268648659e91d022566d4844cBrad Fitzpatrick Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); 386727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } finally { 387727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick // Restore the policy. 388727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setThreadBlockingPolicy(savedPolicy); 389438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 390438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 391438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick 392438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick if ((policy & PENALTY_DEATH) != 0) { 393438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick System.err.println("StrictMode policy violation with POLICY_DEATH; shutting down."); 394438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick Process.killProcess(Process.myPid()); 395438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick System.exit(10); 396438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 397438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 398438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick } 399727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick 400727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick /** 4015b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Called from Parcel.writeNoException() 4025b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 4035b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /* package */ static boolean hasGatheredViolations() { 404703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick return gatheredViolations.get() != null; 405703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } 406703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick 407703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick /** 408703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * Called from Parcel.writeException(), so we drop this memory and 409703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * don't incorrectly attribute it to the wrong caller on the next 410703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick * Binder call on this thread. 411703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick */ 412703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick /* package */ static void clearGatheredViolations() { 413703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick gatheredViolations.set(null); 4145b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 4155b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4165b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 4175b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Called from Parcel.writeNoException() 4185b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 4195b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /* package */ static void writeGatheredViolationsToParcel(Parcel p) { 4205b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick ArrayList<ApplicationErrorReport.CrashInfo> violations = gatheredViolations.get(); 421703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick if (violations == null) { 422703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick p.writeInt(0); 423703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } else { 424703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick p.writeInt(violations.size()); 425703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick for (int i = 0; i < violations.size(); ++i) { 426703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick violations.get(i).writeToParcel(p, 0 /* unused flags? */); 427703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick } 428703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size()); 429703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick violations.clear(); // somewhat redundant, as we're about to null the threadlocal 4305b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 431703e5d3c7fbeb8ca0978045db01d40318f838612Brad Fitzpatrick gatheredViolations.set(null); 4325b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 4335b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4345b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick private static class LogStackTrace extends Exception {} 4355b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4365b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 4375b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, 4385b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick * we here read back all the encoded violations. 4395b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick */ 4405b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /* package */ static void readAndHandleBinderCallViolations(Parcel p) { 4415b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Our own stack trace to append 4425b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick Exception e = new LogStackTrace(); 4435b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick StringWriter sw = new StringWriter(); 4445b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick e.printStackTrace(new PrintWriter(sw)); 4455b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick String ourStack = sw.toString(); 4465b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4475b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int policyMask = getThreadBlockingPolicy(); 4485b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4495b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick int numViolations = p.readInt(); 4505b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick for (int i = 0; i < numViolations; ++i) { 4515b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i); 4525b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick ApplicationErrorReport.CrashInfo crashInfo = new ApplicationErrorReport.CrashInfo(p); 4535b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack; 4545b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4555b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // Unlike the in-process violations in which case we 4565b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // trigger an error _before_ the thing occurs, in this 4575b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // case the violating thing has already occurred, so we 4585b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // can't use our heuristic of waiting for the next event 4595b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // loop idle cycle to measure the approximate violation 4605b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // duration. Instead, just skip that step and use -1 4615b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // (unknown duration) for now. 4625b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // TODO: keep a thread-local on remote process of first 4635b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // violation time's uptimeMillis, and when writing that 4645b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // back out in Parcel reply, include in the header the 4655b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick // violation time and use it here. 4665b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick crashInfo.durationMillis = -1; 4675b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4685b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); 4695b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick if (policy instanceof AndroidBlockGuardPolicy) { 4705b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick ((AndroidBlockGuardPolicy) policy).handleViolation(crashInfo, policyMask); 4715b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 4725b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 4735b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick } 4745b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick 4755b747191ff8ad43a54d41faf50436271d1d7fcc8Brad Fitzpatrick /** 476727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * Called from android_util_Binder.cpp's 477727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * android_os_Parcel_enforceInterface when an incoming Binder call 478727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * requires changing the StrictMode policy mask. The role of this 479727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * function is to ask Binder for its current (native) thread-local 480727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * policy value and synchronize it to libcore's (Java) 481727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick * thread-local policy value. 482727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick */ 483727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick private static void onBinderStrictModePolicyChange(int newPolicy) { 484727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick setBlockGuardPolicy(newPolicy); 485727de40c6bc7c6521a0542ea9def5d5c7b1c5e06Brad Fitzpatrick } 486438d0595121a7a2cdf19741e76e3c0e21a5c173dBrad Fitzpatrick} 487