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