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.annotation.TestApi;
     20 import android.app.ActivityManager;
     21 import android.app.ActivityThread;
     22 import android.app.ApplicationErrorReport;
     23 import android.app.IActivityManager;
     24 import android.content.BroadcastReceiver;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.ServiceConnection;
     28 import android.net.TrafficStats;
     29 import android.net.Uri;
     30 import android.util.ArrayMap;
     31 import android.util.Log;
     32 import android.util.Printer;
     33 import android.util.Singleton;
     34 import android.util.Slog;
     35 import android.view.IWindowManager;
     36 
     37 import com.android.internal.os.RuntimeInit;
     38 import com.android.internal.util.FastPrintWriter;
     39 import com.android.internal.util.HexDump;
     40 
     41 import dalvik.system.BlockGuard;
     42 import dalvik.system.CloseGuard;
     43 import dalvik.system.VMDebug;
     44 import dalvik.system.VMRuntime;
     45 
     46 import java.io.PrintWriter;
     47 import java.io.StringWriter;
     48 import java.net.InetAddress;
     49 import java.net.UnknownHostException;
     50 import java.util.ArrayList;
     51 import java.util.Arrays;
     52 import java.util.HashMap;
     53 import java.util.concurrent.atomic.AtomicInteger;
     54 
     55 /**
     56  * <p>StrictMode is a developer tool which detects things you might be
     57  * doing by accident and brings them to your attention so you can fix
     58  * them.
     59  *
     60  * <p>StrictMode is most commonly used to catch accidental disk or
     61  * network access on the application's main thread, where UI
     62  * operations are received and animations take place.  Keeping disk
     63  * and network operations off the main thread makes for much smoother,
     64  * more responsive applications.  By keeping your application's main thread
     65  * responsive, you also prevent
     66  * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
     67  * from being shown to users.
     68  *
     69  * <p class="note">Note that even though an Android device's disk is
     70  * often on flash memory, many devices run a filesystem on top of that
     71  * memory with very limited concurrency.  It's often the case that
     72  * almost all disk accesses are fast, but may in individual cases be
     73  * dramatically slower when certain I/O is happening in the background
     74  * from other processes.  If possible, it's best to assume that such
     75  * things are not fast.</p>
     76  *
     77  * <p>Example code to enable from early in your
     78  * {@link android.app.Application}, {@link android.app.Activity}, or
     79  * other application component's
     80  * {@link android.app.Application#onCreate} method:
     81  *
     82  * <pre>
     83  * public void onCreate() {
     84  *     if (DEVELOPER_MODE) {
     85  *         StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
     86  *                 .detectDiskReads()
     87  *                 .detectDiskWrites()
     88  *                 .detectNetwork()   // or .detectAll() for all detectable problems
     89  *                 .penaltyLog()
     90  *                 .build());
     91  *         StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
     92  *                 .detectLeakedSqlLiteObjects()
     93  *                 .detectLeakedClosableObjects()
     94  *                 .penaltyLog()
     95  *                 .penaltyDeath()
     96  *                 .build());
     97  *     }
     98  *     super.onCreate();
     99  * }
    100  * </pre>
    101  *
    102  * <p>You can decide what should happen when a violation is detected.
    103  * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can
    104  * watch the output of <code>adb logcat</code> while you use your
    105  * application to see the violations as they happen.
    106  *
    107  * <p>If you find violations that you feel are problematic, there are
    108  * a variety of tools to help solve them: threads, {@link android.os.Handler},
    109  * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
    110  * But don't feel compelled to fix everything that StrictMode finds.  In particular,
    111  * many cases of disk access are often necessary during the normal activity lifecycle.  Use
    112  * StrictMode to find things you did by accident.  Network requests on the UI thread
    113  * are almost always a problem, though.
    114  *
    115  * <p class="note">StrictMode is not a security mechanism and is not
    116  * guaranteed to find all disk or network accesses.  While it does
    117  * propagate its state across process boundaries when doing
    118  * {@link android.os.Binder} calls, it's still ultimately a best
    119  * effort mechanism.  Notably, disk or network access from JNI calls
    120  * won't necessarily trigger it.  Future versions of Android may catch
    121  * more (or fewer) operations, so you should never leave StrictMode
    122  * enabled in applications distributed on Google Play.
    123  */
    124 public final class StrictMode {
    125     private static final String TAG = "StrictMode";
    126     private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE);
    127 
    128     /**
    129      * Boolean system property to disable strict mode checks outright.
    130      * Set this to 'true' to force disable; 'false' has no effect on other
    131      * enable/disable policy.
    132      * @hide
    133      */
    134     public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
    135 
    136     /**
    137      * The boolean system property to control screen flashes on violations.
    138      *
    139      * @hide
    140      */
    141     public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
    142 
    143     /**
    144      * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK}
    145      * in {@link VmPolicy.Builder#detectAll()}. Apps can still always opt-into
    146      * detection using {@link VmPolicy.Builder#detectCleartextNetwork()}.
    147      */
    148     private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.clear";
    149 
    150     // Only log a duplicate stack trace to the logs every second.
    151     private static final long MIN_LOG_INTERVAL_MS = 1000;
    152 
    153     // Only show an annoying dialog at most every 30 seconds
    154     private static final long MIN_DIALOG_INTERVAL_MS = 30000;
    155 
    156     // How many Span tags (e.g. animations) to report.
    157     private static final int MAX_SPAN_TAGS = 20;
    158 
    159     // How many offending stacks to keep track of (and time) per loop
    160     // of the Looper.
    161     private static final int MAX_OFFENSES_PER_LOOP = 10;
    162 
    163     // Byte 1: Thread-policy
    164 
    165     /**
    166      * @hide
    167      */
    168     public static final int DETECT_DISK_WRITE = 0x01;  // for ThreadPolicy
    169 
    170     /**
    171       * @hide
    172      */
    173     public static final int DETECT_DISK_READ = 0x02;  // for ThreadPolicy
    174 
    175     /**
    176      * @hide
    177      */
    178     public static final int DETECT_NETWORK = 0x04;  // for ThreadPolicy
    179 
    180     /**
    181      * For StrictMode.noteSlowCall()
    182      *
    183      * @hide
    184      */
    185     public static final int DETECT_CUSTOM = 0x08;  // for ThreadPolicy
    186 
    187     /**
    188      * For StrictMode.noteResourceMismatch()
    189      *
    190      * @hide
    191      */
    192     public static final int DETECT_RESOURCE_MISMATCH = 0x10;  // for ThreadPolicy
    193 
    194     /**
    195      * @hide
    196      */
    197     public static final int DETECT_UNBUFFERED_IO = 0x20;  // for ThreadPolicy
    198 
    199     private static final int ALL_THREAD_DETECT_BITS =
    200             DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM |
    201             DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO;
    202 
    203     // Byte 2: Process-policy
    204 
    205     /**
    206      * Note, a "VM_" bit, not thread.
    207      * @hide
    208      */
    209     public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8;  // for VmPolicy
    210 
    211     /**
    212      * Note, a "VM_" bit, not thread.
    213      * @hide
    214      */
    215     public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8;  // for VmPolicy
    216 
    217     /**
    218      * Note, a "VM_" bit, not thread.
    219      * @hide
    220      */
    221     public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8;  // for VmPolicy
    222 
    223     /**
    224      * @hide
    225      */
    226     private static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8;  // for VmPolicy
    227 
    228     /**
    229      * @hide
    230      */
    231     public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8;  // for VmPolicy
    232 
    233     /**
    234      * @hide
    235      */
    236     private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8;  // for VmPolicy
    237 
    238     /**
    239      * @hide
    240      */
    241     private static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8;  // for VmPolicy
    242 
    243     /**
    244      * @hide
    245      */
    246     private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8;  // for VmPolicy
    247 
    248     /**
    249      * @hide
    250      */
    251     private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24;  // for VmPolicy
    252 
    253     private static final int ALL_VM_DETECT_BITS =
    254             DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
    255             DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
    256             DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE |
    257             DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION |
    258             DETECT_VM_UNTAGGED_SOCKET;
    259 
    260     // Byte 3: Penalty
    261 
    262     /** {@hide} */
    263     public static final int PENALTY_LOG = 0x01 << 16;  // normal android.util.Log
    264     /** {@hide} */
    265     public static final int PENALTY_DIALOG = 0x02 << 16;
    266     /** {@hide} */
    267     public static final int PENALTY_DEATH = 0x04 << 16;
    268     /** {@hide} */
    269     public static final int PENALTY_FLASH = 0x10 << 16;
    270     /** {@hide} */
    271     public static final int PENALTY_DROPBOX = 0x20 << 16;
    272 
    273     /**
    274      * Non-public penalty mode which overrides all the other penalty
    275      * bits and signals that we're in a Binder call and we should
    276      * ignore the other penalty bits and instead serialize back all
    277      * our offending stack traces to the caller to ultimately handle
    278      * in the originating process.
    279      *
    280      * This must be kept in sync with the constant in libs/binder/Parcel.cpp
    281      *
    282      * @hide
    283      */
    284     public static final int PENALTY_GATHER = 0x40 << 16;
    285 
    286     // Byte 4: Special cases
    287 
    288     /**
    289      * Death when network traffic is detected on main thread.
    290      *
    291      * @hide
    292      */
    293     public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
    294 
    295     /**
    296      * Death when cleartext network traffic is detected.
    297      *
    298      * @hide
    299      */
    300     public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
    301 
    302     /**
    303      * Death when file exposure is detected.
    304      *
    305      * @hide
    306      */
    307     public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
    308 
    309     // CAUTION: we started stealing the top bits of Byte 4 for VM above
    310 
    311     /**
    312      * Mask of all the penalty bits valid for thread policies.
    313      */
    314     private static final int THREAD_PENALTY_MASK =
    315             PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
    316             PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;
    317 
    318     /**
    319      * Mask of all the penalty bits valid for VM policies.
    320      */
    321     private static final int VM_PENALTY_MASK = PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX
    322             | PENALTY_DEATH_ON_CLEARTEXT_NETWORK | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
    323 
    324     /** {@hide} */
    325     public static final int NETWORK_POLICY_ACCEPT = 0;
    326     /** {@hide} */
    327     public static final int NETWORK_POLICY_LOG = 1;
    328     /** {@hide} */
    329     public static final int NETWORK_POLICY_REJECT = 2;
    330 
    331     // TODO: wrap in some ImmutableHashMap thing.
    332     // Note: must be before static initialization of sVmPolicy.
    333     private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP = new HashMap<Class, Integer>();
    334 
    335     /**
    336      * The current VmPolicy in effect.
    337      *
    338      * TODO: these are redundant (mask is in VmPolicy).  Should remove sVmPolicyMask.
    339      */
    340     private static volatile int sVmPolicyMask = 0;
    341     private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
    342 
    343     /** {@hide} */
    344     @TestApi
    345     public interface ViolationListener {
    346         public void onViolation(String message);
    347     }
    348 
    349     private static volatile ViolationListener sListener;
    350 
    351     /** {@hide} */
    352     @TestApi
    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 an explicit 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 && (Build.IS_USER || 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 (Build.IS_ENG) {
   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 (!Build.IS_USER) {
   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 (Build.IS_USER) {
   1220             setCloseGuardEnabled(false);
   1221         } else {
   1222             VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll();
   1223             if (!Build.IS_ENG) {
   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 (Build.IS_ENG) {
   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.enable(DETECT_VM_UNTAGGED_SOCKET);
   1236             } else {
   1237                 policyBuilder.disable(DETECT_VM_UNTAGGED_SOCKET);
   1238             }
   1239             setVmPolicy(policyBuilder.build());
   1240             setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
   1241         }
   1242         return true;
   1243     }
   1244 
   1245     /**
   1246      * Used by the framework to make network usage on the main
   1247      * thread a fatal error.
   1248      *
   1249      * @hide
   1250      */
   1251     public static void enableDeathOnNetwork() {
   1252         int oldPolicy = getThreadPolicyMask();
   1253         int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
   1254         setThreadPolicyMask(newPolicy);
   1255     }
   1256 
   1257     /**
   1258      * Used by the framework to make file usage a fatal error.
   1259      *
   1260      * @hide
   1261      */
   1262     public static void enableDeathOnFileUriExposure() {
   1263         sVmPolicyMask |= DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
   1264     }
   1265 
   1266     /**
   1267      * Used by lame internal apps that haven't done the hard work to get
   1268      * themselves off file:// Uris yet.
   1269      *
   1270      * @hide
   1271      */
   1272     public static void disableDeathOnFileUriExposure() {
   1273         sVmPolicyMask &= ~(DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
   1274     }
   1275 
   1276     /**
   1277      * Parses the BlockGuard policy mask out from the Exception's
   1278      * getMessage() String value.  Kinda gross, but least
   1279      * invasive.  :/
   1280      *
   1281      * Input is of the following forms:
   1282      *     "policy=137 violation=64"
   1283      *     "policy=137 violation=64 msg=Arbitrary text"
   1284      *
   1285      * Returns 0 on failure, which is a valid policy, but not a
   1286      * valid policy during a violation (else there must've been
   1287      * some policy in effect to violate).
   1288      */
   1289     private static int parsePolicyFromMessage(String message) {
   1290         if (message == null || !message.startsWith("policy=")) {
   1291             return 0;
   1292         }
   1293         int spaceIndex = message.indexOf(' ');
   1294         if (spaceIndex == -1) {
   1295             return 0;
   1296         }
   1297         String policyString = message.substring(7, spaceIndex);
   1298         try {
   1299             return Integer.parseInt(policyString);
   1300         } catch (NumberFormatException e) {
   1301             return 0;
   1302         }
   1303     }
   1304 
   1305     /**
   1306      * Like parsePolicyFromMessage(), but returns the violation.
   1307      */
   1308     private static int parseViolationFromMessage(String message) {
   1309         if (message == null) {
   1310             return 0;
   1311         }
   1312         int violationIndex = message.indexOf("violation=");
   1313         if (violationIndex == -1) {
   1314             return 0;
   1315         }
   1316         int numberStartIndex = violationIndex + "violation=".length();
   1317         int numberEndIndex = message.indexOf(' ', numberStartIndex);
   1318         if (numberEndIndex == -1) {
   1319             numberEndIndex = message.length();
   1320         }
   1321         String violationString = message.substring(numberStartIndex, numberEndIndex);
   1322         try {
   1323             return Integer.parseInt(violationString);
   1324         } catch (NumberFormatException e) {
   1325             return 0;
   1326         }
   1327     }
   1328 
   1329     private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
   1330             new ThreadLocal<ArrayList<ViolationInfo>>() {
   1331         @Override protected ArrayList<ViolationInfo> initialValue() {
   1332             return new ArrayList<ViolationInfo>();
   1333         }
   1334     };
   1335 
   1336     // Note: only access this once verifying the thread has a Looper.
   1337     private static final ThreadLocal<Handler> threadHandler = new ThreadLocal<Handler>() {
   1338         @Override protected Handler initialValue() {
   1339             return new Handler();
   1340         }
   1341     };
   1342 
   1343     private static final ThreadLocal<AndroidBlockGuardPolicy>
   1344             threadAndroidPolicy = new ThreadLocal<AndroidBlockGuardPolicy>() {
   1345         @Override
   1346         protected AndroidBlockGuardPolicy initialValue() {
   1347             return new AndroidBlockGuardPolicy(0);
   1348         }
   1349     };
   1350 
   1351     private static boolean tooManyViolationsThisLoop() {
   1352         return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
   1353     }
   1354 
   1355     private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
   1356         private int mPolicyMask;
   1357 
   1358         // Map from violation stacktrace hashcode -> uptimeMillis of
   1359         // last violation.  No locking needed, as this is only
   1360         // accessed by the same thread.
   1361         private ArrayMap<Integer, Long> mLastViolationTime;
   1362 
   1363         public AndroidBlockGuardPolicy(final int policyMask) {
   1364             mPolicyMask = policyMask;
   1365         }
   1366 
   1367         @Override
   1368         public String toString() {
   1369             return "AndroidBlockGuardPolicy; mPolicyMask=" + mPolicyMask;
   1370         }
   1371 
   1372         // Part of BlockGuard.Policy interface:
   1373         public int getPolicyMask() {
   1374             return mPolicyMask;
   1375         }
   1376 
   1377         // Part of BlockGuard.Policy interface:
   1378         public void onWriteToDisk() {
   1379             if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
   1380                 return;
   1381             }
   1382             if (tooManyViolationsThisLoop()) {
   1383                 return;
   1384             }
   1385             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
   1386             e.fillInStackTrace();
   1387             startHandlingViolationException(e);
   1388         }
   1389 
   1390         // Not part of BlockGuard.Policy; just part of StrictMode:
   1391         void onCustomSlowCall(String name) {
   1392             if ((mPolicyMask & DETECT_CUSTOM) == 0) {
   1393                 return;
   1394             }
   1395             if (tooManyViolationsThisLoop()) {
   1396                 return;
   1397             }
   1398             BlockGuard.BlockGuardPolicyException e = new StrictModeCustomViolation(mPolicyMask, name);
   1399             e.fillInStackTrace();
   1400             startHandlingViolationException(e);
   1401         }
   1402 
   1403         // Not part of BlockGuard.Policy; just part of StrictMode:
   1404         void onResourceMismatch(Object tag) {
   1405             if ((mPolicyMask & DETECT_RESOURCE_MISMATCH) == 0) {
   1406                 return;
   1407             }
   1408             if (tooManyViolationsThisLoop()) {
   1409                 return;
   1410             }
   1411             BlockGuard.BlockGuardPolicyException e =
   1412                     new StrictModeResourceMismatchViolation(mPolicyMask, tag);
   1413             e.fillInStackTrace();
   1414             startHandlingViolationException(e);
   1415         }
   1416 
   1417         // Part of BlockGuard.Policy; just part of StrictMode:
   1418         public void onUnbufferedIO() {
   1419             if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
   1420                 return;
   1421             }
   1422             if (tooManyViolationsThisLoop()) {
   1423                 return;
   1424             }
   1425             BlockGuard.BlockGuardPolicyException e =
   1426                     new StrictModeUnbufferedIOViolation(mPolicyMask);
   1427             e.fillInStackTrace();
   1428             startHandlingViolationException(e);
   1429         }
   1430 
   1431         // Part of BlockGuard.Policy interface:
   1432         public void onReadFromDisk() {
   1433             if ((mPolicyMask & DETECT_DISK_READ) == 0) {
   1434                 return;
   1435             }
   1436             if (tooManyViolationsThisLoop()) {
   1437                 return;
   1438             }
   1439             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
   1440             e.fillInStackTrace();
   1441             startHandlingViolationException(e);
   1442         }
   1443 
   1444         // Part of BlockGuard.Policy interface:
   1445         public void onNetwork() {
   1446             if ((mPolicyMask & DETECT_NETWORK) == 0) {
   1447                 return;
   1448             }
   1449             if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
   1450                 throw new NetworkOnMainThreadException();
   1451             }
   1452             if (tooManyViolationsThisLoop()) {
   1453                 return;
   1454             }
   1455             BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
   1456             e.fillInStackTrace();
   1457             startHandlingViolationException(e);
   1458         }
   1459 
   1460         public void setPolicyMask(int policyMask) {
   1461             mPolicyMask = policyMask;
   1462         }
   1463 
   1464         // Start handling a violation that just started and hasn't
   1465         // actually run yet (e.g. no disk write or network operation
   1466         // has yet occurred).  This sees if we're in an event loop
   1467         // thread and, if so, uses it to roughly measure how long the
   1468         // violation took.
   1469         void startHandlingViolationException(BlockGuard.BlockGuardPolicyException e) {
   1470             final ViolationInfo info = new ViolationInfo(e, e.getPolicy());
   1471             info.violationUptimeMillis = SystemClock.uptimeMillis();
   1472             handleViolationWithTimingAttempt(info);
   1473         }
   1474 
   1475         // Attempts to fill in the provided ViolationInfo's
   1476         // durationMillis field if this thread has a Looper we can use
   1477         // to measure with.  We measure from the time of violation
   1478         // until the time the looper is idle again (right before
   1479         // the next epoll_wait)
   1480         void handleViolationWithTimingAttempt(final ViolationInfo info) {
   1481             Looper looper = Looper.myLooper();
   1482 
   1483             // Without a Looper, we're unable to time how long the
   1484             // violation takes place.  This case should be rare, as
   1485             // most users will care about timing violations that
   1486             // happen on their main UI thread.  Note that this case is
   1487             // also hit when a violation takes place in a Binder
   1488             // thread, in "gather" mode.  In this case, the duration
   1489             // of the violation is computed by the ultimate caller and
   1490             // its Looper, if any.
   1491             //
   1492             // Also, as a special short-cut case when the only penalty
   1493             // bit is death, we die immediately, rather than timing
   1494             // the violation's duration.  This makes it convenient to
   1495             // use in unit tests too, rather than waiting on a Looper.
   1496             //
   1497             // TODO: if in gather mode, ignore Looper.myLooper() and always
   1498             //       go into this immediate mode?
   1499             if (looper == null ||
   1500                 (info.policy & THREAD_PENALTY_MASK) == PENALTY_DEATH) {
   1501                 info.durationMillis = -1;  // unknown (redundant, already set)
   1502                 handleViolation(info);
   1503                 return;
   1504             }
   1505 
   1506             final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
   1507             if (records.size() >= MAX_OFFENSES_PER_LOOP) {
   1508                 // Not worth measuring.  Too many offenses in one loop.
   1509                 return;
   1510             }
   1511             records.add(info);
   1512             if (records.size() > 1) {
   1513                 // There's already been a violation this loop, so we've already
   1514                 // registered an idle handler to process the list of violations
   1515                 // at the end of this Looper's loop.
   1516                 return;
   1517             }
   1518 
   1519             final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ?
   1520                     sWindowManager.get() : null;
   1521             if (windowManager != null) {
   1522                 try {
   1523                     windowManager.showStrictModeViolation(true);
   1524                 } catch (RemoteException unused) {
   1525                 }
   1526             }
   1527 
   1528             // We post a runnable to a Handler (== delay 0 ms) for
   1529             // measuring the end time of a violation instead of using
   1530             // an IdleHandler (as was previously used) because an
   1531             // IdleHandler may not run for quite a long period of time
   1532             // if an ongoing animation is happening and continually
   1533             // posting ASAP (0 ms) animation steps.  Animations are
   1534             // throttled back to 60fps via SurfaceFlinger/View
   1535             // invalidates, _not_ by posting frame updates every 16
   1536             // milliseconds.
   1537             threadHandler.get().postAtFrontOfQueue(new Runnable() {
   1538                     public void run() {
   1539                         long loopFinishTime = SystemClock.uptimeMillis();
   1540 
   1541                         // Note: we do this early, before handling the
   1542                         // violation below, as handling the violation
   1543                         // may include PENALTY_DEATH and we don't want
   1544                         // to keep the red border on.
   1545                         if (windowManager != null) {
   1546                             try {
   1547                                 windowManager.showStrictModeViolation(false);
   1548                             } catch (RemoteException unused) {
   1549                             }
   1550                         }
   1551 
   1552                         for (int n = 0; n < records.size(); ++n) {
   1553                             ViolationInfo v = records.get(n);
   1554                             v.violationNumThisLoop = n + 1;
   1555                             v.durationMillis =
   1556                                     (int) (loopFinishTime - v.violationUptimeMillis);
   1557                             handleViolation(v);
   1558                         }
   1559                         records.clear();
   1560                     }
   1561                 });
   1562         }
   1563 
   1564         // Note: It's possible (even quite likely) that the
   1565         // thread-local policy mask has changed from the time the
   1566         // violation fired and now (after the violating code ran) due
   1567         // to people who push/pop temporary policy in regions of code,
   1568         // hence the policy being passed around.
   1569         void handleViolation(final ViolationInfo info) {
   1570             if (info == null || info.crashInfo == null || info.crashInfo.stackTrace == null) {
   1571                 Log.wtf(TAG, "unexpected null stacktrace");
   1572                 return;
   1573             }
   1574 
   1575             if (LOG_V) Log.d(TAG, "handleViolation; policy=" + info.policy);
   1576 
   1577             if ((info.policy & PENALTY_GATHER) != 0) {
   1578                 ArrayList<ViolationInfo> violations = gatheredViolations.get();
   1579                 if (violations == null) {
   1580                     violations = new ArrayList<ViolationInfo>(1);
   1581                     gatheredViolations.set(violations);
   1582                 }
   1583                 for (ViolationInfo previous : violations) {
   1584                     if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
   1585                         // Duplicate. Don't log.
   1586                         return;
   1587                     }
   1588                 }
   1589                 violations.add(info);
   1590                 return;
   1591             }
   1592 
   1593             // Not perfect, but fast and good enough for dup suppression.
   1594             Integer crashFingerprint = info.hashCode();
   1595             long lastViolationTime = 0;
   1596             if (mLastViolationTime != null) {
   1597                 Long vtime = mLastViolationTime.get(crashFingerprint);
   1598                 if (vtime != null) {
   1599                     lastViolationTime = vtime;
   1600                 }
   1601             } else {
   1602                 mLastViolationTime = new ArrayMap<Integer, Long>(1);
   1603             }
   1604             long now = SystemClock.uptimeMillis();
   1605             mLastViolationTime.put(crashFingerprint, now);
   1606             long timeSinceLastViolationMillis = lastViolationTime == 0 ?
   1607                     Long.MAX_VALUE : (now - lastViolationTime);
   1608 
   1609             if ((info.policy & PENALTY_LOG) != 0 && sListener != null) {
   1610                 sListener.onViolation(info.crashInfo.stackTrace);
   1611             }
   1612             if ((info.policy & PENALTY_LOG) != 0 &&
   1613                 timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
   1614                 if (info.durationMillis != -1) {
   1615                     Log.d(TAG, "StrictMode policy violation; ~duration=" +
   1616                           info.durationMillis + " ms: " + info.crashInfo.stackTrace);
   1617                 } else {
   1618                     Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace);
   1619                 }
   1620             }
   1621 
   1622             // The violationMaskSubset, passed to ActivityManager, is a
   1623             // subset of the original StrictMode policy bitmask, with
   1624             // only the bit violated and penalty bits to be executed
   1625             // by the ActivityManagerService remaining set.
   1626             int violationMaskSubset = 0;
   1627 
   1628             if ((info.policy & PENALTY_DIALOG) != 0 &&
   1629                 timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) {
   1630                 violationMaskSubset |= PENALTY_DIALOG;
   1631             }
   1632 
   1633             if ((info.policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) {
   1634                 violationMaskSubset |= PENALTY_DROPBOX;
   1635             }
   1636 
   1637             if (violationMaskSubset != 0) {
   1638                 int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
   1639                 violationMaskSubset |= violationBit;
   1640                 final int savedPolicyMask = getThreadPolicyMask();
   1641 
   1642                 final boolean justDropBox = (info.policy & THREAD_PENALTY_MASK) == PENALTY_DROPBOX;
   1643                 if (justDropBox) {
   1644                     // If all we're going to ask the activity manager
   1645                     // to do is dropbox it (the common case during
   1646                     // platform development), we can avoid doing this
   1647                     // call synchronously which Binder data suggests
   1648                     // isn't always super fast, despite the implementation
   1649                     // in the ActivityManager trying to be mostly async.
   1650                     dropboxViolationAsync(violationMaskSubset, info);
   1651                     return;
   1652                 }
   1653 
   1654                 // Normal synchronous call to the ActivityManager.
   1655                 try {
   1656                     // First, remove any policy before we call into the Activity Manager,
   1657                     // otherwise we'll infinite recurse as we try to log policy violations
   1658                     // to disk, thus violating policy, thus requiring logging, etc...
   1659                     // We restore the current policy below, in the finally block.
   1660                     setThreadPolicyMask(0);
   1661 
   1662                     ActivityManager.getService().handleApplicationStrictModeViolation(
   1663                         RuntimeInit.getApplicationObject(),
   1664                         violationMaskSubset,
   1665                         info);
   1666                 } catch (RemoteException e) {
   1667                     if (e instanceof DeadObjectException) {
   1668                         // System process is dead; ignore
   1669                     } else {
   1670                         Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
   1671                     }
   1672                 } finally {
   1673                     // Restore the policy.
   1674                     setThreadPolicyMask(savedPolicyMask);
   1675                 }
   1676             }
   1677 
   1678             if ((info.policy & PENALTY_DEATH) != 0) {
   1679                 executeDeathPenalty(info);
   1680             }
   1681         }
   1682     }
   1683 
   1684     private static void executeDeathPenalty(ViolationInfo info) {
   1685         int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
   1686         throw new StrictModeViolation(info.policy, violationBit, null);
   1687     }
   1688 
   1689     /**
   1690      * In the common case, as set by conditionallyEnableDebugLogging,
   1691      * we're just dropboxing any violations but not showing a dialog,
   1692      * not loggging, and not killing the process.  In these cases we
   1693      * don't need to do a synchronous call to the ActivityManager.
   1694      * This is used by both per-thread and vm-wide violations when
   1695      * applicable.
   1696      */
   1697     private static void dropboxViolationAsync(
   1698             final int violationMaskSubset, final ViolationInfo info) {
   1699         int outstanding = sDropboxCallsInFlight.incrementAndGet();
   1700         if (outstanding > 20) {
   1701             // What's going on?  Let's not make make the situation
   1702             // worse and just not log.
   1703             sDropboxCallsInFlight.decrementAndGet();
   1704             return;
   1705         }
   1706 
   1707         if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);
   1708 
   1709         new Thread("callActivityManagerForStrictModeDropbox") {
   1710             public void run() {
   1711                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
   1712                 try {
   1713                     IActivityManager am = ActivityManager.getService();
   1714                     if (am == null) {
   1715                         Log.d(TAG, "No activity manager; failed to Dropbox violation.");
   1716                     } else {
   1717                         am.handleApplicationStrictModeViolation(
   1718                             RuntimeInit.getApplicationObject(),
   1719                             violationMaskSubset,
   1720                             info);
   1721                     }
   1722                 } catch (RemoteException e) {
   1723                     if (e instanceof DeadObjectException) {
   1724                         // System process is dead; ignore
   1725                     } else {
   1726                         Log.e(TAG, "RemoteException handling StrictMode violation", e);
   1727                     }
   1728                 }
   1729                 int outstanding = sDropboxCallsInFlight.decrementAndGet();
   1730                 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
   1731             }
   1732         }.start();
   1733     }
   1734 
   1735     private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
   1736         public void report(String message, Throwable allocationSite) {
   1737             onVmPolicyViolation(message, allocationSite);
   1738         }
   1739     }
   1740 
   1741     /**
   1742      * Called from Parcel.writeNoException()
   1743      */
   1744     /* package */ static boolean hasGatheredViolations() {
   1745         return gatheredViolations.get() != null;
   1746     }
   1747 
   1748     /**
   1749      * Called from Parcel.writeException(), so we drop this memory and
   1750      * don't incorrectly attribute it to the wrong caller on the next
   1751      * Binder call on this thread.
   1752      */
   1753     /* package */ static void clearGatheredViolations() {
   1754         gatheredViolations.set(null);
   1755     }
   1756 
   1757     /**
   1758      * @hide
   1759      */
   1760     public static void conditionallyCheckInstanceCounts() {
   1761         VmPolicy policy = getVmPolicy();
   1762         int policySize = policy.classInstanceLimit.size();
   1763         if (policySize == 0) {
   1764             return;
   1765         }
   1766 
   1767         System.gc();
   1768         System.runFinalization();
   1769         System.gc();
   1770 
   1771         // Note: classInstanceLimit is immutable, so this is lock-free
   1772         // Create the classes array.
   1773         Class[] classes = policy.classInstanceLimit.keySet().toArray(new Class[policySize]);
   1774         long[] instanceCounts = VMDebug.countInstancesOfClasses(classes, false);
   1775         for (int i = 0; i < classes.length; ++i) {
   1776             Class klass = classes[i];
   1777             int limit = policy.classInstanceLimit.get(klass);
   1778             long instances = instanceCounts[i];
   1779             if (instances > limit) {
   1780                 Throwable tr = new InstanceCountViolation(klass, instances, limit);
   1781                 onVmPolicyViolation(tr.getMessage(), tr);
   1782             }
   1783         }
   1784     }
   1785 
   1786     private static long sLastInstanceCountCheckMillis = 0;
   1787     private static boolean sIsIdlerRegistered = false;  // guarded by StrictMode.class
   1788     private static final MessageQueue.IdleHandler sProcessIdleHandler =
   1789             new MessageQueue.IdleHandler() {
   1790                 public boolean queueIdle() {
   1791                     long now = SystemClock.uptimeMillis();
   1792                     if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
   1793                         sLastInstanceCountCheckMillis = now;
   1794                         conditionallyCheckInstanceCounts();
   1795                     }
   1796                     return true;
   1797                 }
   1798             };
   1799 
   1800     /**
   1801      * Sets the policy for what actions in the VM process (on any
   1802      * thread) should be detected, as well as the penalty if such
   1803      * actions occur.
   1804      *
   1805      * @param policy the policy to put into place
   1806      */
   1807     public static void setVmPolicy(final VmPolicy policy) {
   1808         synchronized (StrictMode.class) {
   1809             sVmPolicy = policy;
   1810             sVmPolicyMask = policy.mask;
   1811             setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
   1812 
   1813             Looper looper = Looper.getMainLooper();
   1814             if (looper != null) {
   1815                 MessageQueue mq = looper.mQueue;
   1816                 if (policy.classInstanceLimit.size() == 0 ||
   1817                     (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
   1818                     mq.removeIdleHandler(sProcessIdleHandler);
   1819                     sIsIdlerRegistered = false;
   1820                 } else if (!sIsIdlerRegistered) {
   1821                     mq.addIdleHandler(sProcessIdleHandler);
   1822                     sIsIdlerRegistered = true;
   1823                 }
   1824             }
   1825 
   1826             int networkPolicy = NETWORK_POLICY_ACCEPT;
   1827             if ((sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
   1828                 if ((sVmPolicyMask & PENALTY_DEATH) != 0
   1829                         || (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
   1830                     networkPolicy = NETWORK_POLICY_REJECT;
   1831                 } else {
   1832                     networkPolicy = NETWORK_POLICY_LOG;
   1833                 }
   1834             }
   1835 
   1836             final INetworkManagementService netd = INetworkManagementService.Stub.asInterface(
   1837                     ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
   1838             if (netd != null) {
   1839                 try {
   1840                     netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
   1841                 } catch (RemoteException ignored) {
   1842                 }
   1843             } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
   1844                 Log.w(TAG, "Dropping requested network policy due to missing service!");
   1845             }
   1846         }
   1847     }
   1848 
   1849     /**
   1850      * Gets the current VM policy.
   1851      */
   1852     public static VmPolicy getVmPolicy() {
   1853         synchronized (StrictMode.class) {
   1854             return sVmPolicy;
   1855         }
   1856     }
   1857 
   1858     /**
   1859      * Enable the recommended StrictMode defaults, with violations just being logged.
   1860      *
   1861      * <p>This catches disk and network access on the main thread, as
   1862      * well as leaked SQLite cursors and unclosed resources.  This is
   1863      * simply a wrapper around {@link #setVmPolicy} and {@link
   1864      * #setThreadPolicy}.
   1865      */
   1866     public static void enableDefaults() {
   1867         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
   1868                                    .detectAll()
   1869                                    .penaltyLog()
   1870                                    .build());
   1871         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
   1872                                .detectAll()
   1873                                .penaltyLog()
   1874                                .build());
   1875     }
   1876 
   1877     /**
   1878      * @hide
   1879      */
   1880     public static boolean vmSqliteObjectLeaksEnabled() {
   1881         return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
   1882     }
   1883 
   1884     /**
   1885      * @hide
   1886      */
   1887     public static boolean vmClosableObjectLeaksEnabled() {
   1888         return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
   1889     }
   1890 
   1891     /**
   1892      * @hide
   1893      */
   1894     public static boolean vmRegistrationLeaksEnabled() {
   1895         return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
   1896     }
   1897 
   1898     /**
   1899      * @hide
   1900      */
   1901     public static boolean vmFileUriExposureEnabled() {
   1902         return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
   1903     }
   1904 
   1905     /**
   1906      * @hide
   1907      */
   1908     public static boolean vmCleartextNetworkEnabled() {
   1909         return (sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
   1910     }
   1911 
   1912     /**
   1913      * @hide
   1914      */
   1915     public static boolean vmContentUriWithoutPermissionEnabled() {
   1916         return (sVmPolicyMask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
   1917     }
   1918 
   1919     /**
   1920      * @hide
   1921      */
   1922     public static boolean vmUntaggedSocketEnabled() {
   1923         return (sVmPolicyMask & DETECT_VM_UNTAGGED_SOCKET) != 0;
   1924     }
   1925 
   1926     /**
   1927      * @hide
   1928      */
   1929     public static void onSqliteObjectLeaked(String message, Throwable originStack) {
   1930         onVmPolicyViolation(message, originStack);
   1931     }
   1932 
   1933     /**
   1934      * @hide
   1935      */
   1936     public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
   1937         onVmPolicyViolation(null, originStack);
   1938     }
   1939 
   1940     /**
   1941      * @hide
   1942      */
   1943     public static void onIntentReceiverLeaked(Throwable originStack) {
   1944         onVmPolicyViolation(null, originStack);
   1945     }
   1946 
   1947     /**
   1948      * @hide
   1949      */
   1950     public static void onServiceConnectionLeaked(Throwable originStack) {
   1951         onVmPolicyViolation(null, originStack);
   1952     }
   1953 
   1954     /**
   1955      * @hide
   1956      */
   1957     public static void onFileUriExposed(Uri uri, String location) {
   1958         final String message = uri + " exposed beyond app through " + location;
   1959         if ((sVmPolicyMask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
   1960             throw new FileUriExposedException(message);
   1961         } else {
   1962             onVmPolicyViolation(null, new Throwable(message));
   1963         }
   1964     }
   1965 
   1966     /**
   1967      * @hide
   1968      */
   1969     public static void onContentUriWithoutPermission(Uri uri, String location) {
   1970         final String message = uri + " exposed beyond app through " + location
   1971                 + " without permission grant flags; did you forget"
   1972                 + " FLAG_GRANT_READ_URI_PERMISSION?";
   1973         onVmPolicyViolation(null, new Throwable(message));
   1974     }
   1975 
   1976     /**
   1977      * @hide
   1978      */
   1979     public static void onCleartextNetworkDetected(byte[] firstPacket) {
   1980         byte[] rawAddr = null;
   1981         if (firstPacket != null) {
   1982             if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
   1983                 // IPv4
   1984                 rawAddr = new byte[4];
   1985                 System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
   1986             } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
   1987                 // IPv6
   1988                 rawAddr = new byte[16];
   1989                 System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
   1990             }
   1991         }
   1992 
   1993         final int uid = android.os.Process.myUid();
   1994         String msg = "Detected cleartext network traffic from UID " + uid;
   1995         if (rawAddr != null) {
   1996             try {
   1997                 msg = "Detected cleartext network traffic from UID " + uid + " to "
   1998                         + InetAddress.getByAddress(rawAddr);
   1999             } catch (UnknownHostException ignored) {
   2000             }
   2001         }
   2002 
   2003         final boolean forceDeath = (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
   2004         onVmPolicyViolation(HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg),
   2005                 forceDeath);
   2006     }
   2007 
   2008     /**
   2009      * @hide
   2010      */
   2011     public static void onUntaggedSocket() {
   2012         onVmPolicyViolation(null, new Throwable("Untagged socket detected; use"
   2013                 + " TrafficStats.setThreadSocketTag() to track all network usage"));
   2014     }
   2015 
   2016     // Map from VM violation fingerprint to uptime millis.
   2017     private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
   2018 
   2019     /**
   2020      * @hide
   2021      */
   2022     public static void onVmPolicyViolation(String message, Throwable originStack) {
   2023         onVmPolicyViolation(message, originStack, false);
   2024     }
   2025 
   2026     /**
   2027      * @hide
   2028      */
   2029     public static void onVmPolicyViolation(String message, Throwable originStack,
   2030             boolean forceDeath) {
   2031         final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
   2032         final boolean penaltyDeath = ((sVmPolicyMask & PENALTY_DEATH) != 0) || forceDeath;
   2033         final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
   2034         final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicyMask);
   2035 
   2036         // Erase stuff not relevant for process-wide violations
   2037         info.numAnimationsRunning = 0;
   2038         info.tags = null;
   2039         info.broadcastIntentAction = null;
   2040 
   2041         final Integer fingerprint = info.hashCode();
   2042         final long now = SystemClock.uptimeMillis();
   2043         long lastViolationTime = 0;
   2044         long timeSinceLastViolationMillis = Long.MAX_VALUE;
   2045         synchronized (sLastVmViolationTime) {
   2046             if (sLastVmViolationTime.containsKey(fingerprint)) {
   2047                 lastViolationTime = sLastVmViolationTime.get(fingerprint);
   2048                 timeSinceLastViolationMillis = now - lastViolationTime;
   2049             }
   2050             if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
   2051                 sLastVmViolationTime.put(fingerprint, now);
   2052             }
   2053         }
   2054 
   2055         if (penaltyLog && sListener != null) {
   2056             sListener.onViolation(originStack.toString());
   2057         }
   2058         if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
   2059             Log.e(TAG, message, originStack);
   2060         }
   2061 
   2062         int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
   2063 
   2064         if (penaltyDropbox && !penaltyDeath) {
   2065             // Common case for userdebug/eng builds.  If no death and
   2066             // just dropboxing, we can do the ActivityManager call
   2067             // asynchronously.
   2068             dropboxViolationAsync(violationMaskSubset, info);
   2069             return;
   2070         }
   2071 
   2072         if (penaltyDropbox && lastViolationTime == 0) {
   2073             // The violationMask, passed to ActivityManager, is a
   2074             // subset of the original StrictMode policy bitmask, with
   2075             // only the bit violated and penalty bits to be executed
   2076             // by the ActivityManagerService remaining set.
   2077             final int savedPolicyMask = getThreadPolicyMask();
   2078             try {
   2079                 // First, remove any policy before we call into the Activity Manager,
   2080                 // otherwise we'll infinite recurse as we try to log policy violations
   2081                 // to disk, thus violating policy, thus requiring logging, etc...
   2082                 // We restore the current policy below, in the finally block.
   2083                 setThreadPolicyMask(0);
   2084 
   2085                 ActivityManager.getService().handleApplicationStrictModeViolation(
   2086                     RuntimeInit.getApplicationObject(),
   2087                     violationMaskSubset,
   2088                     info);
   2089             } catch (RemoteException e) {
   2090                 if (e instanceof DeadObjectException) {
   2091                     // System process is dead; ignore
   2092                 } else {
   2093                     Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
   2094                 }
   2095             } finally {
   2096                 // Restore the policy.
   2097                 setThreadPolicyMask(savedPolicyMask);
   2098             }
   2099         }
   2100 
   2101         if (penaltyDeath) {
   2102             System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
   2103             Process.killProcess(Process.myPid());
   2104             System.exit(10);
   2105         }
   2106     }
   2107 
   2108     /**
   2109      * Called from Parcel.writeNoException()
   2110      */
   2111     /* package */ static void writeGatheredViolationsToParcel(Parcel p) {
   2112         ArrayList<ViolationInfo> violations = gatheredViolations.get();
   2113         if (violations == null) {
   2114             p.writeInt(0);
   2115         } else {
   2116             // To avoid taking up too much transaction space, only include
   2117             // details for the first 3 violations. Deep inside, CrashInfo
   2118             // will truncate each stack trace to ~20kB.
   2119             final int size = Math.min(violations.size(), 3);
   2120             p.writeInt(size);
   2121             for (int i = 0; i < size; i++) {
   2122                 violations.get(i).writeToParcel(p, 0);
   2123             }
   2124         }
   2125         gatheredViolations.set(null);
   2126     }
   2127 
   2128     private static class LogStackTrace extends Exception {}
   2129 
   2130     /**
   2131      * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS,
   2132      * we here read back all the encoded violations.
   2133      */
   2134     /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
   2135         // Our own stack trace to append
   2136         StringWriter sw = new StringWriter();
   2137         sw.append("# via Binder call with stack:\n");
   2138         PrintWriter pw = new FastPrintWriter(sw, false, 256);
   2139         new LogStackTrace().printStackTrace(pw);
   2140         pw.flush();
   2141         String ourStack = sw.toString();
   2142 
   2143         final int policyMask = getThreadPolicyMask();
   2144         final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
   2145 
   2146         final int size = p.readInt();
   2147         for (int i = 0; i < size; i++) {
   2148             final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
   2149             info.crashInfo.appendStackTrace(ourStack);
   2150             BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2151             if (policy instanceof AndroidBlockGuardPolicy) {
   2152                 ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
   2153             }
   2154         }
   2155     }
   2156 
   2157     /**
   2158      * Called from android_util_Binder.cpp's
   2159      * android_os_Parcel_enforceInterface when an incoming Binder call
   2160      * requires changing the StrictMode policy mask.  The role of this
   2161      * function is to ask Binder for its current (native) thread-local
   2162      * policy value and synchronize it to libcore's (Java)
   2163      * thread-local policy value.
   2164      */
   2165     private static void onBinderStrictModePolicyChange(int newPolicy) {
   2166         setBlockGuardPolicy(newPolicy);
   2167     }
   2168 
   2169     /**
   2170      * A tracked, critical time span.  (e.g. during an animation.)
   2171      *
   2172      * The object itself is a linked list node, to avoid any allocations
   2173      * during rapid span entries and exits.
   2174      *
   2175      * @hide
   2176      */
   2177     public static class Span {
   2178         private String mName;
   2179         private long mCreateMillis;
   2180         private Span mNext;
   2181         private Span mPrev;  // not used when in freeList, only active
   2182         private final ThreadSpanState mContainerState;
   2183 
   2184         Span(ThreadSpanState threadState) {
   2185             mContainerState = threadState;
   2186         }
   2187 
   2188         // Empty constructor for the NO_OP_SPAN
   2189         protected Span() {
   2190             mContainerState = null;
   2191         }
   2192 
   2193         /**
   2194          * To be called when the critical span is complete (i.e. the
   2195          * animation is done animating).  This can be called on any
   2196          * thread (even a different one from where the animation was
   2197          * taking place), but that's only a defensive implementation
   2198          * measure.  It really makes no sense for you to call this on
   2199          * thread other than that where you created it.
   2200          *
   2201          * @hide
   2202          */
   2203         public void finish() {
   2204             ThreadSpanState state = mContainerState;
   2205             synchronized (state) {
   2206                 if (mName == null) {
   2207                     // Duplicate finish call.  Ignore.
   2208                     return;
   2209                 }
   2210 
   2211                 // Remove ourselves from the active list.
   2212                 if (mPrev != null) {
   2213                     mPrev.mNext = mNext;
   2214                 }
   2215                 if (mNext != null) {
   2216                     mNext.mPrev = mPrev;
   2217                 }
   2218                 if (state.mActiveHead == this) {
   2219                     state.mActiveHead = mNext;
   2220                 }
   2221 
   2222                 state.mActiveSize--;
   2223 
   2224                 if (LOG_V) Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
   2225 
   2226                 this.mCreateMillis = -1;
   2227                 this.mName = null;
   2228                 this.mPrev = null;
   2229                 this.mNext = null;
   2230 
   2231                 // Add ourselves to the freeList, if it's not already
   2232                 // too big.
   2233                 if (state.mFreeListSize < 5) {
   2234                     this.mNext = state.mFreeListHead;
   2235                     state.mFreeListHead = this;
   2236                     state.mFreeListSize++;
   2237                 }
   2238             }
   2239         }
   2240     }
   2241 
   2242     // The no-op span that's used in user builds.
   2243     private static final Span NO_OP_SPAN = new Span() {
   2244             public void finish() {
   2245                 // Do nothing.
   2246             }
   2247         };
   2248 
   2249     /**
   2250      * Linked lists of active spans and a freelist.
   2251      *
   2252      * Locking notes: there's one of these structures per thread and
   2253      * all members of this structure (as well as the Span nodes under
   2254      * it) are guarded by the ThreadSpanState object instance.  While
   2255      * in theory there'd be no locking required because it's all local
   2256      * per-thread, the finish() method above is defensive against
   2257      * people calling it on a different thread from where they created
   2258      * the Span, hence the locking.
   2259      */
   2260     private static class ThreadSpanState {
   2261         public Span mActiveHead;    // doubly-linked list.
   2262         public int mActiveSize;
   2263         public Span mFreeListHead;  // singly-linked list.  only changes at head.
   2264         public int mFreeListSize;
   2265     }
   2266 
   2267     private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
   2268             new ThreadLocal<ThreadSpanState>() {
   2269         @Override protected ThreadSpanState initialValue() {
   2270             return new ThreadSpanState();
   2271         }
   2272     };
   2273 
   2274     private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() {
   2275         protected IWindowManager create() {
   2276             return IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
   2277         }
   2278     };
   2279 
   2280     /**
   2281      * Enter a named critical span (e.g. an animation)
   2282      *
   2283      * <p>The name is an arbitary label (or tag) that will be applied
   2284      * to any strictmode violation that happens while this span is
   2285      * active.  You must call finish() on the span when done.
   2286      *
   2287      * <p>This will never return null, but on devices without debugging
   2288      * enabled, this may return a dummy object on which the finish()
   2289      * method is a no-op.
   2290      *
   2291      * <p>TODO: add CloseGuard to this, verifying callers call finish.
   2292      *
   2293      * @hide
   2294      */
   2295     public static Span enterCriticalSpan(String name) {
   2296         if (Build.IS_USER) {
   2297             return NO_OP_SPAN;
   2298         }
   2299         if (name == null || name.isEmpty()) {
   2300             throw new IllegalArgumentException("name must be non-null and non-empty");
   2301         }
   2302         ThreadSpanState state = sThisThreadSpanState.get();
   2303         Span span = null;
   2304         synchronized (state) {
   2305             if (state.mFreeListHead != null) {
   2306                 span = state.mFreeListHead;
   2307                 state.mFreeListHead = span.mNext;
   2308                 state.mFreeListSize--;
   2309             } else {
   2310                 // Shouldn't have to do this often.
   2311                 span = new Span(state);
   2312             }
   2313             span.mName = name;
   2314             span.mCreateMillis = SystemClock.uptimeMillis();
   2315             span.mNext = state.mActiveHead;
   2316             span.mPrev = null;
   2317             state.mActiveHead = span;
   2318             state.mActiveSize++;
   2319             if (span.mNext != null) {
   2320                 span.mNext.mPrev = span;
   2321             }
   2322             if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
   2323         }
   2324         return span;
   2325     }
   2326 
   2327     /**
   2328      * For code to note that it's slow.  This is a no-op unless the
   2329      * current thread's {@link android.os.StrictMode.ThreadPolicy} has
   2330      * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls}
   2331      * enabled.
   2332      *
   2333      * @param name a short string for the exception stack trace that's
   2334      *             built if when this fires.
   2335      */
   2336     public static void noteSlowCall(String name) {
   2337         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2338         if (!(policy instanceof AndroidBlockGuardPolicy)) {
   2339             // StrictMode not enabled.
   2340             return;
   2341         }
   2342         ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
   2343     }
   2344 
   2345     /**
   2346      * For code to note that a resource was obtained using a type other than
   2347      * its defined type. This is a no-op unless the current thread's
   2348      * {@link android.os.StrictMode.ThreadPolicy} has
   2349      * {@link android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()}
   2350      * enabled.
   2351      *
   2352      * @param tag an object for the exception stack trace that's
   2353      *            built if when this fires.
   2354      * @hide
   2355      */
   2356     public static void noteResourceMismatch(Object tag) {
   2357         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2358         if (!(policy instanceof AndroidBlockGuardPolicy)) {
   2359             // StrictMode not enabled.
   2360             return;
   2361         }
   2362         ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag);
   2363     }
   2364 
   2365     /**
   2366      * @hide
   2367      */
   2368     public static void noteUnbufferedIO() {
   2369         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2370         if (!(policy instanceof AndroidBlockGuardPolicy)) {
   2371             // StrictMode not enabled.
   2372             return;
   2373         }
   2374         ((AndroidBlockGuardPolicy) policy).onUnbufferedIO();
   2375     }
   2376 
   2377     /**
   2378      * @hide
   2379      */
   2380     public static void noteDiskRead() {
   2381         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2382         if (!(policy instanceof AndroidBlockGuardPolicy)) {
   2383             // StrictMode not enabled.
   2384             return;
   2385         }
   2386         ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
   2387     }
   2388 
   2389     /**
   2390      * @hide
   2391      */
   2392     public static void noteDiskWrite() {
   2393         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
   2394         if (!(policy instanceof AndroidBlockGuardPolicy)) {
   2395             // StrictMode not enabled.
   2396             return;
   2397         }
   2398         ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
   2399     }
   2400 
   2401     // Guarded by StrictMode.class
   2402     private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
   2403             new HashMap<Class, Integer>();
   2404 
   2405     /**
   2406      * Returns an object that is used to track instances of activites.
   2407      * The activity should store a reference to the tracker object in one of its fields.
   2408      * @hide
   2409      */
   2410     public static Object trackActivity(Object instance) {
   2411         return new InstanceTracker(instance);
   2412     }
   2413 
   2414     /**
   2415      * @hide
   2416      */
   2417     public static void incrementExpectedActivityCount(Class klass) {
   2418         if (klass == null) {
   2419             return;
   2420         }
   2421 
   2422         synchronized (StrictMode.class) {
   2423             if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
   2424                 return;
   2425             }
   2426 
   2427             Integer expected = sExpectedActivityInstanceCount.get(klass);
   2428             Integer newExpected = expected == null ? 1 : expected + 1;
   2429             sExpectedActivityInstanceCount.put(klass, newExpected);
   2430         }
   2431     }
   2432 
   2433     /**
   2434      * @hide
   2435      */
   2436     public static void decrementExpectedActivityCount(Class klass) {
   2437         if (klass == null) {
   2438             return;
   2439         }
   2440 
   2441         final int limit;
   2442         synchronized (StrictMode.class) {
   2443             if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
   2444                 return;
   2445             }
   2446 
   2447             Integer expected = sExpectedActivityInstanceCount.get(klass);
   2448             int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
   2449             if (newExpected == 0) {
   2450                 sExpectedActivityInstanceCount.remove(klass);
   2451             } else {
   2452                 sExpectedActivityInstanceCount.put(klass, newExpected);
   2453             }
   2454 
   2455             // Note: adding 1 here to give some breathing room during
   2456             // orientation changes.  (shouldn't be necessary, though?)
   2457             limit = newExpected + 1;
   2458         }
   2459 
   2460         // Quick check.
   2461         int actual = InstanceTracker.getInstanceCount(klass);
   2462         if (actual <= limit) {
   2463             return;
   2464         }
   2465 
   2466         // Do a GC and explicit count to double-check.
   2467         // This is the work that we are trying to avoid by tracking the object instances
   2468         // explicity.  Running an explicit GC can be expensive (80ms) and so can walking
   2469         // the heap to count instance (30ms).  This extra work can make the system feel
   2470         // noticeably less responsive during orientation changes when activities are
   2471         // being restarted.  Granted, it is only a problem when StrictMode is enabled
   2472         // but it is annoying.
   2473 
   2474         System.gc();
   2475         System.runFinalization();
   2476         System.gc();
   2477 
   2478         long instances = VMDebug.countInstancesOfClass(klass, false);
   2479         if (instances > limit) {
   2480             Throwable tr = new InstanceCountViolation(klass, instances, limit);
   2481             onVmPolicyViolation(tr.getMessage(), tr);
   2482         }
   2483     }
   2484 
   2485     /**
   2486      * Parcelable that gets sent in Binder call headers back to callers
   2487      * to report violations that happened during a cross-process call.
   2488      *
   2489      * @hide
   2490      */
   2491     public static class ViolationInfo implements Parcelable {
   2492         public final String message;
   2493 
   2494         /**
   2495          * Stack and other stuff info.
   2496          */
   2497         public final ApplicationErrorReport.CrashInfo crashInfo;
   2498 
   2499         /**
   2500          * The strict mode policy mask at the time of violation.
   2501          */
   2502         public final int policy;
   2503 
   2504         /**
   2505          * The wall time duration of the violation, when known.  -1 when
   2506          * not known.
   2507          */
   2508         public int durationMillis = -1;
   2509 
   2510         /**
   2511          * The number of animations currently running.
   2512          */
   2513         public int numAnimationsRunning = 0;
   2514 
   2515         /**
   2516          * List of tags from active Span instances during this
   2517          * violation, or null for none.
   2518          */
   2519         public String[] tags;
   2520 
   2521         /**
   2522          * Which violation number this was (1-based) since the last Looper loop,
   2523          * from the perspective of the root caller (if it crossed any processes
   2524          * via Binder calls).  The value is 0 if the root caller wasn't on a Looper
   2525          * thread.
   2526          */
   2527         public int violationNumThisLoop;
   2528 
   2529         /**
   2530          * The time (in terms of SystemClock.uptimeMillis()) that the
   2531          * violation occurred.
   2532          */
   2533         public long violationUptimeMillis;
   2534 
   2535         /**
   2536          * The action of the Intent being broadcast to somebody's onReceive
   2537          * on this thread right now, or null.
   2538          */
   2539         public String broadcastIntentAction;
   2540 
   2541         /**
   2542          * If this is a instance count violation, the number of instances in memory,
   2543          * else -1.
   2544          */
   2545         public long numInstances = -1;
   2546 
   2547         /**
   2548          * Create an uninitialized instance of ViolationInfo
   2549          */
   2550         public ViolationInfo() {
   2551             message = null;
   2552             crashInfo = null;
   2553             policy = 0;
   2554         }
   2555 
   2556         public ViolationInfo(Throwable tr, int policy) {
   2557             this(null, tr, policy);
   2558         }
   2559 
   2560         /**
   2561          * Create an instance of ViolationInfo initialized from an exception.
   2562          */
   2563         public ViolationInfo(String message, Throwable tr, int policy) {
   2564             this.message = message;
   2565             crashInfo = new ApplicationErrorReport.CrashInfo(tr);
   2566             violationUptimeMillis = SystemClock.uptimeMillis();
   2567             this.policy = policy;
   2568             this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
   2569             Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
   2570             if (broadcastIntent != null) {
   2571                 broadcastIntentAction = broadcastIntent.getAction();
   2572             }
   2573             ThreadSpanState state = sThisThreadSpanState.get();
   2574             if (tr instanceof InstanceCountViolation) {
   2575                 this.numInstances = ((InstanceCountViolation) tr).mInstances;
   2576             }
   2577             synchronized (state) {
   2578                 int spanActiveCount = state.mActiveSize;
   2579                 if (spanActiveCount > MAX_SPAN_TAGS) {
   2580                     spanActiveCount = MAX_SPAN_TAGS;
   2581                 }
   2582                 if (spanActiveCount != 0) {
   2583                     this.tags = new String[spanActiveCount];
   2584                     Span iter = state.mActiveHead;
   2585                     int index = 0;
   2586                     while (iter != null && index < spanActiveCount) {
   2587                         this.tags[index] = iter.mName;
   2588                         index++;
   2589                         iter = iter.mNext;
   2590                     }
   2591                 }
   2592             }
   2593         }
   2594 
   2595         @Override
   2596         public int hashCode() {
   2597             int result = 17;
   2598             if (crashInfo != null) {
   2599                 result = 37 * result + crashInfo.stackTrace.hashCode();
   2600             }
   2601             if (numAnimationsRunning != 0) {
   2602                 result *= 37;
   2603             }
   2604             if (broadcastIntentAction != null) {
   2605                 result = 37 * result + broadcastIntentAction.hashCode();
   2606             }
   2607             if (tags != null) {
   2608                 for (String tag : tags) {
   2609                     result = 37 * result + tag.hashCode();
   2610                 }
   2611             }
   2612             return result;
   2613         }
   2614 
   2615         /**
   2616          * Create an instance of ViolationInfo initialized from a Parcel.
   2617          */
   2618         public ViolationInfo(Parcel in) {
   2619             this(in, false);
   2620         }
   2621 
   2622         /**
   2623          * Create an instance of ViolationInfo initialized from a Parcel.
   2624          *
   2625          * @param unsetGatheringBit if true, the caller is the root caller
   2626          *   and the gathering penalty should be removed.
   2627          */
   2628         public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
   2629             message = in.readString();
   2630             if (in.readInt() != 0) {
   2631                 crashInfo = new ApplicationErrorReport.CrashInfo(in);
   2632             } else {
   2633                 crashInfo = null;
   2634             }
   2635             int rawPolicy = in.readInt();
   2636             if (unsetGatheringBit) {
   2637                 policy = rawPolicy & ~PENALTY_GATHER;
   2638             } else {
   2639                 policy = rawPolicy;
   2640             }
   2641             durationMillis = in.readInt();
   2642             violationNumThisLoop = in.readInt();
   2643             numAnimationsRunning = in.readInt();
   2644             violationUptimeMillis = in.readLong();
   2645             numInstances = in.readLong();
   2646             broadcastIntentAction = in.readString();
   2647             tags = in.readStringArray();
   2648         }
   2649 
   2650         /**
   2651          * Save a ViolationInfo instance to a parcel.
   2652          */
   2653         @Override
   2654         public void writeToParcel(Parcel dest, int flags) {
   2655             dest.writeString(message);
   2656             if (crashInfo != null) {
   2657                 dest.writeInt(1);
   2658                 crashInfo.writeToParcel(dest, flags);
   2659             } else {
   2660                 dest.writeInt(0);
   2661             }
   2662             int start = dest.dataPosition();
   2663             dest.writeInt(policy);
   2664             dest.writeInt(durationMillis);
   2665             dest.writeInt(violationNumThisLoop);
   2666             dest.writeInt(numAnimationsRunning);
   2667             dest.writeLong(violationUptimeMillis);
   2668             dest.writeLong(numInstances);
   2669             dest.writeString(broadcastIntentAction);
   2670             dest.writeStringArray(tags);
   2671             int total = dest.dataPosition()-start;
   2672             if (Binder.CHECK_PARCEL_SIZE && total > 10*1024) {
   2673                 Slog.d(TAG, "VIO: policy=" + policy + " dur=" + durationMillis
   2674                         + " numLoop=" + violationNumThisLoop
   2675                         + " anim=" + numAnimationsRunning
   2676                         + " uptime=" + violationUptimeMillis
   2677                         + " numInst=" + numInstances);
   2678                 Slog.d(TAG, "VIO: action=" + broadcastIntentAction);
   2679                 Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags));
   2680                 Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition()-start));
   2681             }
   2682         }
   2683 
   2684 
   2685         /**
   2686          * Dump a ViolationInfo instance to a Printer.
   2687          */
   2688         public void dump(Printer pw, String prefix) {
   2689             if (crashInfo != null) {
   2690                 crashInfo.dump(pw, prefix);
   2691             }
   2692             pw.println(prefix + "policy: " + policy);
   2693             if (durationMillis != -1) {
   2694                 pw.println(prefix + "durationMillis: " + durationMillis);
   2695             }
   2696             if (numInstances != -1) {
   2697                 pw.println(prefix + "numInstances: " + numInstances);
   2698             }
   2699             if (violationNumThisLoop != 0) {
   2700                 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
   2701             }
   2702             if (numAnimationsRunning != 0) {
   2703                 pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
   2704             }
   2705             pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
   2706             if (broadcastIntentAction != null) {
   2707                 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
   2708             }
   2709             if (tags != null) {
   2710                 int index = 0;
   2711                 for (String tag : tags) {
   2712                     pw.println(prefix + "tag[" + (index++) + "]: " + tag);
   2713                 }
   2714             }
   2715         }
   2716 
   2717         @Override
   2718         public int describeContents() {
   2719             return 0;
   2720         }
   2721 
   2722         public static final Parcelable.Creator<ViolationInfo> CREATOR =
   2723                 new Parcelable.Creator<ViolationInfo>() {
   2724                     @Override
   2725                     public ViolationInfo createFromParcel(Parcel in) {
   2726                         return new ViolationInfo(in);
   2727                     }
   2728 
   2729                     @Override
   2730                     public ViolationInfo[] newArray(int size) {
   2731                         return new ViolationInfo[size];
   2732                     }
   2733                 };
   2734     }
   2735 
   2736     // Dummy throwable, for now, since we don't know when or where the
   2737     // leaked instances came from.  We might in the future, but for
   2738     // now we suppress the stack trace because it's useless and/or
   2739     // misleading.
   2740     private static class InstanceCountViolation extends Throwable {
   2741         final Class mClass;
   2742         final long mInstances;
   2743         final int mLimit;
   2744 
   2745         private static final StackTraceElement[] FAKE_STACK = {
   2746             new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
   2747                                   "StrictMode.java", 1)
   2748         };
   2749 
   2750         public InstanceCountViolation(Class klass, long instances, int limit) {
   2751             super(klass.toString() + "; instances=" + instances + "; limit=" + limit);
   2752             setStackTrace(FAKE_STACK);
   2753             mClass = klass;
   2754             mInstances = instances;
   2755             mLimit = limit;
   2756         }
   2757     }
   2758 
   2759     private static final class InstanceTracker {
   2760         private static final HashMap<Class<?>, Integer> sInstanceCounts =
   2761                 new HashMap<Class<?>, Integer>();
   2762 
   2763         private final Class<?> mKlass;
   2764 
   2765         public InstanceTracker(Object instance) {
   2766             mKlass = instance.getClass();
   2767 
   2768             synchronized (sInstanceCounts) {
   2769                 final Integer value = sInstanceCounts.get(mKlass);
   2770                 final int newValue = value != null ? value + 1 : 1;
   2771                 sInstanceCounts.put(mKlass, newValue);
   2772             }
   2773         }
   2774 
   2775         @Override
   2776         protected void finalize() throws Throwable {
   2777             try {
   2778                 synchronized (sInstanceCounts) {
   2779                     final Integer value = sInstanceCounts.get(mKlass);
   2780                     if (value != null) {
   2781                         final int newValue = value - 1;
   2782                         if (newValue > 0) {
   2783                             sInstanceCounts.put(mKlass, newValue);
   2784                         } else {
   2785                             sInstanceCounts.remove(mKlass);
   2786                         }
   2787                     }
   2788                 }
   2789             } finally {
   2790                 super.finalize();
   2791             }
   2792         }
   2793 
   2794         public static int getInstanceCount(Class<?> klass) {
   2795             synchronized (sInstanceCounts) {
   2796                 final Integer value = sInstanceCounts.get(klass);
   2797                 return value != null ? value : 0;
   2798             }
   2799         }
   2800     }
   2801 }
   2802