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.animation.ValueAnimator;
     19 import android.app.ActivityManagerNative;
     20 import android.app.ActivityThread;
     21 import android.app.ApplicationErrorReport;
     22 import android.app.IActivityManager;
     23 import android.content.BroadcastReceiver;
     24 import android.content.Context;
     25 import android.content.Intent;
     26 import android.content.ServiceConnection;
     27 import android.net.Uri;
     28 import android.util.ArrayMap;
     29 import android.util.Log;
     30 import android.util.Printer;
     31 import android.util.Singleton;
     32 import android.util.Slog;
     33 import android.view.IWindowManager;
     34 
     35 import com.android.internal.os.RuntimeInit;
     36 import com.android.internal.util.FastPrintWriter;
     37 import com.android.internal.util.HexDump;
     38 
     39 import dalvik.system.BlockGuard;
     40 import dalvik.system.CloseGuard;
     41 import dalvik.system.VMDebug;
     42 
     43 import java.io.PrintWriter;
     44 import java.io.StringWriter;
     45 import java.net.InetAddress;
     46 import java.net.UnknownHostException;
     47 import java.util.ArrayList;
     48 import java.util.Arrays;
     49 import java.util.HashMap;
     50 import java.util.concurrent.atomic.AtomicInteger;
     51 
     52 /**
     53  * <p>StrictMode is a developer tool which detects things you might be
     54  * doing by accident and brings them to your attention so you can fix
     55  * them.
     56  *
     57  * <p>StrictMode is most commonly used to catch accidental disk or
     58  * network access on the application's main thread, where UI
     59  * operations are received and animations take place.  Keeping disk
     60  * and network operations off the main thread makes for much smoother,
     61  * more responsive applications.  By keeping your application's main thread
     62  * responsive, you also prevent
     63  * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
     64  * from being shown to users.
     65  *
     66  * <p class="note">Note that even though an Android device's disk is
     67  * often on flash memory, many devices run a filesystem on top of that
     68  * memory with very limited concurrency.  It's often the case that
     69  * almost all disk accesses are fast, but may in individual cases be
     70  * dramatically slower when certain I/O is happening in the background
     71  * from other processes.  If possible, it's best to assume that such
     72  * things are not fast.</p>
     73  *
     74  * <p>Example code to enable from early in your
     75  * {@link android.app.Application}, {@link android.app.Activity}, or
     76  * other application component's
     77  * {@link android.app.Application#onCreate} method:
     78  *
     79  * <pre>
     80  * public void onCreate() {
     81  *     if (DEVELOPER_MODE) {
     82  *         StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
     83  *                 .detectDiskReads()
     84  *                 .detectDiskWrites()
     85  *                 .detectNetwork()   // or .detectAll() for all detectable problems
     86  *                 .penaltyLog()
     87  *                 .build());
     88  *         StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
     89  *                 .detectLeakedSqlLiteObjects()
     90  *                 .detectLeakedClosableObjects()
     91  *                 .penaltyLog()
     92  *                 .penaltyDeath()
     93  *                 .build());
     94  *     }
     95  *     super.onCreate();
     96  * }
     97  * </pre>
     98  *
     99  * <p>You can decide what should happen when a violation is detected.
    100  * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can
    101  * watch the output of <code>adb logcat</code> while you use your
    102  * application to see the violations as they happen.
    103  *
    104  * <p>If you find violations that you feel are problematic, there are
    105  * a variety of tools to help solve them: threads, {@link android.os.Handler},
    106  * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
    107  * But don't feel compelled to fix everything that StrictMode finds.  In particular,
    108  * many cases of disk access are often necessary during the normal activity lifecycle.  Use
    109  * StrictMode to find things you did by accident.  Network requests on the UI thread
    110  * are almost always a problem, though.
    111  *
    112  * <p class="note">StrictMode is not a security mechanism and is not
    113  * guaranteed to find all disk or network accesses.  While it does
    114  * propagate its state across process boundaries when doing
    115  * {@link android.os.Binder} calls, it's still ultimately a best
    116  * effort mechanism.  Notably, disk or network access from JNI calls
    117  * won't necessarily trigger it.  Future versions of Android may catch
    118  * more (or fewer) operations, so you should never leave StrictMode
    119  * enabled in applications distributed on Google Play.
    120  */
    121 public final class StrictMode {
    122     private static final String TAG = "StrictMode";
    123     private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
    124 
    125     private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
    126     private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE);
    127 
    128     /**
    129      * Boolean system property to disable strict mode checks outright.
    130      * Set this to 'true' to force disable; 'false' has no effect on other
    131      * enable/disable policy.
    132      * @hide
    133      */
    134     public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
    135 
    136     /**
    137      * The boolean system property to control screen flashes on violations.
    138      *
    139      * @hide
    140      */
    141     public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
    142 
    143     /**
    144      * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK}
    145      * in {@link VmPolicy.Builder#detectAll()}. Apps can still always opt-into
    146      * detection using {@link VmPolicy.Builder#detectCleartextNetwork()}.
    147      */
    148     private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.clear";
    149 
    150     // Only log a duplicate stack trace to the logs every second.
    151     private static final long MIN_LOG_INTERVAL_MS = 1000;
    152 
    153     // Only show an annoying dialog at most every 30 seconds
    154     private static final long MIN_DIALOG_INTERVAL_MS = 30000;
    155 
    156     // How many Span tags (e.g. animations) to report.
    157     private static final int MAX_SPAN_TAGS = 20;
    158 
    159     // How many offending stacks to keep track of (and time) per loop
    160     // of the Looper.
    161     private static final int MAX_OFFENSES_PER_LOOP = 10;
    162 
    163     // Byte 1: Thread-policy
    164 
    165     /**
    166      * @hide
    167      */
    168     public static final int DETECT_DISK_WRITE = 0x01;  // for ThreadPolicy
    169 
    170     /**
    171       * @hide
    172      */
    173     public static final int DETECT_DISK_READ = 0x02;  // for ThreadPolicy
    174 
    175     /**
    176      * @hide
    177      */
    178     public static final int DETECT_NETWORK = 0x04;  // for ThreadPolicy
    179 
    180     /**
    181      * For StrictMode.noteSlowCall()
    182      *
    183      * @hide
    184      */
    185     public static final int DETECT_CUSTOM = 0x08;  // for ThreadPolicy
    186 
    187     /**
    188      * For StrictMode.noteResourceMismatch()
    189      *
    190      * @hide
    191      */
    192     public static final int DETECT_RESOURCE_MISMATCH = 0x10;  // for ThreadPolicy
    193 
    194     private static final int ALL_THREAD_DETECT_BITS =
    195             DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM |
    196             DETECT_RESOURCE_MISMATCH;
    197 
    198     // Byte 2: Process-policy
    199 
    200     /**
    201      * Note, a "VM_" bit, not thread.
    202      * @hide
    203      */
    204     public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8;  // for VmPolicy
    205 
    206     /**
    207      * Note, a "VM_" bit, not thread.
    208      * @hide
    209      */
    210     public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8;  // for VmPolicy
    211 
    212     /**
    213      * Note, a "VM_" bit, not thread.
    214      * @hide
    215      */
    216     public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8;  // for VmPolicy
    217 
    218     /**
    219      * @hide
    220      */
    221     private static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8;  // for VmPolicy
    222 
    223     /**
    224      * @hide
    225      */
    226     public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8;  // for VmPolicy
    227 
    228     /**
    229      * @hide
    230      */
    231     private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8;  // for VmPolicy
    232 
    233     /**
    234      * @hide
    235      */
    236     private static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8;  // for VmPolicy
    237 
    238     private static final int ALL_VM_DETECT_BITS =
    239             DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
    240             DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
    241             DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE |
    242             DETECT_VM_CLEARTEXT_NETWORK;
    243 
    244     // Byte 3: Penalty
    245 
    246     /** {@hide} */
    247     public static final int PENALTY_LOG = 0x01 << 16;  // normal android.util.Log
    248     /** {@hide} */
    249     public static final int PENALTY_DIALOG = 0x02 << 16;
    250     /** {@hide} */
    251     public static final int PENALTY_DEATH = 0x04 << 16;
    252     /** {@hide} */
    253     public static final int PENALTY_FLASH = 0x10 << 16;
    254     /** {@hide} */
    255     public static final int PENALTY_DROPBOX = 0x20 << 16;
    256 
    257     /**
    258      * Non-public penalty mode which overrides all the other penalty
    259      * bits and signals that we're in a Binder call and we should
    260      * ignore the other penalty bits and instead serialize back all
    261      * our offending stack traces to the caller to ultimately handle
    262      * in the originating process.
    263      *
    264      * This must be kept in sync with the constant in libs/binder/Parcel.cpp
    265      *
    266      * @hide
    267      */
    268     public static final int PENALTY_GATHER = 0x40 << 16;
    269 
    270     // Byte 4: Special cases
    271 
    272     /**
    273      * Death when network traffic is detected on main thread.
    274      *
    275      * @hide
    276      */
    277     public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
    278 
    279     /**
    280      * Death when cleartext network traffic is detected.
    281      *
    282      * @hide
    283      */
    284     public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
    285 
    286     /**
    287      * Death when file exposure is detected.
    288      *
    289      * @hide
    290      */
    291     public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
    292 
    293     /**
    294      * Mask of all the penalty bits valid for thread policies.
    295      */
    296     private static final int THREAD_PENALTY_MASK =
    297             PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
    298             PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;
    299 
    300     /**
    301      * Mask of all the penalty bits valid for VM policies.
    302      */
    303     private static final int VM_PENALTY_MASK = PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX
    304             | PENALTY_DEATH_ON_CLEARTEXT_NETWORK | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
    305 
    306     /** {@hide} */
    307     public static final int NETWORK_POLICY_ACCEPT = 0;
    308     /** {@hide} */
    309     public static final int NETWORK_POLICY_LOG = 1;
    310     /** {@hide} */
    311     public static final int NETWORK_POLICY_REJECT = 2;
    312 
    313     // TODO: wrap in some ImmutableHashMap thing.
    314     // Note: must be before static initialization of sVmPolicy.
    315     private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP = new HashMap<Class, Integer>();
    316 
    317     /**
    318      * The current VmPolicy in effect.
    319      *
    320      * TODO: these are redundant (mask is in VmPolicy).  Should remove sVmPolicyMask.
    321      */
    322     private static volatile int sVmPolicyMask = 0;
    323     private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
    324 
    325     /**
    326      * The number of threads trying to do an async dropbox write.
    327      * Just to limit ourselves out of paranoia.
    328      */
    329     private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
    330 
    331     private StrictMode() {}
    332 
    333     /**
    334      * {@link StrictMode} policy applied to a certain thread.
    335      *
    336      * <p>The policy is enabled by {@link #setThreadPolicy}.  The current policy
    337      * can be retrieved with {@link #getThreadPolicy}.
    338      *
    339      * <p>Note that multiple penalties may be provided and they're run
    340      * in order from least to most severe (logging before process
    341      * death, for example).  There's currently no mechanism to choose
    342      * different penalties for different detected actions.
    343      */
    344     public static final class ThreadPolicy {
    345         /**
    346          * The default, lax policy which doesn't catch anything.
    347          */
    348         public static final ThreadPolicy LAX = new ThreadPolicy(0);
    349 
    350         final int mask;
    351 
    352         private ThreadPolicy(int mask) {
    353             this.mask = mask;
    354         }
    355 
    356         @Override
    357         public String toString() {
    358             return "[StrictMode.ThreadPolicy; mask=" + mask + "]";
    359         }
    360 
    361         /**
    362          * Creates {@link ThreadPolicy} instances.  Methods whose names start
    363          * with {@code detect} specify what problems we should look
    364          * for.  Methods whose names start with {@code penalty} specify what
    365          * we should do when we detect a problem.
    366          *
    367          * <p>You can call as many {@code detect} and {@code penalty}
    368          * methods as you like. Currently order is insignificant: all
    369          * penalties apply to all detected problems.
    370          *
    371          * <p>For example, detect everything and log anything that's found:
    372          * <pre>
    373          * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
    374          *     .detectAll()
    375          *     .penaltyLog()
    376          *     .build();
    377          * StrictMode.setThreadPolicy(policy);
    378          * </pre>
    379          */
    380         public static final class Builder {
    381             private int mMask = 0;
    382 
    383             /**
    384              * Create a Builder that detects nothing and has no
    385              * violations.  (but note that {@link #build} will default
    386              * to enabling {@link #penaltyLog} if no other penalties
    387              * are specified)
    388              */
    389             public Builder() {
    390                 mMask = 0;
    391             }
    392 
    393             /**
    394              * Initialize a Builder from an existing ThreadPolicy.
    395              */
    396             public Builder(ThreadPolicy policy) {
    397                 mMask = policy.mask;
    398             }
    399 
    400             /**
    401              * Detect everything that's potentially suspect.
    402              *
    403              * <p>As of the Gingerbread release this includes network and
    404              * disk operations but will likely expand in future releases.
    405              */
    406             public Builder detectAll() {
    407                 return enable(ALL_THREAD_DETECT_BITS);
    408             }
    409 
    410             /**
    411              * Disable the detection of everything.
    412              */
    413             public Builder permitAll() {
    414                 return disable(ALL_THREAD_DETECT_BITS);
    415             }
    416 
    417             /**
    418              * Enable detection of network operations.
    419              */
    420             public Builder detectNetwork() {
    421                 return enable(DETECT_NETWORK);
    422             }
    423 
    424             /**
    425              * Disable detection of network operations.
    426              */
    427             public Builder permitNetwork() {
    428                 return disable(DETECT_NETWORK);
    429             }
    430 
    431             /**
    432              * Enable detection of disk reads.
    433              */
    434             public Builder detectDiskReads() {
    435                 return enable(DETECT_DISK_READ);
    436             }
    437 
    438             /**
    439              * Disable detection of disk reads.
    440              */
    441             public Builder permitDiskReads() {
    442                 return disable(DETECT_DISK_READ);
    443             }
    444 
    445             /**
    446              * Enable detection of slow calls.
    447              */
    448             public Builder detectCustomSlowCalls() {
    449                 return enable(DETECT_CUSTOM);
    450             }
    451 
    452             /**
    453              * Disable detection of slow calls.
    454              */
    455             public Builder permitCustomSlowCalls() {
    456                 return disable(DETECT_CUSTOM);
    457             }
    458 
    459             /**
    460              * Disable detection of mismatches between defined resource types
    461              * and getter calls.
    462              */
    463             public Builder permitResourceMismatches() {
    464                 return disable(DETECT_RESOURCE_MISMATCH);
    465             }
    466 
    467             /**
    468              * Enables detection of mismatches between defined resource types
    469              * and getter calls.
    470              * <p>
    471              * This helps detect accidental type mismatches and potentially
    472              * expensive type conversions when obtaining typed resources.
    473              * <p>
    474              * For example, a strict mode violation would be thrown when
    475              * calling {@link android.content.res.TypedArray#getInt(int, int)}
    476              * on an index that contains a String-type resource. If the string
    477              * value can be parsed as an integer, this method call will return
    478              * a value without crashing; however, the developer should format
    479              * the resource as an integer to avoid unnecessary type conversion.
    480              */
    481             public Builder detectResourceMismatches() {
    482                 return enable(DETECT_RESOURCE_MISMATCH);
    483             }
    484 
    485             /**
    486              * Enable detection of disk writes.
    487              */
    488             public Builder detectDiskWrites() {
    489                 return enable(DETECT_DISK_WRITE);
    490             }
    491 
    492             /**
    493              * Disable detection of disk writes.
    494              */
    495             public Builder permitDiskWrites() {
    496                 return disable(DETECT_DISK_WRITE);
    497             }
    498 
    499             /**
    500              * Show an annoying dialog to the developer on detected
    501              * violations, rate-limited to be only a little annoying.
    502              */
    503             public Builder penaltyDialog() {
    504                 return enable(PENALTY_DIALOG);
    505             }
    506 
    507             /**
    508              * Crash the whole process on violation.  This penalty runs at
    509              * the end of all enabled penalties so you'll still get
    510              * see logging or other violations before the process dies.
    511              *
    512              * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies
    513              * to disk reads, disk writes, and network usage if their
    514              * corresponding detect flags are set.
    515              */
    516             public Builder penaltyDeath() {
    517                 return enable(PENALTY_DEATH);
    518             }
    519 
    520             /**
    521              * Crash the whole process on any network usage.  Unlike
    522              * {@link #penaltyDeath}, this penalty runs
    523              * <em>before</em> anything else.  You must still have
    524              * called {@link #detectNetwork} to enable this.
    525              *
    526              * <p>In the Honeycomb or later SDKs, this is on by default.
    527              */
    528             public Builder penaltyDeathOnNetwork() {
    529                 return enable(PENALTY_DEATH_ON_NETWORK);
    530             }
    531 
    532             /**
    533              * Flash the screen during a violation.
    534              */
    535             public Builder penaltyFlashScreen() {
    536                 return enable(PENALTY_FLASH);
    537             }
    538 
    539             /**
    540              * Log detected violations to the system log.
    541              */
    542             public Builder penaltyLog() {
    543                 return enable(PENALTY_LOG);
    544             }
    545 
    546             /**
    547              * Enable detected violations log a stacktrace and timing data
    548              * to the {@link android.os.DropBoxManager DropBox} on policy
    549              * violation.  Intended mostly for platform integrators doing
    550              * beta user field data collection.
    551              */
    552             public Builder penaltyDropBox() {
    553                 return enable(PENALTY_DROPBOX);
    554             }
    555 
    556             private Builder enable(int bit) {
    557                 mMask |= bit;
    558                 return this;
    559             }
    560 
    561             private Builder disable(int bit) {
    562                 mMask &= ~bit;
    563                 return this;
    564             }
    565 
    566             /**
    567              * Construct the ThreadPolicy instance.
    568              *
    569              * <p>Note: if no penalties are enabled before calling
    570              * <code>build</code>, {@link #penaltyLog} is implicitly
    571              * set.
    572              */
    573             public ThreadPolicy build() {
    574                 // If there are detection bits set but no violation bits
    575                 // set, enable simple logging.
    576                 if (mMask != 0 &&
    577                     (mMask & (PENALTY_DEATH | PENALTY_LOG |
    578                               PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
    579                     penaltyLog();
    580                 }
    581                 return new ThreadPolicy(mMask);
    582             }
    583         }
    584     }
    585 
    586     /**
    587      * {@link StrictMode} policy applied to all threads in the virtual machine's process.
    588      *
    589      * <p>The policy is enabled by {@link #setVmPolicy}.
    590      */
    591     public static final class VmPolicy {
    592         /**
    593          * The default, lax policy which doesn't catch anything.
    594          */
    595         public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP);
    596 
    597         final int mask;
    598 
    599         // Map from class to max number of allowed instances in memory.
    600         final HashMap<Class, Integer> classInstanceLimit;
    601 
    602         private VmPolicy(int mask, HashMap<Class, Integer> classInstanceLimit) {
    603             if (classInstanceLimit == null) {
    604                 throw new NullPointerException("classInstanceLimit == null");
    605             }
    606             this.mask = mask;
    607             this.classInstanceLimit = classInstanceLimit;
    608         }
    609 
    610         @Override
    611         public String toString() {
    612             return "[StrictMode.VmPolicy; mask=" + mask + "]";
    613         }
    614 
    615         /**
    616          * Creates {@link VmPolicy} instances.  Methods whose names start
    617          * with {@code detect} specify what problems we should look
    618          * for.  Methods whose names start with {@code penalty} specify what
    619          * we should do when we detect a problem.
    620          *
    621          * <p>You can call as many {@code detect} and {@code penalty}
    622          * methods as you like. Currently order is insignificant: all
    623          * penalties apply to all detected problems.
    624          *
    625          * <p>For example, detect everything and log anything that's found:
    626          * <pre>
    627          * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
    628          *     .detectAll()
    629          *     .penaltyLog()
    630          *     .build();
    631          * StrictMode.setVmPolicy(policy);
    632          * </pre>
    633          */
    634         public static final class Builder {
    635             private int mMask;
    636 
    637             private HashMap<Class, Integer> mClassInstanceLimit;  // null until needed
    638             private boolean mClassInstanceLimitNeedCow = false;  // need copy-on-write
    639 
    640             public Builder() {
    641                 mMask = 0;
    642             }
    643 
    644             /**
    645              * Build upon an existing VmPolicy.
    646              */
    647             public Builder(VmPolicy base) {
    648                 mMask = base.mask;
    649                 mClassInstanceLimitNeedCow = true;
    650                 mClassInstanceLimit = base.classInstanceLimit;
    651             }
    652 
    653             /**
    654              * Set an upper bound on how many instances of a class can be in memory
    655              * at once.  Helps to prevent object leaks.
    656              */
    657             public Builder setClassInstanceLimit(Class klass, int instanceLimit) {
    658                 if (klass == null) {
    659                     throw new NullPointerException("klass == null");
    660                 }
    661                 if (mClassInstanceLimitNeedCow) {
    662                     if (mClassInstanceLimit.containsKey(klass) &&
    663                         mClassInstanceLimit.get(klass) == instanceLimit) {
    664                         // no-op; don't break COW
    665                         return this;
    666                     }
    667                     mClassInstanceLimitNeedCow = false;
    668                     mClassInstanceLimit = (HashMap<Class, Integer>) mClassInstanceLimit.clone();
    669                 } else if (mClassInstanceLimit == null) {
    670                     mClassInstanceLimit = new HashMap<Class, Integer>();
    671                 }
    672                 mMask |= DETECT_VM_INSTANCE_LEAKS;
    673                 mClassInstanceLimit.put(klass, instanceLimit);
    674                 return this;
    675             }
    676 
    677             /**
    678              * Detect leaks of {@link android.app.Activity} subclasses.
    679              */
    680             public Builder detectActivityLeaks() {
    681                 return enable(DETECT_VM_ACTIVITY_LEAKS);
    682             }
    683 
    684             /**
    685              * Detect everything that's potentially suspect.
    686              *
    687              * <p>In the Honeycomb release this includes leaks of
    688              * SQLite cursors, Activities, and other closable objects
    689              * but will likely expand in future releases.
    690              */
    691             public Builder detectAll() {
    692                 int flags = DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
    693                         | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS
    694                         | DETECT_VM_FILE_URI_EXPOSURE;
    695 
    696                 // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have facility
    697                 // for apps to mark sockets that should be ignored
    698                 if (SystemProperties.getBoolean(CLEARTEXT_PROPERTY, false)) {
    699                     flags |= DETECT_VM_CLEARTEXT_NETWORK;
    700                 }
    701 
    702                 return enable(flags);
    703             }
    704 
    705             /**
    706              * Detect when an
    707              * {@link android.database.sqlite.SQLiteCursor} or other
    708              * SQLite object is finalized without having been closed.
    709              *
    710              * <p>You always want to explicitly close your SQLite
    711              * cursors to avoid unnecessary database contention and
    712              * temporary memory leaks.
    713              */
    714             public Builder detectLeakedSqlLiteObjects() {
    715                 return enable(DETECT_VM_CURSOR_LEAKS);
    716             }
    717 
    718             /**
    719              * Detect when an {@link java.io.Closeable} or other
    720              * object with a explict termination method is finalized
    721              * without having been closed.
    722              *
    723              * <p>You always want to explicitly close such objects to
    724              * avoid unnecessary resources leaks.
    725              */
    726             public Builder detectLeakedClosableObjects() {
    727                 return enable(DETECT_VM_CLOSABLE_LEAKS);
    728             }
    729 
    730             /**
    731              * Detect when a {@link BroadcastReceiver} or
    732              * {@link ServiceConnection} is leaked during {@link Context}
    733              * teardown.
    734              */
    735             public Builder detectLeakedRegistrationObjects() {
    736                 return enable(DETECT_VM_REGISTRATION_LEAKS);
    737             }
    738 
    739             /**
    740              * Detect when this application exposes a {@code file://}
    741              * {@link android.net.Uri} to another app.
    742              * <p>
    743              * This exposure is discouraged since the receiving app may not have
    744              * access to the shared path. For example, the receiving app may not
    745              * have requested the
    746              * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime
    747              * permission, or the platform may be sharing the
    748              * {@link android.net.Uri} across user profile boundaries.
    749              * <p>
    750              * Instead, apps should use {@code content://} Uris so the platform
    751              * can extend temporary permission for the receiving app to access
    752              * the resource.
    753              *
    754              * @see android.support.v4.content.FileProvider
    755              * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
    756              */
    757             public Builder detectFileUriExposure() {
    758                 return enable(DETECT_VM_FILE_URI_EXPOSURE);
    759             }
    760 
    761             /**
    762              * Detect any network traffic from the calling app which is not
    763              * wrapped in SSL/TLS. This can help you detect places that your app
    764              * is inadvertently sending cleartext data across the network.
    765              * <p>
    766              * Using {@link #penaltyDeath()} or
    767              * {@link #penaltyDeathOnCleartextNetwork()} will block further
    768              * traffic on that socket to prevent accidental data leakage, in
    769              * addition to crashing your process.
    770              * <p>
    771              * Using {@link #penaltyDropBox()} will log the raw contents of the
    772              * packet that triggered the violation.
    773              * <p>
    774              * This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it
    775              * may be subject to false positives, such as when STARTTLS
    776              * protocols or HTTP proxies are used.
    777              */
    778             public Builder detectCleartextNetwork() {
    779                 return enable(DETECT_VM_CLEARTEXT_NETWORK);
    780             }
    781 
    782             /**
    783              * Crashes the whole process on violation. This penalty runs at the
    784              * end of all enabled penalties so you'll still get your logging or
    785              * other violations before the process dies.
    786              */
    787             public Builder penaltyDeath() {
    788                 return enable(PENALTY_DEATH);
    789             }
    790 
    791             /**
    792              * Crashes the whole process when cleartext network traffic is
    793              * detected.
    794              *
    795              * @see #detectCleartextNetwork()
    796              */
    797             public Builder penaltyDeathOnCleartextNetwork() {
    798                 return enable(PENALTY_DEATH_ON_CLEARTEXT_NETWORK);
    799             }
    800 
    801             /**
    802              * Crashes the whole process when a {@code file://}
    803              * {@link android.net.Uri} is exposed beyond this app.
    804              *
    805              * @see #detectFileUriExposure()
    806              */
    807             public Builder penaltyDeathOnFileUriExposure() {
    808                 return enable(PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
    809             }
    810 
    811             /**
    812              * Log detected violations to the system log.
    813              */
    814             public Builder penaltyLog() {
    815                 return enable(PENALTY_LOG);
    816             }
    817 
    818             /**
    819              * Enable detected violations log a stacktrace and timing data
    820              * to the {@link android.os.DropBoxManager DropBox} on policy
    821              * violation.  Intended mostly for platform integrators doing
    822              * beta user field data collection.
    823              */
    824             public Builder penaltyDropBox() {
    825                 return enable(PENALTY_DROPBOX);
    826             }
    827 
    828             private Builder enable(int bit) {
    829                 mMask |= bit;
    830                 return this;
    831             }
    832 
    833             /**
    834              * Construct the VmPolicy instance.
    835              *
    836              * <p>Note: if no penalties are enabled before calling
    837              * <code>build</code>, {@link #penaltyLog} is implicitly
    838              * set.
    839              */
    840             public VmPolicy build() {
    841                 // If there are detection bits set but no violation bits
    842                 // set, enable simple logging.
    843                 if (mMask != 0 &&
    844                     (mMask & (PENALTY_DEATH | PENALTY_LOG |
    845                               PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) {
    846                     penaltyLog();
    847                 }
    848                 return new VmPolicy(mMask,
    849                         mClassInstanceLimit != null ? mClassInstanceLimit : EMPTY_CLASS_LIMIT_MAP);
    850             }
    851         }
    852     }
    853 
    854     /**
    855      * Log of strict mode violation stack traces that have occurred
    856      * during a Binder call, to be serialized back later to the caller
    857      * via Parcel.writeNoException() (amusingly) where the caller can
    858      * choose how to react.
    859      */
    860     private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations =
    861             new ThreadLocal<ArrayList<ViolationInfo>>() {
    862         @Override protected ArrayList<ViolationInfo> initialValue() {
    863             // Starts null to avoid unnecessary allocations when
    864             // checking whether there are any violations or not in
    865             // hasGatheredViolations() below.
    866             return null;
    867         }
    868     };
    869 
    870     /**
    871      * Sets the policy for what actions on the current thread should
    872      * be detected, as well as the penalty if such actions occur.
    873      *
    874      * <p>Internally this sets a thread-local variable which is
    875      * propagated across cross-process IPC calls, meaning you can
    876      * catch violations when a system service or another process
    877      * accesses the disk or network on your behalf.
    878      *
    879      * @param policy the policy to put into place
    880      */
    881     public static void setThreadPolicy(final ThreadPolicy policy) {
    882         setThreadPolicyMask(policy.mask);
    883     }
    884 
    885     private static void setThreadPolicyMask(final int policyMask) {
    886         // In addition to the Java-level thread-local in Dalvik's
    887         // BlockGuard, we also need to keep a native thread-local in
    888         // Binder in order to propagate the value across Binder calls,
    889         // even across native-only processes.  The two are kept in
    890         // sync via the callback to onStrictModePolicyChange, below.
    891         setBlockGuardPolicy(policyMask);
    892 
    893         // And set the Android native version...
    894         Binder.setThreadStrictModePolicy(policyMask);
    895     }
    896 
    897     // Sets the policy in Dalvik/libcore (BlockGuard)
    898     private static void setBlockGuardPolicy(final int policyMask) {
    899         if (policyMask == 0) {
    900             BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
    901             return;
    902         }
    903         final BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
    904         final AndroidBlockGuardPolicy androidPolicy;
    905         if (policy instanceof AndroidBlockGuardPolicy) {
    906             androidPolicy = (AndroidBlockGuardPolicy) policy;
    907         } else {
    908             androidPolicy = threadAndroidPolicy.get();
    909             BlockGuard.setThreadPolicy(androidPolicy);
    910         }
    911         androidPolicy.setPolicyMask(policyMask);
    912     }
    913 
    914     // Sets up CloseGuard in Dalvik/libcore
    915     private static void setCloseGuardEnabled(boolean enabled) {
    916         if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
    917             CloseGuard.setReporter(new AndroidCloseGuardReporter());
    918         }
    919         CloseGuard.setEnabled(enabled);
    920     }
    921 
    922     /**
    923      * @hide
    924      */
    925     public static class StrictModeViolation extends BlockGuard.BlockGuardPolicyException {
    926         public StrictModeViolation(int policyState, int policyViolated, String message) {
    927             super(policyState, policyViolated, message);
    928         }
    929     }
    930 
    931     /**
    932      * @hide
    933      */
    934     public static class StrictModeNetworkViolation extends StrictModeViolation {
    935         public StrictModeNetworkViolation(int policyMask) {
    936             super(policyMask, DETECT_NETWORK, null);
    937         }
    938     }
    939 
    940     /**
    941      * @hide
    942      */
    943     private static class StrictModeDiskReadViolation extends StrictModeViolation {
    944         public StrictModeDiskReadViolation(int policyMask) {
    945             super(policyMask, DETECT_DISK_READ, null);
    946         }
    947     }
    948 
    949      /**
    950      * @hide
    951      */
    952    private static class StrictModeDiskWriteViolation extends StrictModeViolation {
    953         public StrictModeDiskWriteViolation(int policyMask) {
    954             super(policyMask, DETECT_DISK_WRITE, null);
    955         }
    956     }
    957 
    958     /**
    959      * @hide
    960      */
    961     private static class StrictModeCustomViolation extends StrictModeViolation {
    962         public StrictModeCustomViolation(int policyMask, String name) {
    963             super(policyMask, DETECT_CUSTOM, name);
    964         }
    965     }
    966 
    967     /**
    968      * @hide
    969      */
    970     private static class StrictModeResourceMismatchViolation extends StrictModeViolation {
    971         public StrictModeResourceMismatchViolation(int policyMask, Object tag) {
    972             super(policyMask, DETECT_RESOURCE_MISMATCH, tag != null ? tag.toString() : null);
    973         }
    974     }
    975 
    976     /**
    977      * Returns the bitmask of the current thread's policy.
    978      *
    979      * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
    980      *
    981      * @hide
    982      */
    983     public static int getThreadPolicyMask() {
    984         return BlockGuard.getThreadPolicy().getPolicyMask();
    985     }
    986 
    987     /**
    988      * Returns the current thread's policy.
    989      */
    990     public static ThreadPolicy getThreadPolicy() {
    991         // TODO: this was a last minute Gingerbread API change (to
    992         // introduce VmPolicy cleanly) but this isn't particularly
    993         // optimal for users who might call this method often.  This
    994         // should be in a thread-local and not allocate on each call.
    995         return new ThreadPolicy(getThreadPolicyMask());
    996     }
    997 
    998     /**
    999      * A convenience wrapper that takes the current
   1000      * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
   1001      * to permit both disk reads &amp; writes, and sets the new policy
   1002      * with {@link #setThreadPolicy}, returning the old policy so you
   1003      * can restore it at the end of a block.
   1004      *
   1005      * @return the old policy, to be passed to {@link #setThreadPolicy} to
   1006      *         restore the policy at the end of a block
   1007      */
   1008     public static ThreadPolicy allowThreadDiskWrites() {
   1009         int oldPolicyMask = getThreadPolicyMask();
   1010         int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
   1011         if (newPolicyMask != oldPolicyMask) {
   1012             setThreadPolicyMask(newPolicyMask);
   1013         }
   1014         return new ThreadPolicy(oldPolicyMask);
   1015     }
   1016 
   1017     /**
   1018      * A convenience wrapper that takes the current
   1019      * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it
   1020      * to permit disk reads, and sets the new policy
   1021      * with {@link #setThreadPolicy}, returning the old policy so you
   1022      * can restore it at the end of a block.
   1023      *
   1024      * @return the old policy, to be passed to setThreadPolicy to
   1025      *         restore the policy.
   1026      */
   1027     public static ThreadPolicy allowThreadDiskReads() {
   1028         int oldPolicyMask = getThreadPolicyMask();
   1029         int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
   1030         if (newPolicyMask != oldPolicyMask) {
   1031             setThreadPolicyMask(newPolicyMask);
   1032         }
   1033         return new ThreadPolicy(oldPolicyMask);
   1034     }
   1035 
   1036     // We don't want to flash the screen red in the system server
   1037     // process, nor do we want to modify all the call sites of
   1038     // conditionallyEnableDebugLogging() in the system server,
   1039     // so instead we use this to determine if we are the system server.
   1040     private static boolean amTheSystemServerProcess() {
   1041         // Fast path.  Most apps don't have the system server's UID.
   1042         if (Process.myUid() != Process.SYSTEM_UID) {
   1043             return false;
   1044         }
   1045 
   1046         // The settings app, though, has the system server's UID so
   1047         // look up our stack to see if we came from the system server.
   1048         Throwable stack = new Throwable();
   1049         stack.fillInStackTrace();
   1050         for (StackTraceElement ste : stack.getStackTrace()) {
   1051             String clsName = ste.getClassName();
   1052             if (clsName != null && clsName.startsWith("com.android.server.")) {
   1053                 return true;
   1054             }
   1055         }
   1056         return false;
   1057     }
   1058 
   1059     /**
   1060      * Enable DropBox logging for debug phone builds.
   1061      *
   1062      * @hide
   1063      */
   1064     public static boolean conditionallyEnableDebugLogging() {
   1065         boolean doFlashes = SystemProperties.getBoolean(VISUAL_PROPERTY, false)
   1066                 && !amTheSystemServerProcess();
   1067         final boolean suppress = SystemProperties.getBoolean(DISABLE_PROPERTY, false);
   1068 
   1069         // For debug builds, log event loop stalls to dropbox for analysis.
   1070         // Similar logic also appears in ActivityThread.java for system apps.
   1071         if (!doFlashes && (IS_USER_BUILD || suppress)) {
   1072             setCloseGuardEnabled(false);
   1073             return false;
   1074         }
   1075 
   1076         // Eng builds have flashes on all the time.  The suppression property
   1077         // overrides this, so we force the behavior only after the short-circuit
   1078         // check above.
   1079         if (IS_ENG_BUILD) {
   1080             doFlashes = true;
   1081         }
   1082 
   1083         // Thread policy controls BlockGuard.
   1084         int threadPolicyMask = StrictMode.DETECT_DISK_WRITE |
   1085                 StrictMode.DETECT_DISK_READ |
   1086                 StrictMode.DETECT_NETWORK;
   1087 
   1088         if (!IS_USER_BUILD) {
   1089             threadPolicyMask |= StrictMode.PENALTY_DROPBOX;
   1090         }
   1091         if (doFlashes) {
   1092             threadPolicyMask |= StrictMode.PENALTY_FLASH;
   1093         }
   1094 
   1095         StrictMode.setThreadPolicyMask(threadPolicyMask);
   1096 
   1097         // VM Policy controls CloseGuard, detection of Activity leaks,
   1098         // and instance counting.
   1099         if (IS_USER_BUILD) {
   1100             setCloseGuardEnabled(false);
   1101         } else {
   1102             VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll().penaltyDropBox();
   1103             if (IS_ENG_BUILD) {
   1104                 policyBuilder.penaltyLog();
   1105             }
   1106             setVmPolicy(policyBuilder.build());
   1107             setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
   1108         }
   1109         return true;
   1110     }
   1111 
   1112     /**
   1113      * Used by the framework to make network usage on the main
   1114      * thread a fatal error.
   1115      *
   1116      * @hide
   1117      */
   1118     public static void enableDeathOnNetwork() {
   1119         int oldPolicy = getThreadPolicyMask();
   1120         int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
   1121         setThreadPolicyMask(newPolicy);
   1122     }
   1123 
   1124     /**
   1125      * Used by the framework to make file usage a fatal error.
   1126      *
   1127      * @hide
   1128      */
   1129     public static void enableDeathOnFileUriExposure() {
   1130         sVmPolicyMask |= DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
   1131     }
   1132 
   1133     /**
   1134      * Used by lame internal apps that haven't done the hard work to get
   1135      * themselves off file:// Uris yet.
   1136      *
   1137      * @hide
   1138      */
   1139     public static void disableDeathOnFileUriExposure() {
   1140         sVmPolicyMask &= ~(DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
   1141     }
   1142 
   1143     /**
   1144      * Parses the BlockGuard policy mask out from the Exception's
   1145      * getMessage() String value.  Kinda gross, but least
   1146      * invasive.  :/
   1147      *
   1148      * Input is of the following forms:
   1149      *     "policy=137 violation=64"
   1150      *     "policy=137 violation=64 msg=Arbitrary text"
   1151      *
   1152      * Returns 0 on failure, which is a valid policy, but not a
   1153      * valid policy during a violation (else there must've been
   1154      * some policy in effect to violate).
   1155      */
   1156     private static int parsePolicyFromMessage(String message) {
   1157         if (message == null || !message.startsWith("policy=")) {
   1158             return 0;
   1159         }
   1160         int spaceIndex = message.indexOf(' ');
   1161         if (spaceIndex == -1) {
   1162             return 0;
   1163         }
   1164         String policyString = message.substring(7, spaceIndex);
   1165         try {
   1166             return Integer.parseInt(policyString);
   1167         } catch (NumberFormatException e) {
   1168             return 0;
   1169         }
   1170     }
   1171 
   1172     /**
   1173      * Like parsePolicyFromMessage(), but returns the violation.
   1174      */
   1175     private static int parseViolationFromMessage(String message) {
   1176         if (message == null) {
   1177             return 0;
   1178         }
   1179         int violationIndex = message.indexOf("violation=");
   1180         if (violationIndex == -1) {
   1181             return 0;
   1182         }
   1183         int numberStartIndex = violationIndex + "violation=".length();
   1184         int numberEndIndex = message.indexOf(' ', numberStartIndex);
   1185         if (numberEndIndex == -1) {
   1186             numberEndIndex = message.length();
   1187         }
   1188         String violationString = message.substring(numberStartIndex, numberEndIndex);
   1189         try {
   1190             return Integer.parseInt(violationString);
   1191         } catch (NumberFormatException e) {
   1192             return 0;
   1193         }
   1194     }
   1195 
   1196     private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
   1197             new ThreadLocal<ArrayList<ViolationInfo>>() {
   1198         @Override protected ArrayList<ViolationInfo> initialValue() {
   1199             return new ArrayList<ViolationInfo>();
   1200         }
   1201     };
   1202 
   1203     // Note: only access this once verifying the thread has a Looper.
   1204     private static final ThreadLocal<Handler> threadHandler = new ThreadLocal<Handler>() {
   1205         @Override protected Handler initialValue() {
   1206             return new Handler();
   1207         }
   1208     };
   1209 
   1210     private static final ThreadLocal<AndroidBlockGuardPolicy>
   1211             threadAndroidPolicy = new ThreadLocal<AndroidBlockGuardPolicy>() {
   1212         @Override
   1213         protected AndroidBlockGuardPolicy initialValue() {
   1214             return new AndroidBlockGuardPolicy(0);
   1215         }
   1216     };
   1217 
   1218     private static boolean tooManyViolationsThisLoop() {
   1219         return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
   1220     }
   1221 
   1222     private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
   1223         private int mPolicyMask;
   1224 
   1225         // Map from violation stacktrace hashcode -> uptimeMillis of
   1226         // last violation.  No locking needed, as this is only
   1227         // accessed by the same thread.
   1228         private ArrayMap<Integer, Long> mLastViolationTime;
   1229 
   1230         public AndroidBlockGuardPolicy(final int policyMask) {
   1231             mPolicyMask = policyMask;
   1232         }
   1233 
   1234         @Override
   1235         public String toString() {
   1236             return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
   1237         }
   1238 
   1239         // Part of BlockGuard.Policy interface:
   1240         public int getPolicyMask() {
   1241             return mPolicyMask;
   1242         }
   1243 
   1244         // Part of BlockGuard.Policy interface:
   1245         public void onWriteToDisk() {
   1246             if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
   1247                 return;
   1248             }
   1249             if (tooManyViolationsThisLoop()) {
   1250                 return;
   1251             }
   1252             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
   1253             e.fillInStackTrace();
   1254             startHandlingViolationException(e);
   1255         }
   1256 
   1257         // Not part of BlockGuard.Policy; just part of StrictMode:
   1258         void onCustomSlowCall(String name) {
   1259             if ((mPolicyMask & DETECT_CUSTOM) == 0) {
   1260                 return;
   1261             }
   1262             if (tooManyViolationsThisLoop()) {
   1263                 return;
   1264             }
   1265             BlockGuard.BlockGuardPolicyException e = new StrictModeCustomViolation(mPolicyMask, name);
   1266             e.fillInStackTrace();
   1267             startHandlingViolationException(e);
   1268         }
   1269 
   1270         // Not part of BlockGuard.Policy; just part of StrictMode:
   1271         void onResourceMismatch(Object tag) {
   1272             if ((mPolicyMask & DETECT_RESOURCE_MISMATCH) == 0) {
   1273                 return;
   1274             }
   1275             if (tooManyViolationsThisLoop()) {
   1276                 return;
   1277             }
   1278             BlockGuard.BlockGuardPolicyException e =
   1279                     new StrictModeResourceMismatchViolation(mPolicyMask, tag);
   1280             e.fillInStackTrace();
   1281             startHandlingViolationException(e);
   1282         }
   1283 
   1284         // Part of BlockGuard.Policy interface:
   1285         public void onReadFromDisk() {
   1286             if ((mPolicyMask & DETECT_DISK_READ) == 0) {
   1287                 return;
   1288             }
   1289             if (tooManyViolationsThisLoop()) {
   1290                 return;
   1291             }
   1292             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
   1293             e.fillInStackTrace();
   1294             startHandlingViolationException(e);
   1295         }
   1296 
   1297         // Part of BlockGuard.Policy interface:
   1298         public void onNetwork() {
   1299             if ((mPolicyMask & DETECT_NETWORK) == 0) {
   1300                 return;
   1301             }
   1302             if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
   1303                 throw new NetworkOnMainThreadException();
   1304             }
   1305             if (tooManyViolationsThisLoop()) {
   1306                 return;
   1307             }
   1308             BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
   1309             e.fillInStackTrace();
   1310             startHandlingViolationException(e);
   1311         }
   1312 
   1313         public void setPolicyMask(int policyMask) {
   1314             mPolicyMask = policyMask;
   1315         }
   1316 
   1317         // Start handling a violation that just started and hasn't
   1318         // actually run yet (e.g. no disk write or network operation
   1319         // has yet occurred).  This sees if we're in an event loop
   1320         // thread and, if so, uses it to roughly measure how long the
   1321         // violation took.
   1322         void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) {
   1323             final ViolationInfo info = new ViolationInfo(e, e.getPolicy());
   1324             info.violationUptimeMillis = SystemClock.uptimeMillis();
   1325             handleViolationWithTimingAttempt(info);
   1326         }
   1327 
   1328         // Attempts to fill in the provided ViolationInfo's
   1329         // durationMillis field if this thread has a Looper we can use
   1330         // to measure with.  We measure from the time of violation
   1331         // until the time the looper is idle again (right before
   1332         // the next epoll_wait)
   1333         void handleViolationWithTimingAttempt(final ViolationInfo info) {
   1334             Looper looper = Looper.myLooper();
   1335 
   1336             // Without a Looper, we're unable to time how long the
   1337             // violation takes place.  This case should be rare, as
   1338             // most users will care about timing violations that
   1339             // happen on their main UI thread.  Note that this case is
   1340             // also hit when a violation takes place in a Binder
   1341             // thread, in "gather" mode.  In this case, the duration
   1342             // of the violation is computed by the ultimate caller and
   1343             // its Looper, if any.
   1344             //
   1345             // Also, as a special short-cut case when the only penalty
   1346             // bit is death, we die immediately, rather than timing
   1347             // the violation's duration.  This makes it convenient to
   1348             // use in unit tests too, rather than waiting on a Looper.
   1349             //
   1350             // TODO: if in gather mode, ignore Looper.myLooper() and always
   1351             //       go into this immediate mode?
   1352             if (looper == null ||
   1353                 (info.policy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
   1354                 info.durationMillis = -1;  // unknown (redundant, already set)
   1355                 handleViolation(info);
   1356                 return;
   1357             }
   1358 
   1359             final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
   1360             if (records.size() >= MAX_OFFENSES_PER_LOOP) {
   1361                 // Not worth measuring.  Too many offenses in one loop.
   1362                 return;
   1363             }
   1364             records.add(info);
   1365             if (records.size() > 1) {
   1366                 // There's already been a violation this loop, so we've already
   1367                 // registered an idle handler to process the list of violations
   1368                 // at the end of this Looper's loop.
   1369                 return;
   1370             }
   1371 
   1372             final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ?
   1373                     sWindowManager.get() : null;
   1374             if (windowManager != null) {
   1375                 try {
   1376                     windowManager.showStrictModeViolation(true);
   1377                 } catch (RemoteException unused) {
   1378                 }
   1379             }
   1380 
   1381             // We post a runnable to a Handler (== delay 0 ms) for
   1382             // measuring the end time of a violation instead of using
   1383             // an IdleHandler (as was previously used) because an
   1384             // IdleHandler may not run for quite a long period of time
   1385             // if an ongoing animation is happening and continually
   1386             // posting ASAP (0 ms) animation steps.  Animations are
   1387             // throttled back to 60fps via SurfaceFlinger/View
   1388             // invalidates, _not_ by posting frame updates every 16
   1389             // milliseconds.
   1390             threadHandler.get().postAtFrontOfQueue(new Runnable() {
   1391                     public void run() {
   1392                         long loopFinishTime = SystemClock.uptimeMillis();
   1393 
   1394                         // Note: we do this early, before handling the
   1395                         // violation below, as handling the violation
   1396                         // may include PENALTY_DEATH and we don't want
   1397                         // to keep the red border on.
   1398                         if (windowManager != null) {
   1399                             try {
   1400                                 windowManager.showStrictModeViolation(false);
   1401                             } catch (RemoteException unused) {
   1402                             }
   1403                         }
   1404 
   1405                         for (int n = 0; n < records.size(); ++n) {
   1406                             ViolationInfo v = records.get(n);
   1407                             v.violationNumThisLoop = n + 1;
   1408                             v.durationMillis =
   1409                                     (int) (loopFinishTime - v.violationUptimeMillis);
   1410                             handleViolation(v);
   1411                         }
   1412                         records.clear();
   1413                     }
   1414                 });
   1415         }
   1416 
   1417         // Note: It's possible (even quite likely) that the
   1418         // thread-local policy mask has changed from the time the
   1419         // violation fired and now (after the violating code ran) due
   1420         // to people who push/pop temporary policy in regions of code,
   1421         // hence the policy being passed around.
   1422         void handleViolation(final ViolationInfo info) {
   1423             if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) {
   1424                 Log.wtf(TAG, "unexpected null stacktrace");
   1425                 return;
   1426             }
   1427 
   1428             if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy);
   1429 
   1430             if ((info.policy & PENALTY_GATHER) != 0) {
   1431                 ArrayList<ViolationInfo> violations = gatheredViolations.get();
   1432                 if (violations == null) {
   1433                     violations = new ArrayList<ViolationInfo>(1);
   1434                     gatheredViolations.set(violations);
   1435                 } else if (violations.size() >= 5) {
   1436                     // Too many.  In a loop or something?  Don't gather them all.
   1437                     return;
   1438                 }
   1439                 for (ViolationInfo previous : violations) {
   1440                     if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
   1441                         // Duplicate. Don't log.
   1442                         return;
   1443                     }
   1444                 }
   1445                 violations.add(info);
   1446                 return;
   1447             }
   1448 
   1449             // Not perfect, but fast and good enough for dup suppression.
   1450             Integer crashFingerprint = info.hashCode();
   1451             long lastViolationTime = 0;
   1452             if (mLastViolationTime != null) {
   1453                 Long vtime = mLastViolationTime.get(crashFingerprint);
   1454                 if (vtime != null) {
   1455                     lastViolationTime = vtime;
   1456                 }
   1457             } else {
   1458                 mLastViolationTime = new ArrayMap<Integer, Long>(1);
   1459             }
   1460             long now = SystemClock.uptimeMillis();
   1461             mLastViolationTime.put(crashFingerprint, now);
   1462             long timeSinceLastViolationMillis = lastViolationTime == 0 ?
   1463                     Long.MAX_VALUE : (now - lastViolationTime);
   1464 
   1465             if ((info.policy & PENALTY_LOG) != 0 &&
   1466                 timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
   1467                 if (info.durationMillis != -1) {
   1468                     Log.d(TAG, "StrictMode policy violation; ~duration=" +
   1469                           info.durationMillis + " ms: " + info.crashInfo.stackTrace);
   1470                 } else {
   1471                     Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
   1472                 }
   1473             }
   1474 
   1475             // The violationMaskSubset, passed to ActivityManager, is a
   1476             // subset of the original StrictMode policy bitmask, with
   1477             // only the bit violated and penalty bits to be executed
   1478             // by the ActivityManagerService remaining set.
   1479             int violationMaskSubset = 0;
   1480 
   1481             if ((info.policy & PENALTY_DIALOG) != 0 &&
   1482                 timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
   1483                 violationMaskSubset |= PENALTY_DIALOG;
   1484             }
   1485 
   1486             if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
   1487                 violationMaskSubset |= PENALTY_DROPBOX;
   1488             }
   1489 
   1490             if (violationMaskSubset != 0) {
   1491                 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
   1492                 violationMaskSubset |= violationBit;
   1493                 final int savedPolicyMask = getThreadPolicyMask();
   1494 
   1495                 final boolean justDropBox = (info.policy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
   1496                 if (justDropBox) {
   1497                     // If all we're going to ask the activity manager
   1498                     // to do is dropbox it (the common case during
   1499                     // platform development), we can avoid doing this
   1500                     // call synchronously which Binder data suggests
   1501                     // isn't always super fast, despite the implementation
   1502                     // in the ActivityManager trying to be mostly async.
   1503                     dropboxViolationAsync(violationMaskSubset, info);
   1504                     return;
   1505                 }
   1506 
   1507                 // Normal synchronous call to the ActivityManager.
   1508                 try {
   1509                     // First, remove any policy before we call into the Activity Manager,
   1510                     // otherwise we'll infinite recurse as we try to log policy violations
   1511                     // to disk, thus violating policy, thus requiring logging, etc...
   1512                     // We restore the current policy below, in the finally block.
   1513                     setThreadPolicyMask(0);
   1514 
   1515                     ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
   1516                         RuntimeInit.getApplicationObject(),
   1517                         violationMaskSubset,
   1518                         info);
   1519                 } catch (RemoteException e) {
   1520                     if (e instanceof DeadObjectException) {
   1521                         // System process is dead; ignore
   1522                     } else {
   1523                         Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
   1524                     }
   1525                 } finally {
   1526                     // Restore the policy.
   1527                     setThreadPolicyMask(savedPolicyMask);
   1528                 }
   1529             }
   1530 
   1531             if ((info.policy & PENALTY_DEATH) != 0) {
   1532                 executeDeathPenalty(info);
   1533             }
   1534         }
   1535     }
   1536 
   1537     private static void executeDeathPenalty(ViolationInfo info) {
   1538         int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
   1539         throw new StrictModeViolation(info.policy, violationBit, null);
   1540     }
   1541 
   1542     /**
   1543      * In the common case, as set by conditionallyEnableDebugLogging,
   1544      * we're just dropboxing any violations but not showing a dialog,
   1545      * not loggging, and not killing the process.  In these cases we
   1546      * don't need to do a synchronous call to the ActivityManager.
   1547      * This is used by both per-thread and vm-wide violations when
   1548      * applicable.
   1549      */
   1550     private static void dropboxViolationAsync(
   1551             final int violationMaskSubset, final ViolationInfo info) {
   1552         int outstanding = sDropboxCallsInFlight.incrementAndGet();
   1553         if (outstanding > 20) {
   1554             // What's going on?  Let's not make make the situation
   1555             // worse and just not log.
   1556             sDropboxCallsInFlight.decrementAndGet();
   1557             return;
   1558         }
   1559 
   1560         if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
   1561 
   1562         new Thread("callActivityManagerForStrictModeDropbox") {
   1563             public void run() {
   1564                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
   1565                 try {
   1566                     IActivityManager am = ActivityManagerNative.getDefault();
   1567                     if (am == null) {
   1568                         Log.d(TAG, "No activity manager; failed to Dropbox violation.");
   1569                     } else {
   1570                         am.handleApplicationStrictModeViolation(
   1571                             RuntimeInit.getApplicationObject(),
   1572                             violationMaskSubset,
   1573                             info);
   1574                     }
   1575                 } catch (RemoteException e) {
   1576                     if (e instanceof DeadObjectException) {
   1577                         // System process is dead; ignore
   1578                     } else {
   1579                         Log.e(TAG, "RemoteException handling StrictMode violation", e);
   1580                     }
   1581                 }
   1582                 int outstanding = sDropboxCallsInFlight.decrementAndGet();
   1583                 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
   1584             }
   1585         }.start();
   1586     }
   1587 
   1588     private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
   1589         public void report(String message, Throwable allocationSite) {
   1590             onVmPolicyViolation(message, allocationSite);
   1591         }
   1592     }
   1593 
   1594     /**
   1595      * Called from Parcel.writeNoException()
   1596      */
   1597     /* package */ static boolean hasGatheredViolations() {
   1598         return gatheredViolations.get() != null;
   1599     }
   1600 
   1601     /**
   1602      * Called from Parcel.writeException(), so we drop this memory and
   1603      * don't incorrectly attribute it to the wrong caller on the next
   1604      * Binder call on this thread.
   1605      */
   1606     /* package */ static void clearGatheredViolations() {
   1607         gatheredViolations.set(null);
   1608     }
   1609 
   1610     /**
   1611      * @hide
   1612      */
   1613     public static void conditionallyCheckInstanceCounts() {
   1614         VmPolicy policy = getVmPolicy();
   1615         int policySize = policy.classInstanceLimit.size();
   1616         if (policySize == 0) {
   1617             return;
   1618         }
   1619 
   1620         System.gc();
   1621         System.runFinalization();
   1622         System.gc();
   1623 
   1624         // Note: classInstanceLimit is immutable, so this is lock-free
   1625         // Create the classes array.
   1626         Class[] classes = policy.classInstanceLimit.keySet().toArray(new Class[policySize]);
   1627         long[] instanceCounts = VMDebug.countInstancesOfClasses(classes, false);
   1628         for (int i = 0; i < classes.length; ++i) {
   1629             Class klass = classes[i];
   1630             int limit = policy.classInstanceLimit.get(klass);
   1631             long instances = instanceCounts[i];
   1632             if (instances > limit) {
   1633                 Throwable tr = new InstanceCountViolation(klass, instances, limit);
   1634                 onVmPolicyViolation(tr.getMessage(), tr);
   1635             }
   1636         }
   1637     }
   1638 
   1639     private static long sLastInstanceCountCheckMillis = 0;
   1640     private static boolean sIsIdlerRegistered = false;  // guarded by StrictMode.class
   1641     private static final MessageQueue.IdleHandler sProcessIdleHandler =
   1642             new MessageQueue.IdleHandler() {
   1643                 public boolean queueIdle() {
   1644                     long now = SystemClock.uptimeMillis();
   1645                     if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
   1646                         sLastInstanceCountCheckMillis = now;
   1647                         conditionallyCheckInstanceCounts();
   1648                     }
   1649                     return true;
   1650                 }
   1651             };
   1652 
   1653     /**
   1654      * Sets the policy for what actions in the VM process (on any
   1655      * thread) should be detected, as well as the penalty if such
   1656      * actions occur.
   1657      *
   1658      * @param policy the policy to put into place
   1659      */
   1660     public static void setVmPolicy(final VmPolicy policy) {
   1661         synchronized (StrictMode.class) {
   1662             sVmPolicy = policy;
   1663             sVmPolicyMask = policy.mask;
   1664             setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
   1665 
   1666             Looper looper = Looper.getMainLooper();
   1667             if (looper != null) {
   1668                 MessageQueue mq = looper.mQueue;
   1669                 if (policy.classInstanceLimit.size() == 0 ||
   1670                     (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
   1671                     mq.removeIdleHandler(sProcessIdleHandler);
   1672                     sIsIdlerRegistered = false;
   1673                 } else if (!sIsIdlerRegistered) {
   1674                     mq.addIdleHandler(sProcessIdleHandler);
   1675                     sIsIdlerRegistered = true;
   1676                 }
   1677             }
   1678 
   1679             int networkPolicy = NETWORK_POLICY_ACCEPT;
   1680             if ((sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
   1681                 if ((sVmPolicyMask & PENALTY_DEATH) != 0
   1682                         || (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
   1683                     networkPolicy = NETWORK_POLICY_REJECT;
   1684                 } else {
   1685                     networkPolicy = NETWORK_POLICY_LOG;
   1686                 }
   1687             }
   1688 
   1689             final INetworkManagementService netd = INetworkManagementService.Stub.asInterface(
   1690                     ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
   1691             if (netd != null) {
   1692                 try {
   1693                     netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
   1694                 } catch (RemoteException ignored) {
   1695                 }
   1696             } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
   1697                 Log.w(TAG, "Dropping requested network policy due to missing service!");
   1698             }
   1699         }
   1700     }
   1701 
   1702     /**
   1703      * Gets the current VM policy.
   1704      */
   1705     public static VmPolicy getVmPolicy() {
   1706         synchronized (StrictMode.class) {
   1707             return sVmPolicy;
   1708         }
   1709     }
   1710 
   1711     /**
   1712      * Enable the recommended StrictMode defaults, with violations just being logged.
   1713      *
   1714      * <p>This catches disk and network access on the main thread, as
   1715      * well as leaked SQLite cursors and unclosed resources.  This is
   1716      * simply a wrapper around {@link #setVmPolicy} and {@link
   1717      * #setThreadPolicy}.
   1718      */
   1719     public static void enableDefaults() {
   1720         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
   1721                                    .detectAll()
   1722                                    .penaltyLog()
   1723                                    .build());
   1724         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
   1725                                .detectAll()
   1726                                .penaltyLog()
   1727                                .build());
   1728     }
   1729 
   1730     /**
   1731      * @hide
   1732      */
   1733     public static boolean vmSqliteObjectLeaksEnabled() {
   1734         return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
   1735     }
   1736 
   1737     /**
   1738      * @hide
   1739      */
   1740     public static boolean vmClosableObjectLeaksEnabled() {
   1741         return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
   1742     }
   1743 
   1744     /**
   1745      * @hide
   1746      */
   1747     public static boolean vmRegistrationLeaksEnabled() {
   1748         return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
   1749     }
   1750 
   1751     /**
   1752      * @hide
   1753      */
   1754     public static boolean vmFileUriExposureEnabled() {
   1755         return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
   1756     }
   1757 
   1758     /**
   1759      * @hide
   1760      */
   1761     public static boolean vmCleartextNetworkEnabled() {
   1762         return (sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
   1763     }
   1764 
   1765     /**
   1766      * @hide
   1767      */
   1768     public static void onSqliteObjectLeaked(String message, Throwable originStack) {
   1769         onVmPolicyViolation(message, originStack);
   1770     }
   1771 
   1772     /**
   1773      * @hide
   1774      */
   1775     public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
   1776         onVmPolicyViolation(null, originStack);
   1777     }
   1778 
   1779     /**
   1780      * @hide
   1781      */
   1782     public static void onIntentReceiverLeaked(Throwable originStack) {
   1783         onVmPolicyViolation(null, originStack);
   1784     }
   1785 
   1786     /**
   1787      * @hide
   1788      */
   1789     public static void onServiceConnectionLeaked(Throwable originStack) {
   1790         onVmPolicyViolation(null, originStack);
   1791     }
   1792 
   1793     /**
   1794      * @hide
   1795      */
   1796     public static void onFileUriExposed(Uri uri, String location) {
   1797         final String message = uri + " exposed beyond app through " + location;
   1798         if ((sVmPolicyMask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
   1799             throw new FileUriExposedException(message);
   1800         } else {
   1801             onVmPolicyViolation(null, new Throwable(message));
   1802         }
   1803     }
   1804 
   1805     /**
   1806      * @hide
   1807      */
   1808     public static void onCleartextNetworkDetected(byte[] firstPacket) {
   1809         byte[] rawAddr = null;
   1810         if (firstPacket != null) {
   1811             if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
   1812                 // IPv4
   1813                 rawAddr = new byte[4];
   1814                 System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
   1815             } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
   1816                 // IPv6
   1817                 rawAddr = new byte[16];
   1818                 System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
   1819             }
   1820         }
   1821 
   1822         final int uid = android.os.Process.myUid();
   1823         String msg = "Detected cleartext network traffic from UID " + uid;
   1824         if (rawAddr != null) {
   1825             try {
   1826                 msg = "Detected cleartext network traffic from UID " + uid + " to "
   1827                         + InetAddress.getByAddress(rawAddr);
   1828             } catch (UnknownHostException ignored) {
   1829             }
   1830         }
   1831 
   1832         final boolean forceDeath = (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
   1833         onVmPolicyViolation(HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg),
   1834                 forceDeath);
   1835     }
   1836 
   1837     // Map from VM violation fingerprint to uptime millis.
   1838     private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
   1839 
   1840     /**
   1841      * @hide
   1842      */
   1843     public static void onVmPolicyViolation(String message, Throwable originStack) {
   1844         onVmPolicyViolation(message, originStack, false);
   1845     }
   1846 
   1847     /**
   1848      * @hide
   1849      */
   1850     public static void onVmPolicyViolation(String message, Throwable originStack,
   1851             boolean forceDeath) {
   1852         final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
   1853         final boolean penaltyDeath = ((sVmPolicyMask & PENALTY_DEATH) != 0) || forceDeath;
   1854         final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
   1855         final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicyMask);
   1856 
   1857         // Erase stuff not relevant for process-wide violations
   1858         info.numAnimationsRunning = 0;
   1859         info.tags = null;
   1860         info.broadcastIntentAction = null;
   1861 
   1862         final Integer fingerprint = info.hashCode();
   1863         final long now = SystemClock.uptimeMillis();
   1864         long lastViolationTime = 0;
   1865         long timeSinceLastViolationMillis = Long.MAX_VALUE;
   1866         synchronized (sLastVmViolationTime) {
   1867             if (sLastVmViolationTime.containsKey(fingerprint)) {
   1868                 lastViolationTime = sLastVmViolationTime.get(fingerprint);
   1869                 timeSinceLastViolationMillis = now - lastViolationTime;
   1870             }
   1871             if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
   1872                 sLastVmViolationTime.put(fingerprint, now);
   1873             }
   1874         }
   1875 
   1876         if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
   1877             Log.e(TAG, message, originStack);
   1878         }
   1879 
   1880         int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
   1881 
   1882         if (penaltyDropbox && !penaltyDeath) {
   1883             // Common case for userdebug/eng builds.  If no death and
   1884             // just dropboxing, we can do the ActivityManager call
   1885             // asynchronously.
   1886             dropboxViolationAsync(violationMaskSubset, info);
   1887             return;
   1888         }
   1889 
   1890         if (penaltyDropbox && lastViolationTime == 0) {
   1891             // The violationMask, passed to ActivityManager, is a
   1892             // subset of the original StrictMode policy bitmask, with
   1893             // only the bit violated and penalty bits to be executed
   1894             // by the ActivityManagerService remaining set.
   1895             final int savedPolicyMask = getThreadPolicyMask();
   1896             try {
   1897                 // First, remove any policy before we call into the Activity Manager,
   1898                 // otherwise we'll infinite recurse as we try to log policy violations
   1899                 // to disk, thus violating policy, thus requiring logging, etc...
   1900                 // We restore the current policy below, in the finally block.
   1901                 setThreadPolicyMask(0);
   1902 
   1903                 ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
   1904                     RuntimeInit.getApplicationObject(),
   1905                     violationMaskSubset,
   1906                     info);
   1907             } catch (RemoteException e) {
   1908                 if (e instanceof DeadObjectException) {
   1909                     // System process is dead; ignore
   1910                 } else {
   1911                     Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
   1912                 }
   1913             } finally {
   1914                 // Restore the policy.
   1915                 setThreadPolicyMask(savedPolicyMask);
   1916             }
   1917         }
   1918 
   1919         if (penaltyDeath) {
   1920             System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
   1921             Process.killProcess(Process.myPid());
   1922             System.exit(10);
   1923         }
   1924     }
   1925 
   1926     /**
   1927      * Called from Parcel.writeNoException()
   1928      */
   1929     /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
   1930         ArrayList<ViolationInfo> violations = gatheredViolations.get();
   1931         if (violations == null) {
   1932             p.writeInt(0);
   1933         } else {
   1934             p.writeInt(violations.size());
   1935             for (int i = 0; i < violations.size(); ++i) {
   1936                 int start = p.dataPosition();
   1937                 violations.get(i).writeToParcel(p, 0 /* unused flags? */);
   1938                 int size = p.dataPosition()-start;
   1939                 if (size > 10*1024) {
   1940                     Slog.d(TAG, "Wrote violation #" + i + " of " + violations.size() + ": "
   1941                             + (p.dataPosition()-start) + " bytes");
   1942                 }
   1943             }
   1944             if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
   1945             violations.clear(); // somewhat redundant, as we're about to null the threadlocal
   1946         }
   1947         gatheredViolations.set(null);
   1948     }
   1949 
   1950     private static class LogStackTrace extends Exception {}
   1951 
   1952     /**
   1953      * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
   1954      * we here read back all the encoded violations.
   1955      */
   1956     /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
   1957         // Our own stack trace to append
   1958         StringWriter sw = new StringWriter();
   1959         PrintWriter pw = new FastPrintWriter(sw, false, 256);
   1960         new LogStackTrace().printStackTrace(pw);
   1961         pw.flush();
   1962         String ourStack = sw.toString();
   1963 
   1964         int policyMask = getThreadPolicyMask();
   1965         boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
   1966 
   1967         int numViolations = p.readInt();
   1968         for (int i = 0; i < numViolations; ++i) {
   1969             if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call.  i=" + i);
   1970             ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
   1971             if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 30000) {
   1972                 String front = info.crashInfo.stackTrace.substring(0, 256);
   1973                 // 30000 characters is way too large for this to be any sane kind of
   1974                 // strict mode collection of stacks.  We've had a problem where we leave
   1975                 // strict mode violations associated with the thread, and it keeps tacking
   1976                 // more and more stacks on to the violations.  Looks like we're in this casse,
   1977                 // so we'll report it and bail on all of the current strict mode violations
   1978                 // we currently are maintaining for this thread.
   1979                 // First, drain the remaining violations from the parcel.
   1980                 i++;  // Skip the current entry.
   1981                 for (; i < numViolations; i++) {
   1982                     info = new ViolationInfo(p, !currentlyGathering);
   1983                 }
   1984                 // Next clear out all gathered violations.
   1985                 clearGatheredViolations();
   1986                 // Now report the problem.
   1987                 Slog.wtfStack(TAG, "Stack is too large: numViolations=" + numViolations
   1988                         + " policy=#" + Integer.toHexString(policyMask)
   1989                         + " front=" + front);
   1990                 return;
   1991             }
   1992             info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
   1993             BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   1994             if (policy instanceof AndroidBlockGuardPolicy) {
   1995                 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
   1996             }
   1997         }
   1998     }
   1999 
   2000     /**
   2001      * Called from android_util_Binder.cpp's
   2002      * android_os_Parcel_enforceInterface when an incoming Binder call
   2003      * requires changing the StrictMode policy mask.  The role of this
   2004      * function is to ask Binder for its current (native) thread-local
   2005      * policy value and synchronize it to libcore's (Java)
   2006      * thread-local policy value.
   2007      */
   2008     private static void onBinderStrictModePolicyChange(int newPolicy) {
   2009         setBlockGuardPolicy(newPolicy);
   2010     }
   2011 
   2012     /**
   2013      * A tracked, critical time span.  (e.g. during an animation.)
   2014      *
   2015      * The object itself is a linked list node, to avoid any allocations
   2016      * during rapid span entries and exits.
   2017      *
   2018      * @hide
   2019      */
   2020     public static class Span {
   2021         private String mName;
   2022         private long mCreateMillis;
   2023         private Span mNext;
   2024         private Span mPrev;  // not used when in freeList, only active
   2025         private final ThreadSpanState mContainerState;
   2026 
   2027         Span(ThreadSpanState threadState) {
   2028             mContainerState = threadState;
   2029         }
   2030 
   2031         // Empty constructor for the NO_OP_SPAN
   2032         protected Span() {
   2033             mContainerState = null;
   2034         }
   2035 
   2036         /**
   2037          * To be called when the critical span is complete (i.e. the
   2038          * animation is done animating).  This can be called on any
   2039          * thread (even a different one from where the animation was
   2040          * taking place), but that's only a defensive implementation
   2041          * measure.  It really makes no sense for you to call this on
   2042          * thread other than that where you created it.
   2043          *
   2044          * @hide
   2045          */
   2046         public void finish() {
   2047             ThreadSpanState state = mContainerState;
   2048             synchronized (state) {
   2049                 if (mName == null) {
   2050                     // Duplicate finish call.  Ignore.
   2051                     return;
   2052                 }
   2053 
   2054                 // Remove ourselves from the active list.
   2055                 if (mPrev != null) {
   2056                     mPrev.mNext = mNext;
   2057                 }
   2058                 if (mNext != null) {
   2059                     mNext.mPrev = mPrev;
   2060                 }
   2061                 if (state.mActiveHead == this) {
   2062                     state.mActiveHead = mNext;
   2063                 }
   2064 
   2065                 state.mActiveSize--;
   2066 
   2067                 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
   2068 
   2069                 this.mCreateMillis = -1;
   2070                 this.mName = null;
   2071                 this.mPrev = null;
   2072                 this.mNext = null;
   2073 
   2074                 // Add ourselves to the freeList, if it's not already
   2075                 // too big.
   2076                 if (state.mFreeListSize < 5) {
   2077                     this.mNext = state.mFreeListHead;
   2078                     state.mFreeListHead = this;
   2079                     state.mFreeListSize++;
   2080                 }
   2081             }
   2082         }
   2083     }
   2084 
   2085     // The no-op span that's used in user builds.
   2086     private static final Span NO_OP_SPAN = new Span() {
   2087             public void finish() {
   2088                 // Do nothing.
   2089             }
   2090         };
   2091 
   2092     /**
   2093      * Linked lists of active spans and a freelist.
   2094      *
   2095      * Locking notes: there's one of these structures per thread and
   2096      * all members of this structure (as well as the Span nodes under
   2097      * it) are guarded by the ThreadSpanState object instance.  While
   2098      * in theory there'd be no locking required because it's all local
   2099      * per-thread, the finish() method above is defensive against
   2100      * people calling it on a different thread from where they created
   2101      * the Span, hence the locking.
   2102      */
   2103     private static class ThreadSpanState {
   2104         public Span mActiveHead;    // doubly-linked list.
   2105         public int mActiveSize;
   2106         public Span mFreeListHead;  // singly-linked list.  only changes at head.
   2107         public int mFreeListSize;
   2108     }
   2109 
   2110     private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
   2111             new ThreadLocal<ThreadSpanState>() {
   2112         @Override protected ThreadSpanState initialValue() {
   2113             return new ThreadSpanState();
   2114         }
   2115     };
   2116 
   2117     private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
   2118         protected IWindowManager create() {
   2119             return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
   2120         }
   2121     };
   2122 
   2123     /**
   2124      * Enter a named critical span (e.g. an animation)
   2125      *
   2126      * <p>The name is an arbitary label (or tag) that will be applied
   2127      * to any strictmode violation that happens while this span is
   2128      * active.  You must call finish() on the span when done.
   2129      *
   2130      * <p>This will never return null, but on devices without debugging
   2131      * enabled, this may return a dummy object on which the finish()
   2132      * method is a no-op.
   2133      *
   2134      * <p>TODO: add CloseGuard to this, verifying callers call finish.
   2135      *
   2136      * @hide
   2137      */
   2138     public static Span enterCriticalSpan(String name) {
   2139         if (IS_USER_BUILD) {
   2140             return NO_OP_SPAN;
   2141         }
   2142         if (name == null || name.isEmpty()) {
   2143             throw new IllegalArgumentException("name must be non-null and non-empty");
   2144         }
   2145         ThreadSpanState state = sThisThreadSpanState.get();
   2146         Span span = null;
   2147         synchronized (state) {
   2148             if (state.mFreeListHead != null) {
   2149                 span = state.mFreeListHead;
   2150                 state.mFreeListHead = span.mNext;
   2151                 state.mFreeListSize--;
   2152             } else {
   2153                 // Shouldn't have to do this often.
   2154                 span = new Span(state);
   2155             }
   2156             span.mName = name;
   2157             span.mCreateMillis = SystemClock.uptimeMillis();
   2158             span.mNext = state.mActiveHead;
   2159             span.mPrev = null;
   2160             state.mActiveHead = span;
   2161             state.mActiveSize++;
   2162             if (span.mNext != null) {
   2163                 span.mNext.mPrev = span;
   2164             }
   2165             if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
   2166         }
   2167         return span;
   2168     }
   2169 
   2170     /**
   2171      * For code to note that it's slow.  This is a no-op unless the
   2172      * current thread's {@link android.os.StrictMode.ThreadPolicy} has
   2173      * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls}
   2174      * enabled.
   2175      *
   2176      * @param name a short string for the exception stack trace that's
   2177      *             built if when this fires.
   2178      */
   2179     public static void noteSlowCall(String name) {
   2180         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2181         if (!(policy instanceof AndroidBlockGuardPolicy)) {
   2182             // StrictMode not enabled.
   2183             return;
   2184         }
   2185         ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
   2186     }
   2187 
   2188     /**
   2189      * For code to note that a resource was obtained using a type other than
   2190      * its defined type. This is a no-op unless the current thread's
   2191      * {@link android.os.StrictMode.ThreadPolicy} has
   2192      * {@link android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()}
   2193      * enabled.
   2194      *
   2195      * @param tag an object for the exception stack trace that's
   2196      *            built if when this fires.
   2197      * @hide
   2198      */
   2199     public static void noteResourceMismatch(Object tag) {
   2200         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2201         if (!(policy instanceof AndroidBlockGuardPolicy)) {
   2202             // StrictMode not enabled.
   2203             return;
   2204         }
   2205         ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag);
   2206     }
   2207 
   2208     /**
   2209      * @hide
   2210      */
   2211     public static void noteDiskRead() {
   2212         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2213         if (!(policy instanceof AndroidBlockGuardPolicy)) {
   2214             // StrictMode not enabled.
   2215             return;
   2216         }
   2217         ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
   2218     }
   2219 
   2220     /**
   2221      * @hide
   2222      */
   2223     public static void noteDiskWrite() {
   2224         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2225         if (!(policy instanceof AndroidBlockGuardPolicy)) {
   2226             // StrictMode not enabled.
   2227             return;
   2228         }
   2229         ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
   2230     }
   2231 
   2232     // Guarded by StrictMode.class
   2233     private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
   2234             new HashMap<Class, Integer>();
   2235 
   2236     /**
   2237      * Returns an object that is used to track instances of activites.
   2238      * The activity should store a reference to the tracker object in one of its fields.
   2239      * @hide
   2240      */
   2241     public static Object trackActivity(Object instance) {
   2242         return new InstanceTracker(instance);
   2243     }
   2244 
   2245     /**
   2246      * @hide
   2247      */
   2248     public static void incrementExpectedActivityCount(Class klass) {
   2249         if (klass == null) {
   2250             return;
   2251         }
   2252 
   2253         synchronized (StrictMode.class) {
   2254             if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
   2255                 return;
   2256             }
   2257 
   2258             Integer expected = sExpectedActivityInstanceCount.get(klass);
   2259             Integer newExpected = expected == null ? 1 : expected + 1;
   2260             sExpectedActivityInstanceCount.put(klass, newExpected);
   2261         }
   2262     }
   2263 
   2264     /**
   2265      * @hide
   2266      */
   2267     public static void decrementExpectedActivityCount(Class klass) {
   2268         if (klass == null) {
   2269             return;
   2270         }
   2271 
   2272         final int limit;
   2273         synchronized (StrictMode.class) {
   2274             if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
   2275                 return;
   2276             }
   2277 
   2278             Integer expected = sExpectedActivityInstanceCount.get(klass);
   2279             int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
   2280             if (newExpected == 0) {
   2281                 sExpectedActivityInstanceCount.remove(klass);
   2282             } else {
   2283                 sExpectedActivityInstanceCount.put(klass, newExpected);
   2284             }
   2285 
   2286             // Note: adding 1 here to give some breathing room during
   2287             // orientation changes.  (shouldn't be necessary, though?)
   2288             limit = newExpected + 1;
   2289         }
   2290 
   2291         // Quick check.
   2292         int actual = InstanceTracker.getInstanceCount(klass);
   2293         if (actual <= limit) {
   2294             return;
   2295         }
   2296 
   2297         // Do a GC and explicit count to double-check.
   2298         // This is the work that we are trying to avoid by tracking the object instances
   2299         // explicity.  Running an explicit GC can be expensive (80ms) and so can walking
   2300         // the heap to count instance (30ms).  This extra work can make the system feel
   2301         // noticeably less responsive during orientation changes when activities are
   2302         // being restarted.  Granted, it is only a problem when StrictMode is enabled
   2303         // but it is annoying.
   2304 
   2305         System.gc();
   2306         System.runFinalization();
   2307         System.gc();
   2308 
   2309         long instances = VMDebug.countInstancesOfClass(klass, false);
   2310         if (instances > limit) {
   2311             Throwable tr = new InstanceCountViolation(klass, instances, limit);
   2312             onVmPolicyViolation(tr.getMessage(), tr);
   2313         }
   2314     }
   2315 
   2316     /**
   2317      * Parcelable that gets sent in Binder call headers back to callers
   2318      * to report violations that happened during a cross-process call.
   2319      *
   2320      * @hide
   2321      */
   2322     public static class ViolationInfo {
   2323         public String message;
   2324 
   2325         /**
   2326          * Stack and other stuff info.
   2327          */
   2328         public final ApplicationErrorReport.CrashInfo crashInfo;
   2329 
   2330         /**
   2331          * The strict mode policy mask at the time of violation.
   2332          */
   2333         public final int policy;
   2334 
   2335         /**
   2336          * The wall time duration of the violation, when known.  -1 when
   2337          * not known.
   2338          */
   2339         public int durationMillis = -1;
   2340 
   2341         /**
   2342          * The number of animations currently running.
   2343          */
   2344         public int numAnimationsRunning = 0;
   2345 
   2346         /**
   2347          * List of tags from active Span instances during this
   2348          * violation, or null for none.
   2349          */
   2350         public String[] tags;
   2351 
   2352         /**
   2353          * Which violation number this was (1-based) since the last Looper loop,
   2354          * from the perspective of the root caller (if it crossed any processes
   2355          * via Binder calls).  The value is 0 if the root caller wasn't on a Looper
   2356          * thread.
   2357          */
   2358         public int violationNumThisLoop;
   2359 
   2360         /**
   2361          * The time (in terms of SystemClock.uptimeMillis()) that the
   2362          * violation occurred.
   2363          */
   2364         public long violationUptimeMillis;
   2365 
   2366         /**
   2367          * The action of the Intent being broadcast to somebody's onReceive
   2368          * on this thread right now, or null.
   2369          */
   2370         public String broadcastIntentAction;
   2371 
   2372         /**
   2373          * If this is a instance count violation, the number of instances in memory,
   2374          * else -1.
   2375          */
   2376         public long numInstances = -1;
   2377 
   2378         /**
   2379          * Create an uninitialized instance of ViolationInfo
   2380          */
   2381         public ViolationInfo() {
   2382             crashInfo = null;
   2383             policy = 0;
   2384         }
   2385 
   2386         public ViolationInfo(Throwable tr, int policy) {
   2387             this(null, tr, policy);
   2388         }
   2389 
   2390         /**
   2391          * Create an instance of ViolationInfo initialized from an exception.
   2392          */
   2393         public ViolationInfo(String message, Throwable tr, int policy) {
   2394             this.message = message;
   2395             crashInfo = new ApplicationErrorReport.CrashInfo(tr);
   2396             violationUptimeMillis = SystemClock.uptimeMillis();
   2397             this.policy = policy;
   2398             this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
   2399             Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
   2400             if (broadcastIntent != null) {
   2401                 broadcastIntentAction = broadcastIntent.getAction();
   2402             }
   2403             ThreadSpanState state = sThisThreadSpanState.get();
   2404             if (tr instanceof InstanceCountViolation) {
   2405                 this.numInstances = ((InstanceCountViolation) tr).mInstances;
   2406             }
   2407             synchronized (state) {
   2408                 int spanActiveCount = state.mActiveSize;
   2409                 if (spanActiveCount > MAX_SPAN_TAGS) {
   2410                     spanActiveCount = MAX_SPAN_TAGS;
   2411                 }
   2412                 if (spanActiveCount != 0) {
   2413                     this.tags = new String[spanActiveCount];
   2414                     Span iter = state.mActiveHead;
   2415                     int index = 0;
   2416                     while (iter != null && index < spanActiveCount) {
   2417                         this.tags[index] = iter.mName;
   2418                         index++;
   2419                         iter = iter.mNext;
   2420                     }
   2421                 }
   2422             }
   2423         }
   2424 
   2425         @Override
   2426         public int hashCode() {
   2427             int result = 17;
   2428             result = 37 * result + crashInfo.stackTrace.hashCode();
   2429             if (numAnimationsRunning != 0) {
   2430                 result *= 37;
   2431             }
   2432             if (broadcastIntentAction != null) {
   2433                 result = 37 * result + broadcastIntentAction.hashCode();
   2434             }
   2435             if (tags != null) {
   2436                 for (String tag : tags) {
   2437                     result = 37 * result + tag.hashCode();
   2438                 }
   2439             }
   2440             return result;
   2441         }
   2442 
   2443         /**
   2444          * Create an instance of ViolationInfo initialized from a Parcel.
   2445          */
   2446         public ViolationInfo(Parcel in) {
   2447             this(in, false);
   2448         }
   2449 
   2450         /**
   2451          * Create an instance of ViolationInfo initialized from a Parcel.
   2452          *
   2453          * @param unsetGatheringBit if true, the caller is the root caller
   2454          *   and the gathering penalty should be removed.
   2455          */
   2456         public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
   2457             message = in.readString();
   2458             crashInfo = new ApplicationErrorReport.CrashInfo(in);
   2459             int rawPolicy = in.readInt();
   2460             if (unsetGatheringBit) {
   2461                 policy = rawPolicy & ~PENALTY_GATHER;
   2462             } else {
   2463                 policy = rawPolicy;
   2464             }
   2465             durationMillis = in.readInt();
   2466             violationNumThisLoop = in.readInt();
   2467             numAnimationsRunning = in.readInt();
   2468             violationUptimeMillis = in.readLong();
   2469             numInstances = in.readLong();
   2470             broadcastIntentAction = in.readString();
   2471             tags = in.readStringArray();
   2472         }
   2473 
   2474         /**
   2475          * Save a ViolationInfo instance to a parcel.
   2476          */
   2477         public void writeToParcel(Parcel dest, int flags) {
   2478             dest.writeString(message);
   2479             crashInfo.writeToParcel(dest, flags);
   2480             int start = dest.dataPosition();
   2481             dest.writeInt(policy);
   2482             dest.writeInt(durationMillis);
   2483             dest.writeInt(violationNumThisLoop);
   2484             dest.writeInt(numAnimationsRunning);
   2485             dest.writeLong(violationUptimeMillis);
   2486             dest.writeLong(numInstances);
   2487             dest.writeString(broadcastIntentAction);
   2488             dest.writeStringArray(tags);
   2489             int total = dest.dataPosition()-start;
   2490             if (total > 10*1024) {
   2491                 Slog.d(TAG, "VIO: policy=" + policy + " dur=" + durationMillis
   2492                         + " numLoop=" + violationNumThisLoop
   2493                         + " anim=" + numAnimationsRunning
   2494                         + " uptime=" + violationUptimeMillis
   2495                         + " numInst=" + numInstances);
   2496                 Slog.d(TAG, "VIO: action=" + broadcastIntentAction);
   2497                 Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags));
   2498                 Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition()-start));
   2499             }
   2500         }
   2501 
   2502 
   2503         /**
   2504          * Dump a ViolationInfo instance to a Printer.
   2505          */
   2506         public void dump(Printer pw, String prefix) {
   2507             crashInfo.dump(pw, prefix);
   2508             pw.println(prefix + "policy: " + policy);
   2509             if (durationMillis != -1) {
   2510                 pw.println(prefix + "durationMillis: " + durationMillis);
   2511             }
   2512             if (numInstances != -1) {
   2513                 pw.println(prefix + "numInstances: " + numInstances);
   2514             }
   2515             if (violationNumThisLoop != 0) {
   2516                 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
   2517             }
   2518             if (numAnimationsRunning != 0) {
   2519                 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
   2520             }
   2521             pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
   2522             if (broadcastIntentAction != null) {
   2523                 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
   2524             }
   2525             if (tags != null) {
   2526                 int index = 0;
   2527                 for (String tag : tags) {
   2528                     pw.println(prefix + "tag[" + (index++) + "]: " + tag);
   2529                 }
   2530             }
   2531         }
   2532 
   2533     }
   2534 
   2535     // Dummy throwable, for now, since we don't know when or where the
   2536     // leaked instances came from.  We might in the future, but for
   2537     // now we suppress the stack trace because it's useless and/or
   2538     // misleading.
   2539     private static class InstanceCountViolation extends Throwable {
   2540         final Class mClass;
   2541         final long mInstances;
   2542         final int mLimit;
   2543 
   2544         private static final StackTraceElement[] FAKE_STACK = {
   2545             new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
   2546                                   "StrictMode.java", 1)
   2547         };
   2548 
   2549         public InstanceCountViolation(Class klass, long instances, int limit) {
   2550             super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
   2551             setStackTrace(FAKE_STACK);
   2552             mClass = klass;
   2553             mInstances = instances;
   2554             mLimit = limit;
   2555         }
   2556     }
   2557 
   2558     private static final class InstanceTracker {
   2559         private static final HashMap<Class<?>, Integer> sInstanceCounts =
   2560                 new HashMap<Class<?>, Integer>();
   2561 
   2562         private final Class<?> mKlass;
   2563 
   2564         public InstanceTracker(Object instance) {
   2565             mKlass = instance.getClass();
   2566 
   2567             synchronized (sInstanceCounts) {
   2568                 final Integer value = sInstanceCounts.get(mKlass);
   2569                 final int newValue = value != null ? value + 1 : 1;
   2570                 sInstanceCounts.put(mKlass, newValue);
   2571             }
   2572         }
   2573 
   2574         @Override
   2575         protected void finalize() throws Throwable {
   2576             try {
   2577                 synchronized (sInstanceCounts) {
   2578                     final Integer value = sInstanceCounts.get(mKlass);
   2579                     if (value != null) {
   2580                         final int newValue = value - 1;
   2581                         if (newValue > 0) {
   2582                             sInstanceCounts.put(mKlass, newValue);
   2583                         } else {
   2584                             sInstanceCounts.remove(mKlass);
   2585                         }
   2586                     }
   2587                 }
   2588             } finally {
   2589                 super.finalize();
   2590             }
   2591         }
   2592 
   2593         public static int getInstanceCount(Class<?> klass) {
   2594             synchronized (sInstanceCounts) {
   2595                 final Integer value = sInstanceCounts.get(klass);
   2596                 return value != null ? value : 0;
   2597             }
   2598         }
   2599     }
   2600 }
   2601