Merge "More StrictMode work, handling violations in ActivityManagerService." into gingerbread
This commit is contained in:
committed by
Android (Google) Code Review
commit
94f14aeca9
@ -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();
|
||||
|
@ -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 |
|
||||
|
@ -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.
|
||||
*/
|
||||
@ -73,6 +72,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}.
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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());
|
||||
|
@ -97,6 +97,7 @@ import android.os.Process;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.StrictMode;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.provider.Settings;
|
||||
@ -9354,11 +9355,17 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
}
|
||||
|
||||
public void handleApplicationStrictModeViolation(
|
||||
IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
|
||||
IBinder app, int violationMask, ApplicationErrorReport.CrashInfo crashInfo) {
|
||||
ProcessRecord r = findAppProcess(app);
|
||||
// TODO: implement
|
||||
Log.w(TAG, "handleApplicationStrictModeViolation.");
|
||||
|
||||
if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
|
||||
Integer crashFingerprint = crashInfo.stackTrace.hashCode();
|
||||
Log.d(TAG, "supposed to drop box for fingerprint " + crashFingerprint);
|
||||
}
|
||||
|
||||
if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
|
||||
AppErrorResult result = new AppErrorResult();
|
||||
synchronized (this) {
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
@ -9376,6 +9383,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
int res = result.get();
|
||||
Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
|
||||
|
@ -80,9 +80,6 @@ class AppErrorDialog extends BaseErrorDialog {
|
||||
DISMISS_TIMEOUT);
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
}
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
synchronized (mProc) {
|
||||
|
@ -81,9 +81,6 @@ class StrictModeViolationDialog extends BaseErrorDialog {
|
||||
DISMISS_TIMEOUT);
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
}
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
synchronized (mProc) {
|
||||
|
Reference in New Issue
Block a user