summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/os/Bundle.java30
-rw-r--r--core/java/android/os/Parcel.java30
-rw-r--r--core/java/android/util/ArrayMap.java43
3 files changed, 84 insertions, 19 deletions
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index b8769b4..2b0ae3a 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -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;
/**
@@ -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
@@ -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();
}
@@ -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;
}
@@ -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();
}
@@ -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;
}
@@ -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) {
@@ -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;
}
@@ -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) {
@@ -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
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 0916ea9..12f7915 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -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;
@@ -572,7 +573,7 @@ public final class Parcel {
* allows you to avoid mysterious type errors at the point of marshalling.
*/
public final void writeMap(Map val) {
- writeMapInternal((Map<String,Object>) val);
+ writeMapInternal((Map<String, Object>) val);
}
/**
@@ -593,6 +594,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.
*/
@@ -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) {
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index b80a14b..51014c8 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -61,6 +61,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.
* The first entry in the array is a pointer to the next array in the
@@ -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;
@@ -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) {
@@ -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.
*/
@@ -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;
@@ -391,6 +410,28 @@ public final class ArrayMap<K, V> implements Map<K, V> {
}
/**
+ * 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.
*/