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