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