diff options
author | Brad Fitzpatrick <bradfitz@android.com> | 2010-07-07 16:06:39 -0700 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@android.com> | 2010-07-15 13:18:05 -0700 |
commit | 727de40c6bc7c6521a0542ea9def5d5c7b1c5e06 (patch) | |
tree | 0d2f0f400211efbaf131020d7c4d38e647f5bbe3 /core/java | |
parent | d6343c26b8580f61a257a3045bfa124049201116 (diff) | |
download | frameworks_base-727de40c6bc7c6521a0542ea9def5d5c7b1c5e06.zip frameworks_base-727de40c6bc7c6521a0542ea9def5d5c7b1c5e06.tar.gz frameworks_base-727de40c6bc7c6521a0542ea9def5d5c7b1c5e06.tar.bz2 |
More StrictMode work, keeping Binder & BlockGuard's thread-locals in-sync.
Change-Id: Ia67cabcc17a73a0f15907ffea683d06bc41b90e5
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/os/Binder.java | 25 | ||||
-rw-r--r-- | core/java/android/os/StrictMode.java | 51 |
2 files changed, 75 insertions, 1 deletions
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index c9df567..4c40982 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -101,7 +101,30 @@ public class Binder implements IBinder { * @see #clearCallingIdentity */ public static final native void restoreCallingIdentity(long token); - + + /** + * Sets the native thread-local StrictMode policy mask. + * + * <p>The StrictMode settings are kept in two places: a Java-level + * threadlocal for libcore/Dalvik, and a native threadlocal (set + * here) for propagation via Binder calls. This is a little + * unfortunate, but necessary to break otherwise more unfortunate + * dependencies either of Dalvik on Android, or Android + * native-only code on Dalvik. + * + * @see StrictMode + * @hide + */ + public static final native void setThreadStrictModePolicy(int policyMask); + + /** + * Gets the current native thread-local StrictMode policy mask. + * + * @see #setThreadStrictModePolicy + * @hide + */ + public static final native int getThreadStrictModePolicy(); + /** * Flush any Binder commands pending in the current thread to the kernel * driver. This can be diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 9b18719..f7ad884 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -69,6 +69,17 @@ public final class StrictMode { */ public static final int PENALTY_DROPBOX = 0x80; + /** + * Non-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. + * + * @hide + */ + public static final int PENALTY_GATHER = 0x100; + /** @hide */ public static final int PENALTY_MASK = PENALTY_LOG | PENALTY_DIALOG | @@ -81,6 +92,19 @@ public final class StrictMode { * @param policyMask a bitmask of DISALLOW_* and PENALTY_* values. */ public static void setThreadBlockingPolicy(final 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); + } + + // Sets the policy in Dalvik/libcore (BlockGuard) + private static void setBlockGuardPolicy(final int policyMask) { if (policyMask == 0) { BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY); return; @@ -189,6 +213,11 @@ public final class StrictMode { new ApplicationErrorReport.CrashInfo(violation); crashInfo.durationMillis = durationMillis; + if ((policy & PENALTY_GATHER) != 0) { + Log.d(TAG, "StrictMode violation via Binder call; ignoring for now."); + return; + } + // Not perfect, but fast and good enough for dup suppression. Integer crashFingerprint = crashInfo.stackTrace.hashCode(); long lastViolationTime = 0; @@ -227,13 +256,23 @@ public final class StrictMode { if (violationMask != 0) { violationMask |= violation.getPolicyViolation(); + final int savedPolicy = getThreadBlockingPolicy(); 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. + setThreadBlockingPolicy(0); + ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( RuntimeInit.getApplicationObject(), violationMask, new ApplicationErrorReport.CrashInfo(violation)); } catch (RemoteException e) { Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); + } finally { + // Restore the policy. + setThreadBlockingPolicy(savedPolicy); } } @@ -244,4 +283,16 @@ public final class StrictMode { } } } + + /** + * 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. + */ + private static void onBinderStrictModePolicyChange(int newPolicy) { + setBlockGuardPolicy(newPolicy); + } } |