Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b87655b3 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Switch Bundle's implementation over to ArrayMap.

That was...  um...  easier than I thought it was going to be.

Change-Id: Id8f2211c1d5f8145e0bb009dca0f62a590f2b860
parent 209bede6
Loading
Loading
Loading
Loading
+13 −17
Original line number Diff line number Diff line
@@ -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
+29 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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.
@@ -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) {
+42 −1
Original line number Diff line number Diff line
@@ -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.
@@ -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;
@@ -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.