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