summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/StrictMode.java80
1 files changed, 61 insertions, 19 deletions
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index c836e56..4facc39 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -32,6 +32,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* <p>StrictMode is a developer tool which detects things you might be
@@ -208,6 +209,12 @@ public final class StrictMode {
*/
private static volatile int sVmPolicyMask = 0;
+ /**
+ * The number of threads trying to do an async dropbox write.
+ * Just to limit ourselves out of paranoia.
+ */
+ private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
+
private StrictMode() {}
/**
@@ -984,7 +991,6 @@ public final class StrictMode {
if (violationMaskSubset != 0) {
int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
violationMaskSubset |= violationBit;
- final int violationMaskSubsetFinal = violationMaskSubset;
final int savedPolicyMask = getThreadPolicyMask();
final boolean justDropBox = (info.policy & PENALTY_MASK) == PENALTY_DROPBOX;
@@ -995,20 +1001,7 @@ public final class StrictMode {
// call synchronously which Binder data suggests
// isn't always super fast, despite the implementation
// in the ActivityManager trying to be mostly async.
- new Thread("callActivityManagerForStrictModeDropbox") {
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- try {
- ActivityManagerNative.getDefault().
- handleApplicationStrictModeViolation(
- RuntimeInit.getApplicationObject(),
- violationMaskSubsetFinal,
- info);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException handling StrictMode violation", e);
- }
- }
- }.start();
+ dropboxViolationAsync(violationMaskSubset, info);
return;
}
@@ -1040,6 +1033,44 @@ public final class StrictMode {
}
}
+ /**
+ * 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.
+ */
+ private static void dropboxViolationAsync(
+ final int violationMaskSubset, final ViolationInfo info) {
+ 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 {
+ ActivityManagerNative.getDefault().
+ 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();
+ }
+
private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
public void report (String message, Throwable allocationSite) {
onVmPolicyViolation(message, allocationSite);
@@ -1130,14 +1161,25 @@ public final class StrictMode {
Log.e(TAG, message, originStack);
}
- if ((sVmPolicyMask & PENALTY_DROPBOX) != 0) {
- final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
+ boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
+ boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0;
+
+ int violationMaskSubset = PENALTY_DROPBOX | DETECT_VM_CURSOR_LEAKS;
+ ViolationInfo info = new ViolationInfo(originStack, 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) {
// 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.
- int violationMaskSubset = PENALTY_DROPBOX | DETECT_VM_CURSOR_LEAKS;
final int savedPolicyMask = getThreadPolicyMask();
try {
// First, remove any policy before we call into the Activity Manager,
@@ -1158,7 +1200,7 @@ public final class StrictMode {
}
}
- if ((sVmPolicyMask & PENALTY_DEATH) != 0) {
+ if (penaltyDeath) {
System.err.println("StrictMode VmPolicy violation with POLICY_DEATH; shutting down.");
Process.killProcess(Process.myPid());
System.exit(10);