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