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