FileDocCategorySizeDatePackage
StrictMode.javaAPI DocAndroid 5.1 API86628Thu Mar 12 22:22:10 GMT 2015android.os

StrictMode

public final class StrictMode extends Object

StrictMode is a developer tool which detects things you might be doing by accident and brings them to your attention so you can fix them.

StrictMode is most commonly used to catch accidental disk or network access on the application's main thread, where UI operations are received and animations take place. Keeping disk and network operations off the main thread makes for much smoother, more responsive applications. By keeping your application's main thread responsive, you also prevent ANR dialogs from being shown to users.

Note that even though an Android device's disk is often on flash memory, many devices run a filesystem on top of that memory with very limited concurrency. It's often the case that almost all disk accesses are fast, but may in individual cases be dramatically slower when certain I/O is happening in the background from other processes. If possible, it's best to assume that such things are not fast.

Example code to enable from early in your {@link android.app.Application}, {@link android.app.Activity}, or other application component's {@link android.app.Application#onCreate} method:

public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
super.onCreate();
}

You can decide what should happen when a violation is detected. For example, using {@link ThreadPolicy.Builder#penaltyLog} you can watch the output of adb logcat while you use your application to see the violations as they happen.

If you find violations that you feel are problematic, there are a variety of tools to help solve them: threads, {@link android.os.Handler}, {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc. But don't feel compelled to fix everything that StrictMode finds. In particular, many cases of disk access are often necessary during the normal activity lifecycle. Use StrictMode to find things you did by accident. Network requests on the UI thread are almost always a problem, though.

StrictMode is not a security mechanism and is not guaranteed to find all disk or network accesses. While it does propagate its state across process boundaries when doing {@link android.os.Binder} calls, it's still ultimately a best effort mechanism. Notably, disk or network access from JNI calls won't necessarily trigger it. Future versions of Android may catch more (or fewer) operations, so you should never leave StrictMode enabled in applications distributed on Google Play.

Fields Summary
private static final String
TAG
private static final boolean
LOG_V
private static final boolean
IS_USER_BUILD
private static final boolean
IS_ENG_BUILD
public static final String
DISABLE_PROPERTY
Boolean system property to disable strict mode checks outright. Set this to 'true' to force disable; 'false' has no effect on other enable/disable policy.
public static final String
VISUAL_PROPERTY
The boolean system property to control screen flashes on violations.
private static final long
MIN_LOG_INTERVAL_MS
private static final long
MIN_DIALOG_INTERVAL_MS
private static final int
MAX_SPAN_TAGS
private static final int
MAX_OFFENSES_PER_LOOP
public static final int
DETECT_DISK_WRITE
public static final int
DETECT_DISK_READ
public static final int
DETECT_NETWORK
public static final int
DETECT_CUSTOM
For StrictMode.noteSlowCall()
private static final int
ALL_THREAD_DETECT_BITS
public static final int
DETECT_VM_CURSOR_LEAKS
Note, a "VM_" bit, not thread.
public static final int
DETECT_VM_CLOSABLE_LEAKS
Note, a "VM_" bit, not thread.
public static final int
DETECT_VM_ACTIVITY_LEAKS
Note, a "VM_" bit, not thread.
private static final int
DETECT_VM_INSTANCE_LEAKS
public static final int
DETECT_VM_REGISTRATION_LEAKS
private static final int
DETECT_VM_FILE_URI_EXPOSURE
private static final int
ALL_VM_DETECT_BITS
public static final int
PENALTY_LOG
public static final int
PENALTY_DIALOG
public static final int
PENALTY_DEATH
Death on any detected violation.
public static final int
PENALTY_DEATH_ON_NETWORK
Death just for detected network usage.
public static final int
PENALTY_FLASH
Flash the screen during violations.
public static final int
PENALTY_DROPBOX
public static final int
PENALTY_GATHER
Non-public penalty mode which overrides all the other penalty bits and signals that we're in a Binder call and we should ignore the other penalty bits and instead serialize back all our offending stack traces to the caller to ultimately handle in the originating process. This must be kept in sync with the constant in libs/binder/Parcel.cpp
private static final int
THREAD_PENALTY_MASK
Mask of all the penalty bits valid for thread policies.
private static final int
VM_PENALTY_MASK
Mask of all the penalty bits valid for VM policies.
private static final HashMap
EMPTY_CLASS_LIMIT_MAP
private static volatile int
sVmPolicyMask
The current VmPolicy in effect. TODO: these are redundant (mask is in VmPolicy). Should remove sVmPolicyMask.
private static volatile VmPolicy
sVmPolicy
private static final AtomicInteger
sDropboxCallsInFlight
The number of threads trying to do an async dropbox write. Just to limit ourselves out of paranoia.
private static final ThreadLocal
gatheredViolations
Log of strict mode violation stack traces that have occurred during a Binder call, to be serialized back later to the caller via Parcel.writeNoException() (amusingly) where the caller can choose how to react.
private static final ThreadLocal
violationsBeingTimed
private static final ThreadLocal
threadHandler
private static final ThreadLocal
threadAndroidPolicy
private static long
sLastInstanceCountCheckMillis
private static boolean
sIsIdlerRegistered
private static final MessageQueue.IdleHandler
sProcessIdleHandler
private static final HashMap
sLastVmViolationTime
private static final Span
NO_OP_SPAN
private static final ThreadLocal
sThisThreadSpanState
private static android.util.Singleton
sWindowManager
private static final HashMap
sExpectedActivityInstanceCount
Constructors Summary
private StrictMode()


      
Methods Summary
public static android.os.StrictMode$ThreadPolicyallowThreadDiskReads()
A convenience wrapper that takes the current {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it to permit disk reads, and sets the new policy with {@link #setThreadPolicy}, returning the old policy so you can restore it at the end of a block.

return
the old policy, to be passed to setThreadPolicy to restore the policy.

        int oldPolicyMask = getThreadPolicyMask();
        int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
        if (newPolicyMask != oldPolicyMask) {
            setThreadPolicyMask(newPolicyMask);
        }
        return new ThreadPolicy(oldPolicyMask);
    
public static android.os.StrictMode$ThreadPolicyallowThreadDiskWrites()
A convenience wrapper that takes the current {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it to permit both disk reads & writes, and sets the new policy with {@link #setThreadPolicy}, returning the old policy so you can restore it at the end of a block.

return
the old policy, to be passed to {@link #setThreadPolicy} to restore the policy at the end of a block

        int oldPolicyMask = getThreadPolicyMask();
        int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
        if (newPolicyMask != oldPolicyMask) {
            setThreadPolicyMask(newPolicyMask);
        }
        return new ThreadPolicy(oldPolicyMask);
    
private static booleanamTheSystemServerProcess()

        // Fast path.  Most apps don't have the system server's UID.
        if (Process.myUid() != Process.SYSTEM_UID) {
            return false;
        }

        // The settings app, though, has the system server's UID so
        // look up our stack to see if we came from the system server.
        Throwable stack = new Throwable();
        stack.fillInStackTrace();
        for (StackTraceElement ste : stack.getStackTrace()) {
            String clsName = ste.getClassName();
            if (clsName != null && clsName.startsWith("com.android.server.")) {
                return true;
            }
        }
        return false;
    
static voidclearGatheredViolations()
Called from Parcel.writeException(), so we drop this memory and don't incorrectly attribute it to the wrong caller on the next Binder call on this thread.

        gatheredViolations.set(null);
    
public static voidconditionallyCheckInstanceCounts()

hide

        VmPolicy policy = getVmPolicy();
        if (policy.classInstanceLimit.size() == 0) {
            return;
        }

        System.gc();
        System.runFinalization();
        System.gc();

        // Note: classInstanceLimit is immutable, so this is lock-free
        for (Map.Entry<Class, Integer> entry : policy.classInstanceLimit.entrySet()) {
            Class klass = entry.getKey();
            int limit = entry.getValue();
            long instances = VMDebug.countInstancesOfClass(klass, false);
            if (instances <= limit) {
                continue;
            }
            Throwable tr = new InstanceCountViolation(klass, instances, limit);
            onVmPolicyViolation(tr.getMessage(), tr);
        }
    
public static booleanconditionallyEnableDebugLogging()
Enable DropBox logging for debug phone builds.

hide

        boolean doFlashes = SystemProperties.getBoolean(VISUAL_PROPERTY, false)
                && !amTheSystemServerProcess();
        final boolean suppress = SystemProperties.getBoolean(DISABLE_PROPERTY, false);

        // For debug builds, log event loop stalls to dropbox for analysis.
        // Similar logic also appears in ActivityThread.java for system apps.
        if (!doFlashes && (IS_USER_BUILD || suppress)) {
            setCloseGuardEnabled(false);
            return false;
        }

        // Eng builds have flashes on all the time.  The suppression property
        // overrides this, so we force the behavior only after the short-circuit
        // check above.
        if (IS_ENG_BUILD) {
            doFlashes = true;
        }

        // Thread policy controls BlockGuard.
        int threadPolicyMask = StrictMode.DETECT_DISK_WRITE |
                StrictMode.DETECT_DISK_READ |
                StrictMode.DETECT_NETWORK;

        if (!IS_USER_BUILD) {
            threadPolicyMask |= StrictMode.PENALTY_DROPBOX;
        }
        if (doFlashes) {
            threadPolicyMask |= StrictMode.PENALTY_FLASH;
        }

        StrictMode.setThreadPolicyMask(threadPolicyMask);

        // VM Policy controls CloseGuard, detection of Activity leaks,
        // and instance counting.
        if (IS_USER_BUILD) {
            setCloseGuardEnabled(false);
        } else {
            VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll().penaltyDropBox();
            if (IS_ENG_BUILD) {
                policyBuilder.penaltyLog();
            }
            setVmPolicy(policyBuilder.build());
            setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
        }
        return true;
    
public static voiddecrementExpectedActivityCount(java.lang.Class klass)

hide

        if (klass == null) {
            return;
        }

        final int limit;
        synchronized (StrictMode.class) {
            if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
                return;
            }

            Integer expected = sExpectedActivityInstanceCount.get(klass);
            int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
            if (newExpected == 0) {
                sExpectedActivityInstanceCount.remove(klass);
            } else {
                sExpectedActivityInstanceCount.put(klass, newExpected);
            }

            // Note: adding 1 here to give some breathing room during
            // orientation changes.  (shouldn't be necessary, though?)
            limit = newExpected + 1;
        }

        // Quick check.
        int actual = InstanceTracker.getInstanceCount(klass);
        if (actual <= limit) {
            return;
        }

        // Do a GC and explicit count to double-check.
        // This is the work that we are trying to avoid by tracking the object instances
        // explicity.  Running an explicit GC can be expensive (80ms) and so can walking
        // the heap to count instance (30ms).  This extra work can make the system feel
        // noticeably less responsive during orientation changes when activities are
        // being restarted.  Granted, it is only a problem when StrictMode is enabled
        // but it is annoying.

        System.gc();
        System.runFinalization();
        System.gc();

        long instances = VMDebug.countInstancesOfClass(klass, false);
        if (instances > limit) {
            Throwable tr = new InstanceCountViolation(klass, instances, limit);
            onVmPolicyViolation(tr.getMessage(), tr);
        }
    
private static voiddropboxViolationAsync(int violationMaskSubset, android.os.StrictMode$ViolationInfo info)
In the common case, as set by conditionallyEnableDebugLogging, we're just dropboxing any violations but not showing a dialog, not loggging, and not killing the process. In these cases we don't need to do a synchronous call to the ActivityManager. This is used by both per-thread and vm-wide violations when applicable.

        int outstanding = sDropboxCallsInFlight.incrementAndGet();
        if (outstanding > 20) {
            // What's going on?  Let's not make make the situation
            // worse and just not log.
            sDropboxCallsInFlight.decrementAndGet();
            return;
        }

        if (LOG_V) Log.d(TAG, "Dropboxing async; in-flight=" + outstanding);

        new Thread("callActivityManagerForStrictModeDropbox") {
            public void run() {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                try {
                    IActivityManager am = ActivityManagerNative.getDefault();
                    if (am == null) {
                        Log.d(TAG, "No activity manager; failed to Dropbox violation.");
                    } else {
                        am.handleApplicationStrictModeViolation(
                            RuntimeInit.getApplicationObject(),
                            violationMaskSubset,
                            info);
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException handling StrictMode violation", e);
                }
                int outstanding = sDropboxCallsInFlight.decrementAndGet();
                if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
            }
        }.start();
    
public static voidenableDeathOnNetwork()
Used by the framework to make network usage on the main thread a fatal error.

hide

        int oldPolicy = getThreadPolicyMask();
        int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
        setThreadPolicyMask(newPolicy);
    
public static voidenableDefaults()
Enable the recommended StrictMode defaults, with violations just being logged.

This catches disk and network access on the main thread, as well as leaked SQLite cursors and unclosed resources. This is simply a wrapper around {@link #setVmPolicy} and {@link #setThreadPolicy}.

        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                                   .detectAll()
                                   .penaltyLog()
                                   .build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                               .detectAll()
                               .penaltyLog()
                               .build());
    
public static android.os.StrictMode$SpanenterCriticalSpan(java.lang.String name)
Enter a named critical span (e.g. an animation)

The name is an arbitary label (or tag) that will be applied to any strictmode violation that happens while this span is active. You must call finish() on the span when done.

This will never return null, but on devices without debugging enabled, this may return a dummy object on which the finish() method is a no-op.

TODO: add CloseGuard to this, verifying callers call finish.

hide


                                                                                     
         
        if (IS_USER_BUILD) {
            return NO_OP_SPAN;
        }
        if (name == null || name.isEmpty()) {
            throw new IllegalArgumentException("name must be non-null and non-empty");
        }
        ThreadSpanState state = sThisThreadSpanState.get();
        Span span = null;
        synchronized (state) {
            if (state.mFreeListHead != null) {
                span = state.mFreeListHead;
                state.mFreeListHead = span.mNext;
                state.mFreeListSize--;
            } else {
                // Shouldn't have to do this often.
                span = new Span(state);
            }
            span.mName = name;
            span.mCreateMillis = SystemClock.uptimeMillis();
            span.mNext = state.mActiveHead;
            span.mPrev = null;
            state.mActiveHead = span;
            state.mActiveSize++;
            if (span.mNext != null) {
                span.mNext.mPrev = span;
            }
            if (LOG_V) Log.d(TAG, "Span enter=" + name + "; size=" + state.mActiveSize);
        }
        return span;
    
private static voidexecuteDeathPenalty(android.os.StrictMode$ViolationInfo info)

        int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
        throw new StrictModeViolation(info.policy, violationBit, null);
    
public static android.os.StrictMode$ThreadPolicygetThreadPolicy()
Returns the current thread's policy.

        // TODO: this was a last minute Gingerbread API change (to
        // introduce VmPolicy cleanly) but this isn't particularly
        // optimal for users who might call this method often.  This
        // should be in a thread-local and not allocate on each call.
        return new ThreadPolicy(getThreadPolicyMask());
    
public static intgetThreadPolicyMask()
Returns the bitmask of the current thread's policy.

return
the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
hide

        return BlockGuard.getThreadPolicy().getPolicyMask();
    
public static android.os.StrictMode$VmPolicygetVmPolicy()
Gets the current VM policy.

        synchronized (StrictMode.class) {
            return sVmPolicy;
        }
    
static booleanhasGatheredViolations()
Called from Parcel.writeNoException()

        return gatheredViolations.get() != null;
    
public static voidincrementExpectedActivityCount(java.lang.Class klass)

hide

        if (klass == null) {
            return;
        }

        synchronized (StrictMode.class) {
            if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
                return;
            }

            Integer expected = sExpectedActivityInstanceCount.get(klass);
            Integer newExpected = expected == null ? 1 : expected + 1;
            sExpectedActivityInstanceCount.put(klass, newExpected);
        }
    
public static voidnoteDiskRead()

hide

        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
        if (!(policy instanceof AndroidBlockGuardPolicy)) {
            // StrictMode not enabled.
            return;
        }
        ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
    
public static voidnoteDiskWrite()

hide

        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
        if (!(policy instanceof AndroidBlockGuardPolicy)) {
            // StrictMode not enabled.
            return;
        }
        ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
    
public static voidnoteSlowCall(java.lang.String name)
For code to note that it's slow. This is a no-op unless the current thread's {@link android.os.StrictMode.ThreadPolicy} has {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls} enabled.

param
name a short string for the exception stack trace that's built if when this fires.

        BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
        if (!(policy instanceof AndroidBlockGuardPolicy)) {
            // StrictMode not enabled.
            return;
        }
        ((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
    
private static voidonBinderStrictModePolicyChange(int newPolicy)
Called from android_util_Binder.cpp's android_os_Parcel_enforceInterface when an incoming Binder call requires changing the StrictMode policy mask. The role of this function is to ask Binder for its current (native) thread-local policy value and synchronize it to libcore's (Java) thread-local policy value.

        setBlockGuardPolicy(newPolicy);
    
public static voidonFileUriExposed(java.lang.String location)

hide

        final String message = "file:// Uri exposed through " + location;
        onVmPolicyViolation(message, new Throwable(message));
    
public static voidonIntentReceiverLeaked(java.lang.Throwable originStack)

hide

        onVmPolicyViolation(null, originStack);
    
public static voidonServiceConnectionLeaked(java.lang.Throwable originStack)

hide

        onVmPolicyViolation(null, originStack);
    
public static voidonSqliteObjectLeaked(java.lang.String message, java.lang.Throwable originStack)

hide

        onVmPolicyViolation(message, originStack);
    
public static voidonVmPolicyViolation(java.lang.String message, java.lang.Throwable originStack)

hide


          
           
        final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
        final boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0;
        final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
        final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);

        // Erase stuff not relevant for process-wide violations
        info.numAnimationsRunning = 0;
        info.tags = null;
        info.broadcastIntentAction = null;

        final Integer fingerprint = info.hashCode();
        final long now = SystemClock.uptimeMillis();
        long lastViolationTime = 0;
        long timeSinceLastViolationMillis = Long.MAX_VALUE;
        synchronized (sLastVmViolationTime) {
            if (sLastVmViolationTime.containsKey(fingerprint)) {
                lastViolationTime = sLastVmViolationTime.get(fingerprint);
                timeSinceLastViolationMillis = now - lastViolationTime;
            }
            if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
                sLastVmViolationTime.put(fingerprint, now);
            }
        }

        if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
            Log.e(TAG, message, originStack);
        }

        int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);

        if (penaltyDropbox && !penaltyDeath) {
            // Common case for userdebug/eng builds.  If no death and
            // just dropboxing, we can do the ActivityManager call
            // asynchronously.
            dropboxViolationAsync(violationMaskSubset, info);
            return;
        }

        if (penaltyDropbox && lastViolationTime == 0) {
            // The violationMask, passed to ActivityManager, is a
            // subset of the original StrictMode policy bitmask, with
            // only the bit violated and penalty bits to be executed
            // by the ActivityManagerService remaining set.
            final int savedPolicyMask = getThreadPolicyMask();
            try {
                // First, remove any policy before we call into the Activity Manager,
                // otherwise we'll infinite recurse as we try to log policy violations
                // to disk, thus violating policy, thus requiring logging, etc...
                // We restore the current policy below, in the finally block.
                setThreadPolicyMask(0);

                ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
                    RuntimeInit.getApplicationObject(),
                    violationMaskSubset,
                    info);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
            } finally {
                // Restore the policy.
                setThreadPolicyMask(savedPolicyMask);
            }
        }

        if (penaltyDeath) {
            System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
            Process.killProcess(Process.myPid());
            System.exit(10);
        }
    
public static voidonWebViewMethodCalledOnWrongThread(java.lang.Throwable originStack)

hide

        onVmPolicyViolation(null, originStack);
    
private static intparsePolicyFromMessage(java.lang.String message)
Parses the BlockGuard policy mask out from the Exception's getMessage() String value. Kinda gross, but least invasive. :/ Input is of the following forms: "policy=137 violation=64" "policy=137 violation=64 msg=Arbitrary text" Returns 0 on failure, which is a valid policy, but not a valid policy during a violation (else there must've been some policy in effect to violate).

        if (message == null || !message.startsWith("policy=")) {
            return 0;
        }
        int spaceIndex = message.indexOf(' ");
        if (spaceIndex == -1) {
            return 0;
        }
        String policyString = message.substring(7, spaceIndex);
        try {
            return Integer.valueOf(policyString).intValue();
        } catch (NumberFormatException e) {
            return 0;
        }
    
private static intparseViolationFromMessage(java.lang.String message)
Like parsePolicyFromMessage(), but returns the violation.

        if (message == null) {
            return 0;
        }
        int violationIndex = message.indexOf("violation=");
        if (violationIndex == -1) {
            return 0;
        }
        int numberStartIndex = violationIndex + "violation=".length();
        int numberEndIndex = message.indexOf(' ", numberStartIndex);
        if (numberEndIndex == -1) {
            numberEndIndex = message.length();
        }
        String violationString = message.substring(numberStartIndex, numberEndIndex);
        try {
            return Integer.valueOf(violationString).intValue();
        } catch (NumberFormatException e) {
            return 0;
        }
    
static voidreadAndHandleBinderCallViolations(Parcel p)
Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, we here read back all the encoded violations.

        // Our own stack trace to append
        StringWriter sw = new StringWriter();
        PrintWriter pw = new FastPrintWriter(sw, false, 256);
        new LogStackTrace().printStackTrace(pw);
        pw.flush();
        String ourStack = sw.toString();

        int policyMask = getThreadPolicyMask();
        boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;

        int numViolations = p.readInt();
        for (int i = 0; i < numViolations; ++i) {
            if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call.  i=" + i);
            ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
            if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 10000) {
                String front = info.crashInfo.stackTrace.substring(256);
                // 10000 characters is way too large for this to be any sane kind of
                // strict mode collection of stacks.  We've had a problem where we leave
                // strict mode violations associated with the thread, and it keeps tacking
                // more and more stacks on to the violations.  Looks like we're in this casse,
                // so we'll report it and bail on all of the current strict mode violations
                // we currently are maintaining for this thread.
                // First, drain the remaining violations from the parcel.
                while (i < numViolations) {
                    info = new ViolationInfo(p, !currentlyGathering);
                    i++;
                }
                // Next clear out all gathered violations.
                clearGatheredViolations();
                // Now report the problem.
                Slog.wtfStack(TAG, "Stack is too large: numViolations=" + numViolations
                        + " policy=#" + Integer.toHexString(policyMask)
                        + " front=" + front);
                return;
            }
            info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
            BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
            if (policy instanceof AndroidBlockGuardPolicy) {
                ((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
            }
        }
    
private static voidsetBlockGuardPolicy(int policyMask)

        if (policyMask == 0) {
            BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
            return;
        }
        final BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
        final AndroidBlockGuardPolicy androidPolicy;
        if (policy instanceof AndroidBlockGuardPolicy) {
            androidPolicy = (AndroidBlockGuardPolicy) policy;
        } else {
            androidPolicy = threadAndroidPolicy.get();
            BlockGuard.setThreadPolicy(androidPolicy);
        }
        androidPolicy.setPolicyMask(policyMask);
    
private static voidsetCloseGuardEnabled(boolean enabled)

        if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
            CloseGuard.setReporter(new AndroidCloseGuardReporter());
        }
        CloseGuard.setEnabled(enabled);
    
public static voidsetThreadPolicy(android.os.StrictMode$ThreadPolicy policy)
Sets the policy for what actions on the current thread should be detected, as well as the penalty if such actions occur.

Internally this sets a thread-local variable which is propagated across cross-process IPC calls, meaning you can catch violations when a system service or another process accesses the disk or network on your behalf.

param
policy the policy to put into place


                                                                        
          
        setThreadPolicyMask(policy.mask);
    
private static voidsetThreadPolicyMask(int policyMask)

        // In addition to the Java-level thread-local in Dalvik's
        // BlockGuard, we also need to keep a native thread-local in
        // Binder in order to propagate the value across Binder calls,
        // even across native-only processes.  The two are kept in
        // sync via the callback to onStrictModePolicyChange, below.
        setBlockGuardPolicy(policyMask);

        // And set the Android native version...
        Binder.setThreadStrictModePolicy(policyMask);
    
public static voidsetVmPolicy(android.os.StrictMode$VmPolicy policy)
Sets the policy for what actions in the VM process (on any thread) should be detected, as well as the penalty if such actions occur.

param
policy the policy to put into place


                                          
          
        synchronized (StrictMode.class) {
            sVmPolicy = policy;
            sVmPolicyMask = policy.mask;
            setCloseGuardEnabled(vmClosableObjectLeaksEnabled());

            Looper looper = Looper.getMainLooper();
            if (looper != null) {
                MessageQueue mq = looper.mQueue;
                if (policy.classInstanceLimit.size() == 0 ||
                    (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
                    mq.removeIdleHandler(sProcessIdleHandler);
                    sIsIdlerRegistered = false;
                } else if (!sIsIdlerRegistered) {
                    mq.addIdleHandler(sProcessIdleHandler);
                    sIsIdlerRegistered = true;
                }
            }
        }
    
private static booleantooManyViolationsThisLoop()


        
        return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
    
public static java.lang.ObjecttrackActivity(java.lang.Object instance)
Returns an object that is used to track instances of activites. The activity should store a reference to the tracker object in one of its fields.

hide


                                    
         
        return new InstanceTracker(instance);
    
public static booleanvmClosableObjectLeaksEnabled()

hide

        return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
    
public static booleanvmFileUriExposureEnabled()

hide

        return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
    
public static booleanvmRegistrationLeaksEnabled()

hide

        return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
    
public static booleanvmSqliteObjectLeaksEnabled()

hide

        return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
    
static voidwriteGatheredViolationsToParcel(Parcel p)
Called from Parcel.writeNoException()

        ArrayList<ViolationInfo> violations = gatheredViolations.get();
        if (violations == null) {
            p.writeInt(0);
        } else {
            p.writeInt(violations.size());
            for (int i = 0; i < violations.size(); ++i) {
                int start = p.dataPosition();
                violations.get(i).writeToParcel(p, 0 /* unused flags? */);
                int size = p.dataPosition()-start;
                if (size > 10*1024) {
                    Slog.d(TAG, "Wrote violation #" + i + " of " + violations.size() + ": "
                            + (p.dataPosition()-start) + " bytes");
                }
            }
            if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
            violations.clear(); // somewhat redundant, as we're about to null the threadlocal
        }
        gatheredViolations.set(null);