diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/os/BaseBundle.java | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java index f5a7433e9739..0fef78d1f4ba 100644 --- a/core/java/android/os/BaseBundle.java +++ b/core/java/android/os/BaseBundle.java @@ -40,8 +40,9 @@ public class BaseBundle { private static final String TAG = "Bundle"; static final boolean DEBUG = false; - // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp. - static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L' + // Keep them in sync with frameworks/native/libs/binder/PersistableBundle.cpp. + private static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L' + private static final int BUNDLE_MAGIC_NATIVE = 0x4C444E44; // 'B' 'N' 'D' 'N' /** * Flag indicating that this Bundle is okay to "defuse." That is, it's okay @@ -91,6 +92,11 @@ public class BaseBundle { Parcel mParcelledData = null; /** + * Whether {@link #mParcelledData} was generated by native coed or not. + */ + private boolean mParcelledByNative; + + /** * The ClassLoader used when unparcelling data from mParcelledData. */ private ClassLoader mClassLoader; @@ -223,7 +229,7 @@ public class BaseBundle { synchronized (this) { final Parcel source = mParcelledData; if (source != null) { - initializeFromParcelLocked(source, /*recycleParcel=*/ true); + initializeFromParcelLocked(source, /*recycleParcel=*/ true, mParcelledByNative); } else { if (DEBUG) { Log.d(TAG, "unparcel " @@ -234,7 +240,8 @@ public class BaseBundle { } } - private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean recycleParcel) { + private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean recycleParcel, + boolean parcelledByNative) { if (LOG_DEFUSABLE && sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) { Slog.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may " + "clobber all data inside!", new Throwable()); @@ -251,6 +258,7 @@ public class BaseBundle { mMap.erase(); } mParcelledData = null; + mParcelledByNative = false; return; } @@ -270,7 +278,15 @@ public class BaseBundle { map.ensureCapacity(count); } try { - parcelledData.readArrayMapInternal(map, count, mClassLoader); + if (parcelledByNative) { + // If it was parcelled by native code, then the array map keys aren't sorted + // by their hash codes, so use the safe (slow) one. + parcelledData.readArrayMapSafelyInternal(map, count, mClassLoader); + } else { + // If parcelled by Java, we know the contents are sorted properly, + // so we can use ArrayMap.append(). + parcelledData.readArrayMapInternal(map, count, mClassLoader); + } } catch (BadParcelableException e) { if (sShouldDefuse) { Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e); @@ -284,6 +300,7 @@ public class BaseBundle { recycleParcel(parcelledData); } mParcelledData = null; + mParcelledByNative = false; } if (DEBUG) { Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this)) @@ -403,14 +420,17 @@ public class BaseBundle { if (from.mParcelledData != null) { if (from.isEmptyParcel()) { mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL; + mParcelledByNative = false; } else { mParcelledData = Parcel.obtain(); mParcelledData.appendFrom(from.mParcelledData, 0, from.mParcelledData.dataSize()); mParcelledData.setDataPosition(0); + mParcelledByNative = from.mParcelledByNative; } } else { mParcelledData = null; + mParcelledByNative = false; } if (from.mMap != null) { @@ -1538,7 +1558,7 @@ public class BaseBundle { } else { int length = mParcelledData.dataSize(); parcel.writeInt(length); - parcel.writeInt(BUNDLE_MAGIC); + parcel.writeInt(mParcelledByNative ? BUNDLE_MAGIC_NATIVE : BUNDLE_MAGIC); parcel.appendFrom(mParcelledData, 0, length); } return; @@ -1585,11 +1605,14 @@ public class BaseBundle { } else if (length == 0) { // Empty Bundle or end of data. mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL; + mParcelledByNative = false; return; } final int magic = parcel.readInt(); - if (magic != BUNDLE_MAGIC) { + final boolean isJavaBundle = magic == BUNDLE_MAGIC; + final boolean isNativeBundle = magic == BUNDLE_MAGIC_NATIVE; + if (!isJavaBundle && !isNativeBundle) { throw new IllegalStateException("Bad magic number for Bundle: 0x" + Integer.toHexString(magic)); } @@ -1598,7 +1621,7 @@ public class BaseBundle { // If the parcel has a read-write helper, then we can't lazily-unparcel it, so just // unparcel right away. synchronized (this) { - initializeFromParcelLocked(parcel, /*recycleParcel=*/ false); + initializeFromParcelLocked(parcel, /*recycleParcel=*/ false, isNativeBundle); } return; } @@ -1616,6 +1639,7 @@ public class BaseBundle { p.setDataPosition(0); mParcelledData = p; + mParcelledByNative = isNativeBundle; } /** {@hide} */ |
