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