summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@android.com>2010-06-11 13:57:58 -0700
committerBrad Fitzpatrick <bradfitz@android.com>2010-06-11 16:11:26 -0700
commit46d42387464a651268648659e91d022566d4844c (patch)
tree1252f3113aea8f95506bc0860b461fe3737c45c7 /core/java/android
parent126ca6f9ecab6f912ea9f4f00af35c410aae504b (diff)
downloadframeworks_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')
-rw-r--r--core/java/android/app/ActivityManagerNative.java5
-rw-r--r--core/java/android/app/ActivityThread.java1
-rw-r--r--core/java/android/app/ApplicationErrorReport.java6
-rw-r--r--core/java/android/app/IActivityManager.java7
-rw-r--r--core/java/android/os/StrictMode.java79
5 files changed, 68 insertions, 30 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b4c7edc..2c1f2da 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1065,8 +1065,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case HANDLE_APPLICATION_STRICT_MODE_VIOLATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder app = data.readStrongBinder();
+ int violationMask = data.readInt();
ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data);
- handleApplicationStrictModeViolation(app, ci);
+ handleApplicationStrictModeViolation(app, violationMask, ci);
reply.writeNoException();
return true;
}
@@ -2551,12 +2552,14 @@ class ActivityManagerProxy implements IActivityManager
}
public void handleApplicationStrictModeViolation(IBinder app,
+ int violationMask,
ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app);
+ data.writeInt(violationMask);
crashInfo.writeToParcel(data, 0);
mRemote.transact(HANDLE_APPLICATION_STRICT_MODE_VIOLATION_TRANSACTION, data, reply, 0);
reply.readException();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 49f1a8f..0ce790e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4139,7 +4139,6 @@ public final class ActivityThread {
*/
if ((data.appInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0 &&
!"user".equals(Build.TYPE)) {
- StrictMode.setDropBoxManager(ContextImpl.createDropBoxManager());
StrictMode.setThreadBlockingPolicy(
StrictMode.DISALLOW_DISK_WRITE |
StrictMode.DISALLOW_DISK_READ |
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index f0cef98..57a23ae 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -52,7 +52,6 @@ public class ApplicationErrorReport implements Parcelable {
// System property defining default error report receiver
static final String DEFAULT_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.default";
-
/**
* Uninitialized error report.
*/
@@ -74,6 +73,11 @@ public class ApplicationErrorReport implements Parcelable {
public static final int TYPE_BATTERY = 3;
/**
+ * An error report about a StrictMode violation.
+ */
+ public static final int TYPE_STRICT_MODE_VIOLATION = 4;
+
+ /**
* Type of this report. Can be one of {@link #TYPE_NONE},
* {@link #TYPE_CRASH}, {@link #TYPE_ANR}, or {@link #TYPE_BATTERY}.
*/
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index ca09290..542bc41 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -256,7 +256,12 @@ public interface IActivityManager extends IInterface {
ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
public boolean handleApplicationWtf(IBinder app, String tag,
ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
- public void handleApplicationStrictModeViolation(IBinder app,
+
+ // A StrictMode violation to be handled. The violationMask 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.
+ public void handleApplicationStrictModeViolation(IBinder app, int violationMask,
ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
/*
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());