Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package android.os;
     17 
     18 import android.app.ActivityManagerNative;
     19 import android.app.ApplicationErrorReport;
     20 import android.util.Log;
     21 import android.util.Printer;
     22 
     23 import com.android.internal.os.RuntimeInit;
     24 
     25 import dalvik.system.BlockGuard;
     26 
     27 import java.io.PrintWriter;
     28 import java.io.StringWriter;
     29 import java.util.ArrayList;
     30 import java.util.HashMap;
     31 
     32 /**
     33  * <p>StrictMode is a developer tool which detects things you might be
     34  * doing by accident and brings them to your attention so you can fix
     35  * them.
     36  *
     37  * <p>StrictMode is most commonly used to catch accidental disk or
     38  * network access on the application's main thread, where UI
     39  * operations are received and animations take place.  Keeping disk
     40  * and network operations off the main thread makes for much smoother,
     41  * more responsive applications.  By keeping your application's main thread
     42  * responsive, you also prevent
     43  * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
     44  * from being shown to users.
     45  *
     46  * <p class="note">Note that even though an Android device's disk is
     47  * often on flash memory, many devices run a filesystem on top of that
     48  * memory with very limited concurrency.  It's often the case that
     49  * almost all disk accesses are fast, but may in individual cases be
     50  * dramatically slower when certain I/O is happening in the background
     51  * from other processes.  If possible, it's best to assume that such
     52  * things are not fast.</p>
     53  *
     54  * <p>Example code to enable from early in your
     55  * {@link android.app.Application}, {@link android.app.Activity}, or
     56  * other application component's
     57  * {@link android.app.Application#onCreate} method:
     58  *
     59  * <pre>
     60  * public void onCreate() {
     61  *     if (DEVELOPER_MODE) {
     62  *         StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
     63  *                 .detectDiskReads()
     64  *                 .detectDiskWrites()
     65  *                 .detectNetwork()   // or .detectAll() for all detectable problems
     66  *                 .penaltyLog()
     67  *                 .build());
     68  *         StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
     69  *                 .detectLeakedSqlLiteObjects()
     70  *                 .penaltyLog()
     71  *                 .penaltyDeath()
     72  *                 .build());
     73  *     }
     74  *     super.onCreate();
     75  * }
     76  * </pre>
     77  *
     78  * <p>You can decide what should happen when a violation is detected.
     79  * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can
     80  * watch the output of <code>adb logcat</code> while you use your
     81  * application to see the violations as they happen.
     82  *
     83  * <p>If you find violations that you feel are problematic, there are
     84  * a variety of tools to help solve them: threads, {@link android.os.Handler},
     85  * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
     86  * But don't feel compelled to fix everything that StrictMode finds.  In particular,
     87  * many cases of disk access are often necessary during the normal activity lifecycle.  Use
     88  * StrictMode to find things you did by accident.  Network requests on the UI thread
     89  * are almost always a problem, though.
     90  *
     91  * <p class="note">StrictMode is not a security mechanism and is not
     92  * guaranteed to find all disk or network accesses.  While it does
     93  * propagate its state across process boundaries when doing
     94  * {@link android.os.Binder} calls, it's still ultimately a best
     95  * effort mechanism.  Notably, disk or network access from JNI calls
     96  * won't necessarily trigger it.  Future versions of Android may catch
     97  * more (or fewer) operations, so you should never leave StrictMode
     98  * enabled in shipping applications on the Android Market.
     99  */
    100 public final class StrictMode {
    101     private static final String TAG = "StrictMode";
    102     private static final boolean LOG_V = false;
    103 
    104     // Only log a duplicate stack trace to the logs every second.
    105     private static final long MIN_LOG_INTERVAL_MS = 1000;
    106 
    107     // Only show an annoying dialog at most every 30 seconds
    108     private static final long MIN_DIALOG_INTERVAL_MS = 30000;
    109 
    110     // How many offending stacks to keep track of (and time) per loop
    111     // of the Looper.
    112     private static final int MAX_OFFENSES_PER_LOOP = 10;
    113 
    114     // Thread-policy:
    115 
    116     /**
    117      * @hide
    118      */
    119     public static final int DETECT_DISK_WRITE = 0x01;  // for ThreadPolicy
    120 
    121     /**
    122       * @hide
    123      */
    124     public static final int DETECT_DISK_READ = 0x02;  // for ThreadPolicy
    125 
    126     /**
    127      * @hide
    128      */
    129     public static final int DETECT_NETWORK = 0x04;  // for ThreadPolicy
    130 
    131     // Process-policy:
    132 
    133     /**
    134      * Note, a "VM_" bit, not thread.
    135      * @hide
    136      */
    137     public static final int DETECT_VM_CURSOR_LEAKS = 0x200;  // for ProcessPolicy
    138 
    139     /**
    140      * @hide
    141      */
    142     public static final int PENALTY_LOG = 0x10;  // normal android.util.Log
    143 
    144     // Used for both process and thread policy:
    145 
    146     /**
    147      * @hide
    148      */
    149     public static final int PENALTY_DIALOG = 0x20;
    150 
    151     /**
    152      * @hide
    153      */
    154     public static final int PENALTY_DEATH = 0x40;
    155 
    156     /**
    157      * @hide
    158      */
    159     public static final int PENALTY_DROPBOX = 0x80;
    160 
    161     /**
    162      * Non-public penalty mode which overrides all the other penalty
    163      * bits and signals that we're in a Binder call and we should
    164      * ignore the other penalty bits and instead serialize back all
    165      * our offending stack traces to the caller to ultimately handle
    166      * in the originating process.
    167      *
    168      * This must be kept in sync with the constant in libs/binder/Parcel.cpp
    169      *
    170      * @hide
    171      */
    172     public static final int PENALTY_GATHER = 0x100;
    173 
    174     /**
    175      * The current VmPolicy in effect.
    176      */
    177     private static volatile int sVmPolicyMask = 0;
    178 
    179     private StrictMode() {}
    180 
    181     /**
    182      * {@link StrictMode} policy applied to a certain thread.
    183      *
    184      * <p>The policy is enabled by {@link #setThreadPolicy}.  The current policy
    185      * can be retrieved with {@link #getThreadPolicy}.
    186      *
    187      * <p>Note that multiple penalties may be provided and they're run
    188      * in order from least to most severe (logging before process
    189      * death, for example).  There's currently no mechanism to choose
    190      * different penalties for different detected actions.
    191      */
    192     public static final class ThreadPolicy {
    193         /**
    194          * The default, lax policy which doesn't catch anything.
    195          */
    196         public static final ThreadPolicy LAX = new ThreadPolicy(0);
    197 
    198         final int mask;
    199 
    200         private ThreadPolicy(int mask) {
    201             this.mask = mask;
    202         }
    203 
    204         @Override
    205         public String toString() {
    206             return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
    207         }
    208 
    209         /**
    210          * Creates ThreadPolicy instances.  Methods whose names start
    211          * with {@code detect} specify what problems we should look
    212          * for.  Methods whose names start with {@code penalty} specify what
    213          * we should do when we detect a problem.
    214          *
    215          * <p>You can call as many {@code detect} and {@code penalty}
    216          * methods as you like. Currently order is insignificant: all
    217          * penalties apply to all detected problems.
    218          *
    219          * <p>For example, detect everything and log anything that's found:
    220          * <pre>
    221          * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
    222          *     .detectAll()
    223          *     .penaltyLog()
    224          *     .build();
    225          * StrictMode.setVmPolicy(policy);
    226          * </pre>
    227          */
    228         public static final class Builder {
    229             private int mMask = 0;
    230 
    231             /**
    232              * Create a Builder that detects nothing and has no
    233              * violations.  (but note that {@link #build} will default
    234              * to enabling {@link #penaltyLog} if no other penalties
    235              * are specified)
    236              */
    237             public Builder() {
    238                 mMask = 0;
    239             }
    240 
    241             /**
    242              * Initialize a Builder from an existing ThreadPolicy.
    243              */
    244             public Builder(ThreadPolicy policy) {
    245                 mMask = policy.mask;
    246             }
    247 
    248             /**
    249              * Detect everything that's potentially suspect.
    250              *
    251              * <p>As of the Gingerbread release this includes network and
    252              * disk operations but will likely expand in future releases.
    253              */
    254             public Builder detectAll() {
    255                 return enable(DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK);
    256             }
    257 
    258             /**
    259              * Disable the detection of everything.
    260              */
    261             public Builder permitAll() {
    262                 return disable(DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK);
    263             }
    264 
    265             /**
    266              * Enable detection of network operations.
    267              */
    268             public Builder detectNetwork() {
    269                 return enable(DETECT_NETWORK);
    270             }
    271 
    272             /**
    273              * Disable detection of network operations.
    274              */
    275             public Builder permitNetwork() {
    276                 return disable(DETECT_NETWORK);
    277             }
    278 
    279             /**
    280              * Enable detection of disk reads.
    281              */
    282             public Builder detectDiskReads() {
    283                 return enable(DETECT_DISK_READ);
    284             }
    285 
    286             /**
    287              * Disable detection of disk reads.
    288              */
    289             public Builder permitDiskReads() {
    290                 return disable(DETECT_DISK_READ);
    291             }
    292 
    293             /**
    294              * Enable detection of disk writes.
    295              */
    296             public Builder detectDiskWrites() {
    297                 return enable(DETECT_DISK_WRITE);
    298             }
    299 
    300             /**
    301              * Disable detection of disk writes.
    302              */
    303             public Builder permitDiskWrites() {
    304                 return disable(DETECT_DISK_WRITE);
    305             }
    306 
    307             /**
    308              * Show an annoying dialog to the developer on detected
    309              * violations, rate-limited to be only a little annoying.
    310              */
    311             public Builder penaltyDialog() {
    312                 return enable(PENALTY_DIALOG);
    313             }
    314 
    315             /**
    316              * Crash the whole process on violation.  This penalty runs at
    317              * the end of all enabled penalties so you'll still get
    318              * see logging or other violations before the process dies.
    319              */
    320             public Builder penaltyDeath() {
    321                 return enable(PENALTY_DEATH);
    322             }
    323 
    324             /**
    325              * Log detected violations to the system log.
    326              */
    327             public Builder penaltyLog() {
    328                 return enable(PENALTY_LOG);
    329             }
    330 
    331             /**
    332              * Enable detected violations log a stacktrace and timing data
    333              * to the {@link android.os.DropBoxManager DropBox} on policy
    334              * violation.  Intended mostly for platform integrators doing
    335              * beta user field data collection.
    336              */
    337             public Builder penaltyDropBox() {
    338                 return enable(PENALTY_DROPBOX);
    339             }
    340 
    341             private Builder enable(int bit) {
    342                 mMask |= bit;
    343                 return this;
    344             }
    345 
    346             private Builder disable(int bit) {
    347                 mMask &= ~bit;
    348                 return this;
    349             }
    350 
    351             /**
    352              * Construct the ThreadPolicy instance.
    353              *
    354              * <p>Note: if no penalties are enabled before calling
    355              * <code>build</code>, {@link #penaltyLog} is implicitly
    356              * set.
    357              */
    358             public ThreadPolicy build() {
    359                 // If there are detection bits set but no violation bits
    360                 // set, enable simple logging.
    361                 if (mMask != 0 &&
    362                     (mMask & (PENALTY_DEATH | PENALTY_LOG |
    363                               PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
    364                     penaltyLog();
    365                 }
    366                 return new ThreadPolicy(mMask);
    367             }
    368         }
    369     }
    370 
    371     /**
    372      * {@link StrictMode} policy applied to all threads in the virtual machine's process.
    373      *
    374      * <p>The policy is enabled by {@link #setVmPolicy}.
    375      */
    376     public static final class VmPolicy {
    377         /**
    378          * The default, lax policy which doesn't catch anything.
    379          */
    380         public static final VmPolicy LAX = new VmPolicy(0);
    381 
    382         final int mask;
    383 
    384         private VmPolicy(int mask) {
    385             this.mask = mask;
    386         }
    387 
    388         @Override
    389         public String toString() {
    390             return "[StrictMode.VmPolicy; mask=" + mask + "]";
    391         }
    392 
    393         /**
    394          * Creates {@link VmPolicy} instances.  Methods whose names start
    395          * with {@code detect} specify what problems we should look
    396          * for.  Methods whose names start with {@code penalty} specify what
    397          * we should do when we detect a problem.
    398          *
    399          * <p>You can call as many {@code detect} and {@code penalty}
    400          * methods as you like. Currently order is insignificant: all
    401          * penalties apply to all detected problems.
    402          *
    403          * <p>For example, detect everything and log anything that's found:
    404          * <pre>
    405          * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
    406          *     .detectAll()
    407          *     .penaltyLog()
    408          *     .build();
    409          * StrictMode.setVmPolicy(policy);
    410          * </pre>
    411          */
    412         public static final class Builder {
    413             private int mMask;
    414 
    415             /**
    416              * Detect everything that's potentially suspect.
    417              *
    418              * <p>As of the Gingerbread release this only includes
    419              * SQLite cursor leaks but will likely expand in future
    420              * releases.
    421              */
    422             public Builder detectAll() {
    423                 return enable(DETECT_VM_CURSOR_LEAKS);
    424             }
    425 
    426             /**
    427              * Detect when an
    428              * {@link android.database.sqlite.SQLiteCursor} or other
    429              * SQLite object is finalized without having been closed.
    430              *
    431              * <p>You always want to explicitly close your SQLite
    432              * cursors to avoid unnecessary database contention and
    433              * temporary memory leaks.
    434              */
    435             public Builder detectLeakedSqlLiteObjects() {
    436                 return enable(DETECT_VM_CURSOR_LEAKS);
    437             }
    438 
    439             /**
    440              * Crashes the whole process on violation.  This penalty runs at
    441              * the end of all enabled penalties so yo you'll still get
    442              * your logging or other violations before the process dies.
    443              */
    444             public Builder penaltyDeath() {
    445                 return enable(PENALTY_DEATH);
    446             }
    447 
    448             /**
    449              * Log detected violations to the system log.
    450              */
    451             public Builder penaltyLog() {
    452                 return enable(PENALTY_LOG);
    453             }
    454 
    455             /**
    456              * Enable detected violations log a stacktrace and timing data
    457              * to the {@link android.os.DropBoxManager DropBox} on policy
    458              * violation.  Intended mostly for platform integrators doing
    459              * beta user field data collection.
    460              */
    461             public Builder penaltyDropBox() {
    462                 return enable(PENALTY_DROPBOX);
    463             }
    464 
    465             private Builder enable(int bit) {
    466                 mMask |= bit;
    467                 return this;
    468             }
    469 
    470             /**
    471              * Construct the VmPolicy instance.
    472              *
    473              * <p>Note: if no penalties are enabled before calling
    474              * <code>build</code>, {@link #penaltyLog} is implicitly
    475              * set.
    476              */
    477             public VmPolicy build() {
    478                 // If there are detection bits set but no violation bits
    479                 // set, enable simple logging.
    480                 if (mMask != 0 &&
    481                     (mMask & (PENALTY_DEATH | PENALTY_LOG |
    482                               PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
    483                     penaltyLog();
    484                 }
    485                 return new VmPolicy(mMask);
    486             }
    487         }
    488     }
    489 
    490     /**
    491      * Log of strict mode violation stack traces that have occurred
    492      * during a Binder call, to be serialized back later to the caller
    493      * via Parcel.writeNoException() (amusingly) where the caller can
    494      * choose how to react.
    495      */
    496     private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
    497             new ThreadLocal<ArrayList<ViolationInfo>>() {
    498         @Override protected ArrayList<ViolationInfo> initialValue() {
    499             // Starts null to avoid unnecessary allocations when
    500             // checking whether there are any violations or not in
    501             // hasGatheredViolations() below.
    502             return null;
    503         }
    504     };
    505 
    506     /**
    507      * Sets the policy for what actions on the current thread should
    508      * be detected, as well as the penalty if such actions occur.
    509      *
    510      * <p>Internally this sets a thread-local variable which is
    511      * propagated across cross-process IPC calls, meaning you can
    512      * catch violations when a system service or another process
    513      * accesses the disk or network on your behalf.
    514      *
    515      * @param policy the policy to put into place
    516      */
    517     public static void setThreadPolicy(final ThreadPolicy policy) {
    518         setThreadPolicyMask(policy.mask);
    519     }
    520 
    521     private static void setThreadPolicyMask(final int policyMask) {
    522         // In addition to the Java-level thread-local in Dalvik's
    523         // BlockGuard, we also need to keep a native thread-local in
    524         // Binder in order to propagate the value across Binder calls,
    525         // even across native-only processes.  The two are kept in
    526         // sync via the callback to onStrictModePolicyChange, below.
    527         setBlockGuardPolicy(policyMask);
    528 
    529         // And set the Android native version...
    530         Binder.setThreadStrictModePolicy(policyMask);
    531     }
    532 
    533     // Sets the policy in Dalvik/libcore (BlockGuard)
    534     private static void setBlockGuardPolicy(final int policyMask) {
    535         if (policyMask == 0) {
    536             BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
    537             return;
    538         }
    539         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
    540         if (!(policy instanceof AndroidBlockGuardPolicy)) {
    541             BlockGuard.setThreadPolicy(new AndroidBlockGuardPolicy(policyMask));
    542         } else {
    543             AndroidBlockGuardPolicy androidPolicy = (AndroidBlockGuardPolicy) policy;
    544             androidPolicy.setPolicyMask(policyMask);
    545         }
    546     }
    547 
    548     private static class StrictModeNetworkViolation extends BlockGuard.BlockGuardPolicyException {
    549         public StrictModeNetworkViolation(int policyMask) {
    550             super(policyMask, DETECT_NETWORK);
    551         }
    552     }
    553 
    554     private static class StrictModeDiskReadViolation extends BlockGuard.BlockGuardPolicyException {
    555         public StrictModeDiskReadViolation(int policyMask) {
    556             super(policyMask, DETECT_DISK_READ);
    557         }
    558     }
    559 
    560     private static class StrictModeDiskWriteViolation extends BlockGuard.BlockGuardPolicyException {
    561         public StrictModeDiskWriteViolation(int policyMask) {
    562             super(policyMask, DETECT_DISK_WRITE);
    563         }
    564     }
    565 
    566     /**
    567      * Returns the bitmask of the current thread's policy.
    568      *
    569      * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
    570      *
    571      * @hide
    572      */
    573     public static int getThreadPolicyMask() {
    574         return BlockGuard.getThreadPolicy().getPolicyMask();
    575     }
    576 
    577     /**
    578      * Returns the current thread's policy.
    579      */
    580     public static ThreadPolicy getThreadPolicy() {
    581         return new ThreadPolicy(getThreadPolicyMask());
    582     }
    583 
    584     /**
    585      * A convenience wrapper that takes the current
    586      * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
    587      * to permit both disk reads &amp; writes, and sets the new policy
    588      * with {@link #setThreadPolicy}, returning the old policy so you
    589      * can restore it at the end of a block.
    590      *
    591      * @return the old policy, to be passed to {@link #setThreadPolicy} to
    592      *         restore the policy at the end of a block
    593      */
    594     public static ThreadPolicy allowThreadDiskWrites() {
    595         int oldPolicyMask = getThreadPolicyMask();
    596         int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
    597         if (newPolicyMask != oldPolicyMask) {
    598             setThreadPolicyMask(newPolicyMask);
    599         }
    600         return new ThreadPolicy(oldPolicyMask);
    601     }
    602 
    603     /**
    604      * A convenience wrapper that takes the current
    605      * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
    606      * to permit disk reads, and sets the new policy
    607      * with {@link #setThreadPolicy}, returning the old policy so you
    608      * can restore it at the end of a block.
    609      *
    610      * @return the old policy, to be passed to setThreadPolicy to
    611      *         restore the policy.
    612      */
    613     public static ThreadPolicy allowThreadDiskReads() {
    614         int oldPolicyMask = getThreadPolicyMask();
    615         int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
    616         if (newPolicyMask != oldPolicyMask) {
    617             setThreadPolicyMask(newPolicyMask);
    618         }
    619         return new ThreadPolicy(oldPolicyMask);
    620     }
    621 
    622     /**
    623      * Enable DropBox logging for debug phone builds.
    624      *
    625      * @hide
    626      */
    627     public static boolean conditionallyEnableDebugLogging() {
    628         // For debug builds, log event loop stalls to dropbox for analysis.
    629         // Similar logic also appears in ActivityThread.java for system apps.
    630         if ("user".equals(Build.TYPE)) {
    631             return false;
    632         }
    633         StrictMode.setThreadPolicyMask(
    634             StrictMode.DETECT_DISK_WRITE |
    635             StrictMode.DETECT_DISK_READ |
    636             StrictMode.DETECT_NETWORK |
    637             StrictMode.PENALTY_DROPBOX);
    638         sVmPolicyMask = StrictMode.DETECT_VM_CURSOR_LEAKS |
    639                 StrictMode.PENALTY_DROPBOX |
    640                 StrictMode.PENALTY_LOG;
    641         return true;
    642     }
    643 
    644     /**
    645      * Parses the BlockGuard policy mask out from the Exception's
    646      * getMessage() String value.  Kinda gross, but least
    647      * invasive.  :/
    648      *
    649      * Input is of form "policy=137 violation=64"
    650      *
    651      * Returns 0 on failure, which is a valid policy, but not a
    652      * valid policy during a violation (else there must've been
    653      * some policy in effect to violate).
    654      */
    655     private static int parsePolicyFromMessage(String message) {
    656         if (message == null || !message.startsWith("policy=")) {
    657             return 0;
    658         }
    659         int spaceIndex = message.indexOf(' ');
    660         if (spaceIndex == -1) {
    661             return 0;
    662         }
    663         String policyString = message.substring(7, spaceIndex);
    664         try {
    665             return Integer.valueOf(policyString).intValue();
    666         } catch (NumberFormatException e) {
    667             return 0;
    668         }
    669     }
    670 
    671     /**
    672      * Like parsePolicyFromMessage(), but returns the violation.
    673      */
    674     private static int parseViolationFromMessage(String message) {
    675         if (message == null) {
    676             return 0;
    677         }
    678         int violationIndex = message.indexOf("violation=");
    679         if (violationIndex == -1) {
    680             return 0;
    681         }
    682         String violationString = message.substring(violationIndex + 10);
    683         try {
    684             return Integer.valueOf(violationString).intValue();
    685         } catch (NumberFormatException e) {
    686             return 0;
    687         }
    688     }
    689 
    690     private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
    691             new ThreadLocal<ArrayList<ViolationInfo>>() {
    692         @Override protected ArrayList<ViolationInfo> initialValue() {
    693             return new ArrayList<ViolationInfo>();
    694         }
    695     };
    696 
    697     private static boolean tooManyViolationsThisLoop() {
    698         return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
    699     }
    700 
    701     private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
    702         private int mPolicyMask;
    703 
    704         // Map from violation stacktrace hashcode -> uptimeMillis of
    705         // last violation.  No locking needed, as this is only
    706         // accessed by the same thread.
    707         private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>();
    708 
    709         public AndroidBlockGuardPolicy(final int policyMask) {
    710             mPolicyMask = policyMask;
    711         }
    712 
    713         @Override
    714         public String toString() {
    715             return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
    716         }
    717 
    718         // Part of BlockGuard.Policy interface:
    719         public int getPolicyMask() {
    720             return mPolicyMask;
    721         }
    722 
    723         // Part of BlockGuard.Policy interface:
    724         public void onWriteToDisk() {
    725             if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
    726                 return;
    727             }
    728             if (tooManyViolationsThisLoop()) {
    729                 return;
    730             }
    731             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
    732             e.fillInStackTrace();
    733             startHandlingViolationException(e);
    734         }
    735 
    736         // Part of BlockGuard.Policy interface:
    737         public void onReadFromDisk() {
    738             if ((mPolicyMask & DETECT_DISK_READ) == 0) {
    739                 return;
    740             }
    741             if (tooManyViolationsThisLoop()) {
    742                 return;
    743             }
    744             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
    745             e.fillInStackTrace();
    746             startHandlingViolationException(e);
    747         }
    748 
    749         // Part of BlockGuard.Policy interface:
    750         public void onNetwork() {
    751             if ((mPolicyMask & DETECT_NETWORK) == 0) {
    752                 return;
    753             }
    754             if (tooManyViolationsThisLoop()) {
    755                 return;
    756             }
    757             BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
    758             e.fillInStackTrace();
    759             startHandlingViolationException(e);
    760         }
    761 
    762         public void setPolicyMask(int policyMask) {
    763             mPolicyMask = policyMask;
    764         }
    765 
    766         // Start handling a violation that just started and hasn't
    767         // actually run yet (e.g. no disk write or network operation
    768         // has yet occurred).  This sees if we're in an event loop
    769         // thread and, if so, uses it to roughly measure how long the
    770         // violation took.
    771         void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) {
    772             final ViolationInfo info = new ViolationInfo(e, e.getPolicy());
    773             info.violationUptimeMillis = SystemClock.uptimeMillis();
    774             handleViolationWithTimingAttempt(info);
    775         }
    776 
    777         // Attempts to fill in the provided ViolationInfo's
    778         // durationMillis field if this thread has a Looper we can use
    779         // to measure with.  We measure from the time of violation
    780         // until the time the looper is idle again (right before
    781         // the next epoll_wait)
    782         void handleViolationWithTimingAttempt(final ViolationInfo info) {
    783             Looper looper = Looper.myLooper();
    784 
    785             // Without a Looper, we're unable to time how long the
    786             // violation takes place.  This case should be rare, as
    787             // most users will care about timing violations that
    788             // happen on their main UI thread.  Note that this case is
    789             // also hit when a violation takes place in a Binder
    790             // thread, in "gather" mode.  In this case, the duration
    791             // of the violation is computed by the ultimate caller and
    792             // its Looper, if any.
    793             // TODO: if in gather mode, ignore Looper.myLooper() and always
    794             //       go into this immediate mode?
    795             if (looper == null) {
    796                 info.durationMillis = -1;  // unknown (redundant, already set)
    797                 handleViolation(info);
    798                 return;
    799             }
    800 
    801             MessageQueue queue = Looper.myQueue();
    802             final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
    803             if (records.size() >= MAX_OFFENSES_PER_LOOP) {
    804                 // Not worth measuring.  Too many offenses in one loop.
    805                 return;
    806             }
    807             records.add(info);
    808             if (records.size() > 1) {
    809                 // There's already been a violation this loop, so we've already
    810                 // registered an idle handler to process the list of violations
    811                 // at the end of this Looper's loop.
    812                 return;
    813             }
    814 
    815             queue.addIdleHandler(new MessageQueue.IdleHandler() {
    816                     public boolean queueIdle() {
    817                         long loopFinishTime = SystemClock.uptimeMillis();
    818                         for (int n = 0; n < records.size(); ++n) {
    819                             ViolationInfo v = records.get(n);
    820                             v.violationNumThisLoop = n + 1;
    821                             v.durationMillis =
    822                                     (int) (loopFinishTime - v.violationUptimeMillis);
    823                             handleViolation(v);
    824                         }
    825                         records.clear();
    826                         return false;  // remove this idle handler from the array
    827                     }
    828                 });
    829         }
    830 
    831         // Note: It's possible (even quite likely) that the
    832         // thread-local policy mask has changed from the time the
    833         // violation fired and now (after the violating code ran) due
    834         // to people who push/pop temporary policy in regions of code,
    835         // hence the policy being passed around.
    836         void handleViolation(final ViolationInfo info) {
    837             if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) {
    838                 Log.wtf(TAG, "unexpected null stacktrace");
    839                 return;
    840             }
    841 
    842             if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy);
    843 
    844             if ((info.policy & PENALTY_GATHER) != 0) {
    845                 ArrayList<ViolationInfo> violations = gatheredViolations.get();
    846                 if (violations == null) {
    847                     violations = new ArrayList<ViolationInfo>(1);
    848                     gatheredViolations.set(violations);
    849                 } else if (violations.size() >= 5) {
    850                     // Too many.  In a loop or something?  Don't gather them all.
    851                     return;
    852                 }
    853                 for (ViolationInfo previous : violations) {
    854                     if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
    855                         // Duplicate. Don't log.
    856                         return;
    857                     }
    858                 }
    859                 violations.add(info);
    860                 return;
    861             }
    862 
    863             // Not perfect, but fast and good enough for dup suppression.
    864             Integer crashFingerprint = info.crashInfo.stackTrace.hashCode();
    865             long lastViolationTime = 0;
    866             if (mLastViolationTime.containsKey(crashFingerprint)) {
    867                 lastViolationTime = mLastViolationTime.get(crashFingerprint);
    868             }
    869             long now = SystemClock.uptimeMillis();
    870             mLastViolationTime.put(crashFingerprint, now);
    871             long timeSinceLastViolationMillis = lastViolationTime == 0 ?
    872                     Long.MAX_VALUE : (now - lastViolationTime);
    873 
    874             if ((info.policy & PENALTY_LOG) != 0 &&
    875                 timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
    876                 if (info.durationMillis != -1) {
    877                     Log.d(TAG, "StrictMode policy violation; ~duration=" +
    878                           info.durationMillis + " ms: " + info.crashInfo.stackTrace);
    879                 } else {
    880                     Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
    881                 }
    882             }
    883 
    884             // The violationMask, passed to ActivityManager, is a
    885             // subset of the original StrictMode policy bitmask, with
    886             // only the bit violated and penalty bits to be executed
    887             // by the ActivityManagerService remaining set.
    888             int violationMaskSubset = 0;
    889 
    890             if ((info.policy & PENALTY_DIALOG) != 0 &&
    891                 timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
    892                 violationMaskSubset |= PENALTY_DIALOG;
    893             }
    894 
    895             if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
    896                 violationMaskSubset |= PENALTY_DROPBOX;
    897             }
    898 
    899             if (violationMaskSubset != 0) {
    900                 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
    901                 violationMaskSubset |= violationBit;
    902                 final int savedPolicyMask = getThreadPolicyMask();
    903                 try {
    904                     // First, remove any policy before we call into the Activity Manager,
    905                     // otherwise we'll infinite recurse as we try to log policy violations
    906                     // to disk, thus violating policy, thus requiring logging, etc...
    907                     // We restore the current policy below, in the finally block.
    908                     setThreadPolicyMask(0);
    909 
    910                     ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
    911                         RuntimeInit.getApplicationObject(),
    912                         violationMaskSubset,
    913                         info);
    914                 } catch (RemoteException e) {
    915                     Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
    916                 } finally {
    917                     // Restore the policy.
    918                     setThreadPolicyMask(savedPolicyMask);
    919                 }
    920             }
    921 
    922             if ((info.policy & PENALTY_DEATH) != 0) {
    923                 System.err.println("StrictMode policy violation with POLICY_DEATH; shutting down.");
    924                 Process.killProcess(Process.myPid());
    925                 System.exit(10);
    926             }
    927         }
    928     }
    929 
    930     /**
    931      * Called from Parcel.writeNoException()
    932      */
    933     /* package */ static boolean hasGatheredViolations() {
    934         return gatheredViolations.get() != null;
    935     }
    936 
    937     /**
    938      * Called from Parcel.writeException(), so we drop this memory and
    939      * don't incorrectly attribute it to the wrong caller on the next
    940      * Binder call on this thread.
    941      */
    942     /* package */ static void clearGatheredViolations() {
    943         gatheredViolations.set(null);
    944     }
    945 
    946     /**
    947      * Sets the policy for what actions in the VM process (on any
    948      * thread) should be detected, as well as the penalty if such
    949      * actions occur.
    950      *
    951      * @param policy the policy to put into place
    952      */
    953     public static void setVmPolicy(final VmPolicy policy) {
    954         sVmPolicyMask = policy.mask;
    955     }
    956 
    957     /**
    958      * Gets the current VM policy.
    959      */
    960     public static VmPolicy getVmPolicy() {
    961         return new VmPolicy(sVmPolicyMask);
    962     }
    963 
    964     /**
    965      * Enable the recommended StrictMode defaults, with violations just being logged.
    966      *
    967      * <p>This catches disk and network access on the main thread, as
    968      * well as leaked SQLite cursors.  This is simply a wrapper around
    969      * {@link #setVmPolicy} and {@link #setThreadPolicy}.
    970      */
    971     public static void enableDefaults() {
    972         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
    973                                    .detectAll()
    974                                    .penaltyLog()
    975                                    .build());
    976         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
    977                                .detectLeakedSqlLiteObjects()
    978                                .penaltyLog()
    979                                .build());
    980     }
    981 
    982     /**
    983      * @hide
    984      */
    985     public static boolean vmSqliteObjectLeaksEnabled() {
    986         return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
    987     }
    988 
    989     /**
    990      * @hide
    991      */
    992     public static void onSqliteObjectLeaked(String message, Throwable originStack) {
    993         if ((sVmPolicyMask & PENALTY_LOG) != 0) {
    994             Log.e(TAG, message, originStack);
    995         }
    996 
    997         if ((sVmPolicyMask & PENALTY_DROPBOX) != 0) {
    998             final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
    999 
   1000             // The violationMask, passed to ActivityManager, is a
   1001             // subset of the original StrictMode policy bitmask, with
   1002             // only the bit violated and penalty bits to be executed
   1003             // by the ActivityManagerService remaining set.
   1004             int violationMaskSubset = PENALTY_DROPBOX | DETECT_VM_CURSOR_LEAKS;
   1005             final int savedPolicyMask = getThreadPolicyMask();
   1006             try {
   1007                 // First, remove any policy before we call into the Activity Manager,
   1008                 // otherwise we'll infinite recurse as we try to log policy violations
   1009                 // to disk, thus violating policy, thus requiring logging, etc...
   1010                 // We restore the current policy below, in the finally block.
   1011                 setThreadPolicyMask(0);
   1012 
   1013                 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
   1014                     RuntimeInit.getApplicationObject(),
   1015                     violationMaskSubset,
   1016                     info);
   1017             } catch (RemoteException e) {
   1018                 Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
   1019             } finally {
   1020                 // Restore the policy.
   1021                 setThreadPolicyMask(savedPolicyMask);
   1022             }
   1023         }
   1024 
   1025         if ((sVmPolicyMask & PENALTY_DEATH) != 0) {
   1026             System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
   1027             Process.killProcess(Process.myPid());
   1028             System.exit(10);
   1029         }
   1030     }
   1031 
   1032     /**
   1033      * Called from Parcel.writeNoException()
   1034      */
   1035     /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
   1036         ArrayList<ViolationInfo> violations = gatheredViolations.get();
   1037         if (violations == null) {
   1038             p.writeInt(0);
   1039         } else {
   1040             p.writeInt(violations.size());
   1041             for (int i = 0; i < violations.size(); ++i) {
   1042                 violations.get(i).writeToParcel(p, 0 /* unused flags? */);
   1043             }
   1044             if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
   1045             violations.clear(); // somewhat redundant, as we're about to null the threadlocal
   1046         }
   1047         gatheredViolations.set(null);
   1048     }
   1049 
   1050     private static class LogStackTrace extends Exception {}
   1051 
   1052     /**
   1053      * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
   1054      * we here read back all the encoded violations.
   1055      */
   1056     /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
   1057         // Our own stack trace to append
   1058         StringWriter sw = new StringWriter();
   1059         new LogStackTrace().printStackTrace(new PrintWriter(sw));
   1060         String ourStack = sw.toString();
   1061 
   1062         int policyMask = getThreadPolicyMask();
   1063         boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
   1064 
   1065         int numViolations = p.readInt();
   1066         for (int i = 0; i < numViolations; ++i) {
   1067             if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call.  i=" + i);
   1068             ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
   1069             info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
   1070             BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   1071             if (policy instanceof AndroidBlockGuardPolicy) {
   1072                 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
   1073             }
   1074         }
   1075     }
   1076 
   1077     /**
   1078      * Called from android_util_Binder.cpp's
   1079      * android_os_Parcel_enforceInterface when an incoming Binder call
   1080      * requires changing the StrictMode policy mask.  The role of this
   1081      * function is to ask Binder for its current (native) thread-local
   1082      * policy value and synchronize it to libcore's (Java)
   1083      * thread-local policy value.
   1084      */
   1085     private static void onBinderStrictModePolicyChange(int newPolicy) {
   1086         setBlockGuardPolicy(newPolicy);
   1087     }
   1088 
   1089     /**
   1090      * Parcelable that gets sent in Binder call headers back to callers
   1091      * to report violations that happened during a cross-process call.
   1092      *
   1093      * @hide
   1094      */
   1095     public static class ViolationInfo {
   1096         /**
   1097          * Stack and other stuff info.
   1098          */
   1099         public final ApplicationErrorReport.CrashInfo crashInfo;
   1100 
   1101         /**
   1102          * The strict mode policy mask at the time of violation.
   1103          */
   1104         public final int policy;
   1105 
   1106         /**
   1107          * The wall time duration of the violation, when known.  -1 when
   1108          * not known.
   1109          */
   1110         public int durationMillis = -1;
   1111 
   1112         /**
   1113          * Which violation number this was (1-based) since the last Looper loop,
   1114          * from the perspective of the root caller (if it crossed any processes
   1115          * via Binder calls).  The value is 0 if the root caller wasn't on a Looper
   1116          * thread.
   1117          */
   1118         public int violationNumThisLoop;
   1119 
   1120         /**
   1121          * The time (in terms of SystemClock.uptimeMillis()) that the
   1122          * violation occurred.
   1123          */
   1124         public long violationUptimeMillis;
   1125 
   1126         /**
   1127          * Create an uninitialized instance of ViolationInfo
   1128          */
   1129         public ViolationInfo() {
   1130             crashInfo = null;
   1131             policy = 0;
   1132         }
   1133 
   1134         /**
   1135          * Create an instance of ViolationInfo initialized from an exception.
   1136          */
   1137         public ViolationInfo(Throwable tr, int policy) {
   1138             crashInfo = new ApplicationErrorReport.CrashInfo(tr);
   1139             violationUptimeMillis = SystemClock.uptimeMillis();
   1140             this.policy = policy;
   1141         }
   1142 
   1143         /**
   1144          * Create an instance of ViolationInfo initialized from a Parcel.
   1145          */
   1146         public ViolationInfo(Parcel in) {
   1147             this(in, false);
   1148         }
   1149 
   1150         /**
   1151          * Create an instance of ViolationInfo initialized from a Parcel.
   1152          *
   1153          * @param unsetGatheringBit if true, the caller is the root caller
   1154          *   and the gathering penalty should be removed.
   1155          */
   1156         public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
   1157             crashInfo = new ApplicationErrorReport.CrashInfo(in);
   1158             int rawPolicy = in.readInt();
   1159             if (unsetGatheringBit) {
   1160                 policy = rawPolicy & ~PENALTY_GATHER;
   1161             } else {
   1162                 policy = rawPolicy;
   1163             }
   1164             durationMillis = in.readInt();
   1165             violationNumThisLoop = in.readInt();
   1166             violationUptimeMillis = in.readLong();
   1167         }
   1168 
   1169         /**
   1170          * Save a ViolationInfo instance to a parcel.
   1171          */
   1172         public void writeToParcel(Parcel dest, int flags) {
   1173             crashInfo.writeToParcel(dest, flags);
   1174             dest.writeInt(policy);
   1175             dest.writeInt(durationMillis);
   1176             dest.writeInt(violationNumThisLoop);
   1177             dest.writeLong(violationUptimeMillis);
   1178         }
   1179 
   1180 
   1181         /**
   1182          * Dump a ViolationInfo instance to a Printer.
   1183          */
   1184         public void dump(Printer pw, String prefix) {
   1185             crashInfo.dump(pw, prefix);
   1186             pw.println(prefix + "policy: " + policy);
   1187             if (durationMillis != -1) {
   1188                 pw.println(prefix + "durationMillis: " + durationMillis);
   1189             }
   1190             if (violationNumThisLoop != 0) {
   1191                 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
   1192             }
   1193             pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
   1194         }
   1195 
   1196     }
   1197 }
   1198