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