Loading core/java/android/os/Bundle.java +13 −17 Original line number Diff line number Diff line Loading @@ -16,15 +16,12 @@ package android.os; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** Loading @@ -37,13 +34,13 @@ public final class Bundle implements Parcelable, Cloneable { static { EMPTY = new Bundle(); EMPTY.mMap = Collections.unmodifiableMap(new HashMap<String, Object>()); EMPTY.mMap = ArrayMap.EMPTY; } // Invariant - exactly one of mMap / mParcelledData will be null // (except inside a call to unparcel) /* package */ Map<String, Object> mMap = null; /* package */ ArrayMap<String, Object> mMap = null; /* * If mParcelledData is non-null, then mMap will be null and the Loading @@ -65,7 +62,7 @@ public final class Bundle implements Parcelable, Cloneable { * Constructs a new, empty Bundle. */ public Bundle() { mMap = new HashMap<String, Object>(); mMap = new ArrayMap<String, Object>(); mClassLoader = getClass().getClassLoader(); } Loading @@ -91,7 +88,7 @@ public final class Bundle implements Parcelable, Cloneable { * inside of the Bundle. */ public Bundle(ClassLoader loader) { mMap = new HashMap<String, Object>(); mMap = new ArrayMap<String, Object>(); mClassLoader = loader; } Loading @@ -102,7 +99,7 @@ public final class Bundle implements Parcelable, Cloneable { * @param capacity the initial capacity of the Bundle */ public Bundle(int capacity) { mMap = new HashMap<String, Object>(capacity); mMap = new ArrayMap<String, Object>(capacity); mClassLoader = getClass().getClassLoader(); } Loading @@ -122,7 +119,7 @@ public final class Bundle implements Parcelable, Cloneable { } if (b.mMap != null) { mMap = new HashMap<String, Object>(b.mMap); mMap = new ArrayMap<String, Object>(b.mMap); } else { mMap = null; } Loading Loading @@ -162,7 +159,7 @@ public final class Bundle implements Parcelable, Cloneable { if (size == 0) { return null; } Object o = mMap.values().iterator().next(); Object o = mMap.valueAt(0); try { return (String) o; } catch (ClassCastException e) { Loading Loading @@ -218,9 +215,9 @@ public final class Bundle implements Parcelable, Cloneable { return; } if (mMap == null) { mMap = new HashMap<String, Object>(N); mMap = new ArrayMap<String, Object>(N); } mParcelledData.readMapInternal(mMap, N, mClassLoader); mParcelledData.readArrayMapInternal(mMap, N, mClassLoader); mParcelledData.recycle(); mParcelledData = null; } Loading Loading @@ -331,9 +328,8 @@ public final class Bundle implements Parcelable, Cloneable { } } else { // It's been unparcelled, so we need to walk the map Iterator<Map.Entry<String, Object>> iter = mMap.entrySet().iterator(); while (!fdFound && iter.hasNext()) { Object obj = iter.next().getValue(); for (int i=mMap.size()-1; i>=0; i--) { Object obj = mMap.valueAt(i); if (obj instanceof Parcelable) { if ((((Parcelable)obj).describeContents() & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) { Loading Loading @@ -1643,7 +1639,7 @@ public final class Bundle implements Parcelable, Cloneable { parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' int oldPos = parcel.dataPosition(); parcel.writeMapInternal(mMap); parcel.writeArrayMapInternal(mMap); int newPos = parcel.dataPosition(); // Backpatch length Loading core/java/android/os/Parcel.java +29 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.os; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import android.util.SparseBooleanArray; Loading Loading @@ -592,6 +593,23 @@ public final class Parcel { } } /** * Flatten an ArrayMap into the parcel at the current dataPosition(), * growing dataCapacity() if needed. The Map keys must be String objects. */ /* package */ void writeArrayMapInternal(ArrayMap<String,Object> val) { if (val == null) { writeInt(-1); return; } final int N = val.size(); writeInt(N); for (int i=0; i<N; i++) { writeValue(val.keyAt(i)); writeValue(val.valueAt(i)); } } /** * Flatten a Bundle into the parcel at the current dataPosition(), * growing dataCapacity() if needed. Loading Loading @@ -2258,6 +2276,16 @@ public final class Parcel { } } /* package */ void readArrayMapInternal(ArrayMap outVal, int N, ClassLoader loader) { while (N > 0) { Object key = readValue(loader); Object value = readValue(loader); outVal.append(key, value); N--; } } private void readListInternal(List outVal, int N, ClassLoader loader) { while (N > 0) { Loading core/java/android/util/ArrayMap.java +42 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,11 @@ public final class ArrayMap<K, V> implements Map<K, V> { */ private static final int CACHE_SIZE = 10; /** * @hide Special immutable empty ArrayMap. */ public static final ArrayMap EMPTY = new ArrayMap(true); /** * Caches of small array objects to avoid spamming garbage. The cache * Object[] variable is a pointer to a linked list of array objects. Loading @@ -71,6 +76,11 @@ public final class ArrayMap<K, V> implements Map<K, V> { static Object[] mTwiceBaseCache; static int mTwiceBaseCacheSize; /** * Special hash array value that indicates the container is immutable. */ static final int[] EMPTY_IMMUTABLE_INTS = new int[0]; int[] mHashes; Object[] mArray; int mSize; Loading Loading @@ -115,6 +125,9 @@ public final class ArrayMap<K, V> implements Map<K, V> { } private void allocArrays(final int size) { if (mHashes == EMPTY_IMMUTABLE_INTS) { throw new UnsupportedOperationException("ArrayMap is immutable"); } if (size == (BASE_SIZE*2)) { synchronized (ArrayMap.class) { if (mTwiceBaseCache != null) { Loading Loading @@ -204,6 +217,12 @@ public final class ArrayMap<K, V> implements Map<K, V> { mSize = 0; } private ArrayMap(boolean immutable) { mHashes = EMPTY_IMMUTABLE_INTS; mArray = ContainerHelpers.EMPTY_OBJECTS; mSize = 0; } /** * Create a new ArrayMap with the mappings from the given ArrayMap. */ Loading @@ -219,7 +238,7 @@ public final class ArrayMap<K, V> implements Map<K, V> { */ @Override public void clear() { if (mSize != 0) { if (mSize > 0) { freeArrays(mHashes, mArray, mSize); mHashes = ContainerHelpers.EMPTY_INTS; mArray = ContainerHelpers.EMPTY_OBJECTS; Loading Loading @@ -390,6 +409,28 @@ public final class ArrayMap<K, V> implements Map<K, V> { return null; } /** * Special fast path for appending items to the end of the array without validation. * The array must already be large enough to contain the item. * @hide */ public void append(K key, V value) { int index = mSize; final int hash = key.hashCode(); if (index >= mHashes.length) { throw new IllegalStateException("Array is full"); } if (index > 0 && mHashes[index-1] > hash) { throw new IllegalArgumentException("New hash " + hash + " is before end of array hash " + mHashes[index-1]); } mSize = index+1; mHashes[index] = hash; index <<= 1; mArray[index] = key; mArray[index+1] = value; } /** * Perform a {@link #put(Object, Object)} of all key/value pairs in <var>array</var> * @param array The array whose contents are to be retrieved. Loading Loading
core/java/android/os/Bundle.java +13 −17 Original line number Diff line number Diff line Loading @@ -16,15 +16,12 @@ package android.os; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** Loading @@ -37,13 +34,13 @@ public final class Bundle implements Parcelable, Cloneable { static { EMPTY = new Bundle(); EMPTY.mMap = Collections.unmodifiableMap(new HashMap<String, Object>()); EMPTY.mMap = ArrayMap.EMPTY; } // Invariant - exactly one of mMap / mParcelledData will be null // (except inside a call to unparcel) /* package */ Map<String, Object> mMap = null; /* package */ ArrayMap<String, Object> mMap = null; /* * If mParcelledData is non-null, then mMap will be null and the Loading @@ -65,7 +62,7 @@ public final class Bundle implements Parcelable, Cloneable { * Constructs a new, empty Bundle. */ public Bundle() { mMap = new HashMap<String, Object>(); mMap = new ArrayMap<String, Object>(); mClassLoader = getClass().getClassLoader(); } Loading @@ -91,7 +88,7 @@ public final class Bundle implements Parcelable, Cloneable { * inside of the Bundle. */ public Bundle(ClassLoader loader) { mMap = new HashMap<String, Object>(); mMap = new ArrayMap<String, Object>(); mClassLoader = loader; } Loading @@ -102,7 +99,7 @@ public final class Bundle implements Parcelable, Cloneable { * @param capacity the initial capacity of the Bundle */ public Bundle(int capacity) { mMap = new HashMap<String, Object>(capacity); mMap = new ArrayMap<String, Object>(capacity); mClassLoader = getClass().getClassLoader(); } Loading @@ -122,7 +119,7 @@ public final class Bundle implements Parcelable, Cloneable { } if (b.mMap != null) { mMap = new HashMap<String, Object>(b.mMap); mMap = new ArrayMap<String, Object>(b.mMap); } else { mMap = null; } Loading Loading @@ -162,7 +159,7 @@ public final class Bundle implements Parcelable, Cloneable { if (size == 0) { return null; } Object o = mMap.values().iterator().next(); Object o = mMap.valueAt(0); try { return (String) o; } catch (ClassCastException e) { Loading Loading @@ -218,9 +215,9 @@ public final class Bundle implements Parcelable, Cloneable { return; } if (mMap == null) { mMap = new HashMap<String, Object>(N); mMap = new ArrayMap<String, Object>(N); } mParcelledData.readMapInternal(mMap, N, mClassLoader); mParcelledData.readArrayMapInternal(mMap, N, mClassLoader); mParcelledData.recycle(); mParcelledData = null; } Loading Loading @@ -331,9 +328,8 @@ public final class Bundle implements Parcelable, Cloneable { } } else { // It's been unparcelled, so we need to walk the map Iterator<Map.Entry<String, Object>> iter = mMap.entrySet().iterator(); while (!fdFound && iter.hasNext()) { Object obj = iter.next().getValue(); for (int i=mMap.size()-1; i>=0; i--) { Object obj = mMap.valueAt(i); if (obj instanceof Parcelable) { if ((((Parcelable)obj).describeContents() & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) { Loading Loading @@ -1643,7 +1639,7 @@ public final class Bundle implements Parcelable, Cloneable { parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' int oldPos = parcel.dataPosition(); parcel.writeMapInternal(mMap); parcel.writeArrayMapInternal(mMap); int newPos = parcel.dataPosition(); // Backpatch length Loading
core/java/android/os/Parcel.java +29 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.os; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import android.util.SparseBooleanArray; Loading Loading @@ -592,6 +593,23 @@ public final class Parcel { } } /** * Flatten an ArrayMap into the parcel at the current dataPosition(), * growing dataCapacity() if needed. The Map keys must be String objects. */ /* package */ void writeArrayMapInternal(ArrayMap<String,Object> val) { if (val == null) { writeInt(-1); return; } final int N = val.size(); writeInt(N); for (int i=0; i<N; i++) { writeValue(val.keyAt(i)); writeValue(val.valueAt(i)); } } /** * Flatten a Bundle into the parcel at the current dataPosition(), * growing dataCapacity() if needed. Loading Loading @@ -2258,6 +2276,16 @@ public final class Parcel { } } /* package */ void readArrayMapInternal(ArrayMap outVal, int N, ClassLoader loader) { while (N > 0) { Object key = readValue(loader); Object value = readValue(loader); outVal.append(key, value); N--; } } private void readListInternal(List outVal, int N, ClassLoader loader) { while (N > 0) { Loading
core/java/android/util/ArrayMap.java +42 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,11 @@ public final class ArrayMap<K, V> implements Map<K, V> { */ private static final int CACHE_SIZE = 10; /** * @hide Special immutable empty ArrayMap. */ public static final ArrayMap EMPTY = new ArrayMap(true); /** * Caches of small array objects to avoid spamming garbage. The cache * Object[] variable is a pointer to a linked list of array objects. Loading @@ -71,6 +76,11 @@ public final class ArrayMap<K, V> implements Map<K, V> { static Object[] mTwiceBaseCache; static int mTwiceBaseCacheSize; /** * Special hash array value that indicates the container is immutable. */ static final int[] EMPTY_IMMUTABLE_INTS = new int[0]; int[] mHashes; Object[] mArray; int mSize; Loading Loading @@ -115,6 +125,9 @@ public final class ArrayMap<K, V> implements Map<K, V> { } private void allocArrays(final int size) { if (mHashes == EMPTY_IMMUTABLE_INTS) { throw new UnsupportedOperationException("ArrayMap is immutable"); } if (size == (BASE_SIZE*2)) { synchronized (ArrayMap.class) { if (mTwiceBaseCache != null) { Loading Loading @@ -204,6 +217,12 @@ public final class ArrayMap<K, V> implements Map<K, V> { mSize = 0; } private ArrayMap(boolean immutable) { mHashes = EMPTY_IMMUTABLE_INTS; mArray = ContainerHelpers.EMPTY_OBJECTS; mSize = 0; } /** * Create a new ArrayMap with the mappings from the given ArrayMap. */ Loading @@ -219,7 +238,7 @@ public final class ArrayMap<K, V> implements Map<K, V> { */ @Override public void clear() { if (mSize != 0) { if (mSize > 0) { freeArrays(mHashes, mArray, mSize); mHashes = ContainerHelpers.EMPTY_INTS; mArray = ContainerHelpers.EMPTY_OBJECTS; Loading Loading @@ -390,6 +409,28 @@ public final class ArrayMap<K, V> implements Map<K, V> { return null; } /** * Special fast path for appending items to the end of the array without validation. * The array must already be large enough to contain the item. * @hide */ public void append(K key, V value) { int index = mSize; final int hash = key.hashCode(); if (index >= mHashes.length) { throw new IllegalStateException("Array is full"); } if (index > 0 && mHashes[index-1] > hash) { throw new IllegalArgumentException("New hash " + hash + " is before end of array hash " + mHashes[index-1]); } mSize = index+1; mHashes[index] = hash; index <<= 1; mArray[index] = key; mArray[index+1] = value; } /** * Perform a {@link #put(Object, Object)} of all key/value pairs in <var>array</var> * @param array The array whose contents are to be retrieved. Loading