summaryrefslogtreecommitdiff
path: root/core/java/android/os/BaseBundle.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/os/BaseBundle.java')
-rw-r--r--core/java/android/os/BaseBundle.java57
1 files changed, 51 insertions, 6 deletions
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index fe17fbd93adb..fa6766cedda0 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -26,7 +26,9 @@ import java.util.ArrayList;
import java.util.Set;
/**
- * A mapping from String values to various types.
+ * A mapping from String keys to values of various types. In most cases, you
+ * should work directly with either the {@link Bundle} or
+ * {@link PersistableBundle} subclass.
*/
public class BaseBundle {
private static final String TAG = "Bundle";
@@ -35,6 +37,32 @@ public class BaseBundle {
// Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
+ /**
+ * Flag indicating that this Bundle is okay to "defuse." That is, it's okay
+ * for system processes to ignore any {@link BadParcelableException}
+ * encountered when unparceling it, leaving an empty bundle in its place.
+ * <p>
+ * This should <em>only</em> be set when the Bundle reaches its final
+ * destination, otherwise a system process may clobber contents that were
+ * destined for an app that could have unparceled them.
+ */
+ static final int FLAG_DEFUSABLE = 1 << 0;
+
+ private static volatile boolean sShouldDefuse = false;
+
+ /**
+ * Set global variable indicating that any Bundles parsed in this process
+ * should be "defused." That is, any {@link BadParcelableException}
+ * encountered will be suppressed and logged, leaving an empty Bundle
+ * instead of crashing.
+ *
+ * @hide
+ */
+ public static void setShouldDefuse(boolean shouldDefuse) {
+ sShouldDefuse = shouldDefuse;
+ }
+
+ /** {@hide} */
static final Parcel EMPTY_PARCEL;
static {
@@ -58,6 +86,9 @@ public class BaseBundle {
*/
private ClassLoader mClassLoader;
+ /** {@hide} */
+ int mFlags;
+
/**
* Constructs a new, empty Bundle that uses a specific ClassLoader for
* instantiating Parcelable and Serializable objects.
@@ -185,6 +216,11 @@ public class BaseBundle {
return;
}
+ if (sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) {
+ Log.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may "
+ + "clobber all data inside!", new Throwable());
+ }
+
if (mParcelledData == EMPTY_PARCEL) {
if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ ": empty");
@@ -209,9 +245,19 @@ public class BaseBundle {
mMap.erase();
mMap.ensureCapacity(N);
}
- mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
- mParcelledData.recycle();
- mParcelledData = null;
+ try {
+ mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
+ } catch (BadParcelableException e) {
+ if (sShouldDefuse) {
+ Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
+ mMap.erase();
+ } else {
+ throw e;
+ }
+ } finally {
+ mParcelledData.recycle();
+ mParcelledData = null;
+ }
if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ " final map: " + mMap);
}
@@ -1431,9 +1477,8 @@ public class BaseBundle {
return;
}
- int magic = parcel.readInt();
+ final int magic = parcel.readInt();
if (magic != BUNDLE_MAGIC) {
- //noinspection ThrowableInstanceNeverThrown
throw new IllegalStateException("Bad magic number for Bundle: 0x"
+ Integer.toHexString(magic));
}