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_PROPERTYBoolean 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_PROPERTYThe 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_CUSTOMFor StrictMode.noteSlowCall() |
private static final int | ALL_THREAD_DETECT_BITS |
public static final int | DETECT_VM_CURSOR_LEAKSNote, a "VM_" bit, not thread. |
public static final int | DETECT_VM_CLOSABLE_LEAKSNote, a "VM_" bit, not thread. |
public static final int | DETECT_VM_ACTIVITY_LEAKSNote, 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_DEATHDeath on any detected violation. |
public static final int | PENALTY_DEATH_ON_NETWORKDeath just for detected network usage. |
public static final int | PENALTY_FLASHFlash the screen during violations. |
public static final int | PENALTY_DROPBOX |
public static final int | PENALTY_GATHERNon-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_MASKMask of all the penalty bits valid for thread policies. |
private static final int | VM_PENALTY_MASKMask of all the penalty bits valid for VM policies. |
private static final HashMap | EMPTY_CLASS_LIMIT_MAP |
private static volatile int | sVmPolicyMaskThe current VmPolicy in effect.
TODO: these are redundant (mask is in VmPolicy). Should remove sVmPolicyMask. |
private static volatile VmPolicy | sVmPolicy |
private static final AtomicInteger | sDropboxCallsInFlightThe number of threads trying to do an async dropbox write.
Just to limit ourselves out of paranoia. |
private static final ThreadLocal | gatheredViolationsLog 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 |
Methods Summary |
---|
public static android.os.StrictMode$ThreadPolicy | allowThreadDiskReads()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.
int oldPolicyMask = getThreadPolicyMask();
int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_READ);
if (newPolicyMask != oldPolicyMask) {
setThreadPolicyMask(newPolicyMask);
}
return new ThreadPolicy(oldPolicyMask);
|
public static android.os.StrictMode$ThreadPolicy | allowThreadDiskWrites()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.
int oldPolicyMask = getThreadPolicyMask();
int newPolicyMask = oldPolicyMask & ~(DETECT_DISK_WRITE | DETECT_DISK_READ);
if (newPolicyMask != oldPolicyMask) {
setThreadPolicyMask(newPolicyMask);
}
return new ThreadPolicy(oldPolicyMask);
|
private static boolean | amTheSystemServerProcess()
// 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 void | clearGatheredViolations()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 void | conditionallyCheckInstanceCounts()
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 boolean | conditionallyEnableDebugLogging()Enable DropBox logging for debug phone builds.
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 void | decrementExpectedActivityCount(java.lang.Class klass)
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 void | dropboxViolationAsync(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 void | enableDeathOnNetwork()Used by the framework to make network usage on the main
thread a fatal error.
int oldPolicy = getThreadPolicyMask();
int newPolicy = oldPolicy | DETECT_NETWORK | PENALTY_DEATH_ON_NETWORK;
setThreadPolicyMask(newPolicy);
|
public static void | enableDefaults()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$Span | enterCriticalSpan(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.
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 void | executeDeathPenalty(android.os.StrictMode$ViolationInfo info)
int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
throw new StrictModeViolation(info.policy, violationBit, null);
|
public static android.os.StrictMode$ThreadPolicy | getThreadPolicy()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 int | getThreadPolicyMask()Returns the bitmask of the current thread's policy.
return BlockGuard.getThreadPolicy().getPolicyMask();
|
public static android.os.StrictMode$VmPolicy | getVmPolicy()Gets the current VM policy.
synchronized (StrictMode.class) {
return sVmPolicy;
}
|
static boolean | hasGatheredViolations()Called from Parcel.writeNoException()
return gatheredViolations.get() != null;
|
public static void | incrementExpectedActivityCount(java.lang.Class klass)
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 void | noteDiskRead()
BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
if (!(policy instanceof AndroidBlockGuardPolicy)) {
// StrictMode not enabled.
return;
}
((AndroidBlockGuardPolicy) policy).onReadFromDisk();
|
public static void | noteDiskWrite()
BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
if (!(policy instanceof AndroidBlockGuardPolicy)) {
// StrictMode not enabled.
return;
}
((AndroidBlockGuardPolicy) policy).onWriteToDisk();
|
public static void | noteSlowCall(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.
BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
if (!(policy instanceof AndroidBlockGuardPolicy)) {
// StrictMode not enabled.
return;
}
((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
|
private static void | onBinderStrictModePolicyChange(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 void | onFileUriExposed(java.lang.String location)
final String message = "file:// Uri exposed through " + location;
onVmPolicyViolation(message, new Throwable(message));
|
public static void | onIntentReceiverLeaked(java.lang.Throwable originStack)
onVmPolicyViolation(null, originStack);
|
public static void | onServiceConnectionLeaked(java.lang.Throwable originStack)
onVmPolicyViolation(null, originStack);
|
public static void | onSqliteObjectLeaked(java.lang.String message, java.lang.Throwable originStack)
onVmPolicyViolation(message, originStack);
|
public static void | onVmPolicyViolation(java.lang.String message, java.lang.Throwable originStack)
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 void | onWebViewMethodCalledOnWrongThread(java.lang.Throwable originStack)
onVmPolicyViolation(null, originStack);
|
private static int | parsePolicyFromMessage(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 int | parseViolationFromMessage(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 void | readAndHandleBinderCallViolations(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 void | setBlockGuardPolicy(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 void | setCloseGuardEnabled(boolean enabled)
if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
CloseGuard.setReporter(new AndroidCloseGuardReporter());
}
CloseGuard.setEnabled(enabled);
|
public static void | setThreadPolicy(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.
setThreadPolicyMask(policy.mask);
|
private static void | setThreadPolicyMask(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 void | setVmPolicy(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.
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 boolean | tooManyViolationsThisLoop()
return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
|
public static java.lang.Object | trackActivity(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.
return new InstanceTracker(instance);
|
public static boolean | vmClosableObjectLeaksEnabled()
return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
|
public static boolean | vmFileUriExposureEnabled()
return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
|
public static boolean | vmRegistrationLeaksEnabled()
return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
|
public static boolean | vmSqliteObjectLeaksEnabled()
return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
|
static void | writeGatheredViolationsToParcel(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);
|