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