diff options
author | Brad Fitzpatrick <bradfitz@android.com> | 2010-06-11 13:57:58 -0700 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@android.com> | 2010-06-11 16:11:26 -0700 |
commit | 46d42387464a651268648659e91d022566d4844c (patch) | |
tree | 1252f3113aea8f95506bc0860b461fe3737c45c7 /core/java/android/os/StrictMode.java | |
parent | 126ca6f9ecab6f912ea9f4f00af35c410aae504b (diff) | |
download | frameworks_base-46d42387464a651268648659e91d022566d4844c.zip frameworks_base-46d42387464a651268648659e91d022566d4844c.tar.gz frameworks_base-46d42387464a651268648659e91d022566d4844c.tar.bz2 |
More StrictMode work, handling violations in ActivityManagerService.
Also starts to do duplicate-suppression.
Change-Id: I0502f6ab6c45fa319298de4874ecfe44b7829d21
Diffstat (limited to 'core/java/android/os/StrictMode.java')
-rw-r--r-- | core/java/android/os/StrictMode.java | 79 |
1 files changed, 53 insertions, 26 deletions
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 876ec39..c0ae263 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -23,6 +23,8 @@ import com.android.internal.os.RuntimeInit; import dalvik.system.BlockGuard; +import java.util.HashMap; + /** * <p>StrictMode lets you impose stricter rules under which your * application runs.</p> @@ -30,6 +32,12 @@ import dalvik.system.BlockGuard; public final class StrictMode { private static final String TAG = "StrictMode"; + // Only log a duplicate stack trace to the logs every second. + private static final long MIN_LOG_INTERVAL_MS = 1000; + + // Only show an annoying dialog at most every 30 seconds + private static final long MIN_DIALOG_INTERVAL_MS = 30000; + private StrictMode() {} public static final int DISALLOW_DISK_WRITE = 0x01; @@ -73,6 +81,10 @@ public final class StrictMode { * @param policyMask a bitmask of DISALLOW_* and PENALTY_* values. */ public static void setThreadBlockingPolicy(final int policyMask) { + if (policyMask == 0) { + BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY); + return; + } BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); if (!(policy instanceof AndroidBlockGuardPolicy)) { BlockGuard.setThreadPolicy(new AndroidBlockGuardPolicy(policyMask)); @@ -91,19 +103,13 @@ public final class StrictMode { return BlockGuard.getThreadPolicy().getPolicyMask(); } - /** @hide */ - public static void setDropBoxManager(DropBoxManager dropBoxManager) { - BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); - if (!(policy instanceof AndroidBlockGuardPolicy)) { - policy = new AndroidBlockGuardPolicy(0); - BlockGuard.setThreadPolicy(policy); - } - ((AndroidBlockGuardPolicy) policy).setDropBoxManager(dropBoxManager); - } - private static class AndroidBlockGuardPolicy implements BlockGuard.Policy { private int mPolicyMask; - private DropBoxManager mDropBoxManager = null; + + // Map from violation stacktrace hashcode -> uptimeMillis of + // last violation. No locking needed, as this is only + // accessed by the same thread. + private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>(); public AndroidBlockGuardPolicy(final int policyMask) { mPolicyMask = policyMask; @@ -142,10 +148,6 @@ public final class StrictMode { mPolicyMask = policyMask; } - public void setDropBoxManager(DropBoxManager dropBoxManager) { - mDropBoxManager = dropBoxManager; - } - private void handleViolation(int violationBit) { final BlockGuard.BlockGuardPolicyException violation = new BlockGuard.BlockGuardPolicyException(mPolicyMask, violationBit); @@ -182,7 +184,23 @@ public final class StrictMode { // the old policy here. int policy = violation.getPolicy(); - if ((policy & PENALTY_LOG) != 0) { + // Not _really_ a Crash, but we use the same data structure... + ApplicationErrorReport.CrashInfo crashInfo = + new ApplicationErrorReport.CrashInfo(violation); + + // Not perfect, but fast and good enough for dup suppression. + Integer crashFingerprint = crashInfo.stackTrace.hashCode(); + long lastViolationTime = 0; + if (mLastViolationTime.containsKey(crashFingerprint)) { + lastViolationTime = mLastViolationTime.get(crashFingerprint); + } + long now = SystemClock.uptimeMillis(); + mLastViolationTime.put(crashFingerprint, now); + long timeSinceLastViolationMillis = lastViolationTime == 0 ? + Long.MAX_VALUE : (now - lastViolationTime); + + if ((policy & PENALTY_LOG) != 0 && + timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) { if (durationMillis != -1) { Log.d(TAG, "StrictMode policy violation; ~duration=" + durationMillis + " ms", violation); @@ -191,24 +209,33 @@ public final class StrictMode { } } - if ((policy & PENALTY_DIALOG) != 0) { - // Currently this is just used for the dialog. + // 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 violationMask = 0; + + if ((policy & PENALTY_DIALOG) != 0 && + timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) { + violationMask |= PENALTY_DIALOG; + } + + if ((policy & PENALTY_DROPBOX) != 0 && lastViolationTime == 0) { + violationMask |= PENALTY_DROPBOX; + } + + if (violationMask != 0) { + violationMask |= violation.getPolicyViolation(); try { ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( RuntimeInit.getApplicationObject(), + violationMask, new ApplicationErrorReport.CrashInfo(violation)); } catch (RemoteException e) { - Log.e(TAG, "RemoteException trying to open strict mode dialog", e); + Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); } } - if ((policy & PENALTY_DROPBOX) != 0) { - // TODO: call into ActivityManagerNative to do the dropboxing. - // But do the first-layer signature dup-checking first client-side. - // This conditional should be combined with the above, too, along - // with PENALTY_DEATH below. - } - if ((policy & PENALTY_DEATH) != 0) { System.err.println("StrictMode policy violation with POLICY_DEATH; shutting down."); Process.killProcess(Process.myPid()); |