Home | History | Annotate | Download | only in shadows
      1 package com.xtremelabs.robolectric.shadows;
      2 
      3 import static com.xtremelabs.robolectric.Robolectric.shadowOf;
      4 
      5 import android.os.Bundle;
      6 import android.os.Parcel;
      7 import android.os.Parcelable;
      8 import android.text.TextUtils;
      9 import android.util.Log;
     10 import android.util.Pair;
     11 
     12 import com.xtremelabs.robolectric.Robolectric;
     13 import com.xtremelabs.robolectric.bytecode.ShadowWrangler;
     14 import com.xtremelabs.robolectric.internal.Implementation;
     15 import com.xtremelabs.robolectric.internal.Implements;
     16 import com.xtremelabs.robolectric.internal.RealObject;
     17 
     18 import java.lang.reflect.Field;
     19 import java.util.ArrayList;
     20 import java.util.HashMap;
     21 import java.util.List;
     22 import java.util.Map;
     23 import java.util.Set;
     24 
     25 @Implements(Parcel.class)
     26 @SuppressWarnings("unchecked")
     27 public class ShadowParcel {
     28 
     29     private static final int VAL_NULL = -1;
     30     private static final int VAL_STRING = 0;
     31     private static final int VAL_INTEGER = 1;
     32     private static final int VAL_MAP = 2;
     33     private static final int VAL_BUNDLE = 3;
     34     private static final int VAL_PARCELABLE = 4;
     35     private static final int VAL_SHORT = 5;
     36     private static final int VAL_LONG = 6;
     37     private static final int VAL_FLOAT = 7;
     38     private static final int VAL_DOUBLE = 8;
     39     private static final int VAL_BOOLEAN = 9;
     40     private static final int VAL_CHARSEQUENCE = 10;
     41     private static final int VAL_BYTEARRAY = 13;
     42     private static final int VAL_STRINGARRAY = 14;
     43     private static final int VAL_OBJECTARRAY = 17;
     44     private static final int VAL_INTARRAY = 18;
     45     private static final int VAL_LONGARRAY = 19;
     46     private static final int VAL_BYTE = 20;
     47     private static final int VAL_BOOLEANARRAY = 23;
     48 
     49     private final ArrayList<Pair<Integer, ?>> parcelData = new ArrayList<Pair<Integer, ?>>();
     50     private int index = 0;
     51 
     52     @RealObject
     53     private Parcel realParcel;
     54 
     55     @Implementation
     56     public static Parcel obtain() {
     57         return Robolectric.newInstanceOf(Parcel.class);
     58     }
     59 
     60     @Implementation
     61     public int dataAvail() {
     62         return dataSize() - dataPosition();
     63     }
     64 
     65     @Implementation
     66     public int dataPosition() {
     67         return calculateSizeToIndex(index);
     68     }
     69 
     70     @Implementation
     71     public int dataSize() {
     72         return calculateSizeToIndex(parcelData.size());
     73     }
     74 
     75     @Implementation
     76     public int dataCapacity() {
     77         return dataSize();
     78     }
     79 
     80     @Implementation
     81     public void setDataPosition(int pos) {
     82         index = calculateIndexFromSizePosition(pos);
     83     }
     84 
     85     private int calculateSizeToIndex(int index) {
     86         int size = 0;
     87         for (int i = 0; i < index; i++) {
     88             size += parcelData.get(i).first;
     89         }
     90         return size;
     91     }
     92 
     93     private int calculateIndexFromSizePosition(int pos) {
     94         int size = 0;
     95         for (int i = 0; i < parcelData.size(); i++) {
     96             if (size >= pos) {
     97                 return i;
     98             }
     99             size += parcelData.get(i).first;
    100         }
    101         return parcelData.size();
    102     }
    103 
    104     @Implementation
    105     public void writeString(String str) {
    106         if (str == null) {
    107             writeInt(-1);
    108         } else {
    109             writeInt(str.length());
    110             addValueToList(Pair.create(str.length(), str));
    111         }
    112     }
    113 
    114     @Implementation
    115     public String readString() {
    116         int N = readInt();
    117         if (N < 0) {
    118             return null;
    119         } else {
    120             return readValueFromList(null);
    121         }
    122     }
    123 
    124     @Implementation
    125     public void writeInt(int i) {
    126         addValueToList(Pair.create(Integer.SIZE / 8, i));
    127     }
    128 
    129     @Implementation
    130     public int readInt() {
    131         return readValueFromList(0);
    132     }
    133 
    134     @Implementation
    135     public void writeLong(long i) {
    136         addValueToList(Pair.create(Long.SIZE / 8, i));
    137     }
    138 
    139     @Implementation
    140     public long readLong() {
    141         return readValueFromList((long) 0);
    142     }
    143 
    144     @Implementation
    145     public void writeFloat(float f) {
    146         addValueToList(Pair.create(Float.SIZE / 8, f));
    147     }
    148 
    149     @Implementation
    150     public float readFloat() {
    151         return readValueFromList((float) 0);
    152     }
    153 
    154     @Implementation
    155     public void writeDouble(double f) {
    156         addValueToList(Pair.create(Double.SIZE / 8, f));
    157     }
    158 
    159     @Implementation
    160     public double readDouble() {
    161         return readValueFromList((double) 0);
    162     }
    163 
    164     public void writeBoolean(boolean b) {
    165         addValueToList(Pair.create(1, b));
    166     }
    167 
    168     public boolean readBoolean() {
    169         return readValueFromList(false);
    170     }
    171 
    172     public void writeChar(char c) {
    173         addValueToList(Pair.create(Character.SIZE / 8, c));
    174     }
    175 
    176     public char readChar() {
    177         return readValueFromList((char) 0);
    178     }
    179 
    180     @Implementation
    181     @SuppressWarnings("unchecked")
    182     public void writeByte(byte b) {
    183         addValueToList(Pair.create(Byte.SIZE / 8, b));
    184     }
    185 
    186     @Implementation
    187     public byte readByte() {
    188         return readValueFromList((byte) 0);
    189     }
    190 
    191     @Implementation
    192     public void readBooleanArray(boolean[] val) {
    193         int N = readInt();
    194         if (val.length != N)
    195             throw new RuntimeException("bad array lengths");
    196         for (int i = 0; i < val.length; i++) {
    197             val[i] = readBoolean();
    198         }
    199     }
    200 
    201     @Implementation
    202     public void writeBooleanArray(boolean[] val) {
    203         if (val == null) {
    204             writeInt(-1);
    205             return;
    206         }
    207         writeInt(val.length);
    208         for (boolean b : val)
    209             writeBoolean(b);
    210     }
    211 
    212     @Implementation
    213     public boolean[] createBooleanArray() {
    214         int N = readInt();
    215         if (N < 0) {
    216             return null;
    217         }
    218         boolean[] val = new boolean[N];
    219         for (int i = 0; i < val.length; i++) {
    220             val[i] = readBoolean();
    221         }
    222         return val;
    223     }
    224 
    225     @Implementation
    226     public void readCharArray(char[] val) {
    227         int N = readInt();
    228         if (val.length != N)
    229             throw new RuntimeException("bad array lengths");
    230         for (int i = 0; i < val.length; i++) {
    231             val[i] = readChar();
    232         }
    233     }
    234 
    235     @Implementation
    236     public void writeCharArray(char[] val) {
    237         if (val == null) {
    238             writeInt(-1);
    239             return;
    240         }
    241         writeInt(val.length);
    242         for (char b : val)
    243             writeChar(b);
    244     }
    245 
    246     @Implementation
    247     public char[] createCharArray() {
    248         int N = readInt();
    249         if (N < 0) {
    250             return null;
    251         }
    252         char[] val = new char[N];
    253         for (int i = 0; i < val.length; i++) {
    254             val[i] = readChar();
    255         }
    256         return val;
    257     }
    258 
    259     @Implementation
    260     public void readFloatArray(float[] val) {
    261         int N = readInt();
    262         if (val.length != N)
    263             throw new RuntimeException("bad array lengths");
    264         for (int i = 0; i < val.length; i++) {
    265             val[i] = readFloat();
    266         }
    267     }
    268 
    269     @Implementation
    270     public void writeFloatArray(float[] val) {
    271         if (val == null) {
    272             writeInt(-1);
    273             return;
    274         }
    275         writeInt(val.length);
    276         for (float f : val)
    277             writeFloat(f);
    278     }
    279 
    280     @Implementation
    281     public float[] createFloatArray() {
    282         int N = readInt();
    283         if (N < 0) {
    284             return null;
    285         }
    286         float[] val = new float[N];
    287         for (int i = 0; i < val.length; i++) {
    288             val[i] = readFloat();
    289         }
    290         return val;
    291     }
    292 
    293     @Implementation
    294     public void writeDoubleArray(double[] val) {
    295         if (val == null) {
    296             writeInt(-1);
    297             return;
    298         }
    299         writeInt(val.length);
    300         for (double f : val)
    301             writeDouble(f);
    302     }
    303 
    304     @Implementation
    305     public void readDoubleArray(double[] val) {
    306         int N = readInt();
    307         if (val.length != N)
    308             throw new RuntimeException("bad array lengths");
    309         for (int i = 0; i < val.length; i++) {
    310             val[i] = readDouble();
    311         }
    312     }
    313 
    314     @Implementation
    315     public double[] createDoubleArray() {
    316         int N = readInt();
    317         if (N < 0) {
    318             return null;
    319         }
    320         double[] val = new double[N];
    321         for (int i = 0; i < val.length; i++) {
    322             val[i] = readDouble();
    323         }
    324         return val;
    325     }
    326 
    327     @Implementation
    328     public void writeIntArray(int[] val) {
    329         if (val == null) {
    330             writeInt(-1);
    331             return;
    332         }
    333         writeInt(val.length);
    334         for (int f : val)
    335             writeInt(f);
    336     }
    337 
    338     @Implementation
    339     public void readIntArray(int[] val) {
    340         int N = readInt();
    341         if (val.length != N)
    342             throw new RuntimeException("bad array lengths");
    343         for (int i = 0; i < val.length; i++) {
    344             val[i] = readInt();
    345         }
    346     }
    347 
    348     @Implementation
    349     public int[] createIntArray() {
    350         int N = readInt();
    351         if (N < 0) {
    352             return null;
    353         }
    354         int[] val = new int[N];
    355         for (int i = 0; i < val.length; i++) {
    356             val[i] = readInt();
    357         }
    358         return val;
    359     }
    360 
    361     @Implementation
    362     public void writeByteArray(byte[] val) {
    363         if (val == null) {
    364             writeInt(-1);
    365             return;
    366         }
    367         writeInt(val.length);
    368         for (byte f : val)
    369             writeByte(f);
    370     }
    371 
    372     @Implementation
    373     public void readByteArray(byte[] val) {
    374         int N = readInt();
    375         if (val.length != N)
    376             throw new RuntimeException("bad array lengths");
    377         for (int i = 0; i < val.length; i++) {
    378             val[i] = readByte();
    379         }
    380     }
    381 
    382     @Implementation
    383     public byte[] createByteArray() {
    384         int N = readInt();
    385         if (N < 0) {
    386             return null;
    387         }
    388         byte[] val = new byte[N];
    389         for (int i = 0; i < val.length; i++) {
    390             val[i] = readByte();
    391         }
    392         return val;
    393     }
    394 
    395     @Implementation
    396     public void writeLongArray(long[] val) {
    397         if (val == null) {
    398             writeInt(-1);
    399             return;
    400         }
    401         writeInt(val.length);
    402         for (long f : val)
    403             writeLong(f);
    404     }
    405 
    406     @Implementation
    407     public void readLongArray(long[] val) {
    408         int N = readInt();
    409         if (val.length != N)
    410             throw new RuntimeException("bad array lengths");
    411         for (int i = 0; i < val.length; i++) {
    412             val[i] = readLong();
    413         }
    414     }
    415 
    416     @Implementation
    417     public long[] createLongArray() {
    418         int N = readInt();
    419         if (N < 0) {
    420             return null;
    421         }
    422         long[] val = new long[N];
    423         for (int i = 0; i < val.length; i++) {
    424             val[i] = readLong();
    425         }
    426         return val;
    427     }
    428 
    429     @Implementation
    430     public void writeStringArray(String[] val) {
    431         if (val == null) {
    432             writeInt(-1);
    433             return;
    434         }
    435         writeInt(val.length);
    436         for (String f : val)
    437             writeString(f);
    438     }
    439 
    440     @Implementation
    441     public String[] createStringArray() {
    442         String[] array = null;
    443 
    444         int N = readInt();
    445         if (N >= 0) {
    446             array = new String[N];
    447             for (int i = 0; i < N; i++) {
    448                 array[i] = readString();
    449             }
    450         }
    451         return array;
    452     }
    453 
    454     @Implementation
    455     public void readStringArray(String[] dest) {
    456         int N = readInt();
    457         if (dest.length != N)
    458             throw new RuntimeException("bad array lengths");
    459         for (int i = 0; i < dest.length; i++) {
    460             dest[i] = readString();
    461         }
    462     }
    463 
    464     @Implementation
    465     public void writeStringList(List<String> strings) {
    466         if (strings == null) {
    467             writeInt(-1);
    468             return;
    469         }
    470         int count = strings.size();
    471         int i = 0;
    472         writeInt(count);
    473         while (i < count) {
    474             writeString(strings.get(i));
    475             i++;
    476         }
    477     }
    478 
    479     @Implementation
    480     public void readStringList(List<String> list) {
    481         int listSizeBeforeChange = list.size();
    482         int addCount = readInt();
    483         int i = 0;
    484         for (; i < listSizeBeforeChange && i < addCount; i++) {
    485             list.set(i, readString());
    486         }
    487         for (; i < addCount; i++) {
    488             list.add(readString());
    489         }
    490         for (; i < listSizeBeforeChange; i++) {
    491             list.remove(addCount);
    492         }
    493     }
    494 
    495     @Implementation
    496     public ArrayList<String> createStringArrayList() {
    497         int N = readInt();
    498         if (N < 0) {
    499             return null;
    500         }
    501 
    502         ArrayList<String> l = new ArrayList<String>(N);
    503         while (N > 0) {
    504             l.add(readString());
    505             N--;
    506         }
    507         return l;
    508     }
    509 
    510     @Implementation
    511     public void writeArray(Object[] values) {
    512         if (values == null) {
    513             writeInt(-1);
    514             return;
    515         }
    516         int N = values.length;
    517         writeInt(N);
    518         for (Object value : values) {
    519             writeValue(value);
    520         }
    521     }
    522 
    523     @Implementation
    524     public Object[] readArray(ClassLoader loader) {
    525         int N = readInt();
    526         if (N < 0) {
    527             return null;
    528         }
    529         Object[] l = new Object[N];
    530         readArrayInternal(l, N, loader);
    531         return l;
    532     }
    533 
    534     @Implementation
    535     public void writeValue(Object v) {
    536         if (v == null) {
    537             writeInt(VAL_NULL);
    538         } else if (v instanceof String) {
    539             writeInt(VAL_STRING);
    540             writeString((String) v);
    541         } else if (v instanceof Integer) {
    542             writeInt(VAL_INTEGER);
    543             writeInt((Integer) v);
    544         } else if (v instanceof Map) {
    545             writeInt(VAL_MAP);
    546             writeMap((Map) v);
    547         } else if (v instanceof Bundle) {
    548             // Must be before Parcelable
    549             writeInt(VAL_BUNDLE);
    550             writeBundle((Bundle) v);
    551         } else if (v instanceof Parcelable) {
    552             writeInt(VAL_PARCELABLE);
    553             writeParcelable((Parcelable) v, 0);
    554         } else if (v instanceof Short) {
    555             writeInt(VAL_SHORT);
    556             writeInt(((Short) v).intValue());
    557         } else if (v instanceof Long) {
    558             writeInt(VAL_LONG);
    559             writeLong((Long) v);
    560         } else if (v instanceof Float) {
    561             writeInt(VAL_FLOAT);
    562             writeFloat((Float) v);
    563         } else if (v instanceof Double) {
    564             writeInt(VAL_DOUBLE);
    565             writeDouble((Double) v);
    566         } else if (v instanceof Boolean) {
    567             writeInt(VAL_BOOLEAN);
    568             writeInt((Boolean) v ? 1 : 0);
    569         } else if (v instanceof CharSequence) {
    570             // Must be after String
    571             writeInt(VAL_CHARSEQUENCE);
    572             TextUtils.writeToParcel((CharSequence) v, realParcel, 0);
    573         } else if (v instanceof boolean[]) {
    574             writeInt(VAL_BOOLEANARRAY);
    575             writeBooleanArray((boolean[]) v);
    576         } else if (v instanceof byte[]) {
    577             writeInt(VAL_BYTEARRAY);
    578             writeByteArray((byte[]) v);
    579         } else if (v instanceof String[]) {
    580             writeInt(VAL_STRINGARRAY);
    581             writeStringArray((String[]) v);
    582         } else if (v instanceof Object[]) {
    583             writeInt(VAL_OBJECTARRAY);
    584             writeArray((Object[]) v);
    585         } else if (v instanceof int[]) {
    586             writeInt(VAL_INTARRAY);
    587             writeIntArray((int[]) v);
    588         } else if (v instanceof long[]) {
    589             writeInt(VAL_LONGARRAY);
    590             writeLongArray((long[]) v);
    591         } else if (v instanceof Byte) {
    592             writeInt(VAL_BYTE);
    593             writeByte((Byte) v);
    594         } else {
    595             throw new RuntimeException(
    596                     "Parcel: unable to marshal value with type" + v.getClass().getName());
    597         }
    598     }
    599 
    600     @Implementation
    601     public Object readValue(ClassLoader loader) {
    602         int type = readInt();
    603 
    604         switch (type) {
    605             case VAL_NULL:
    606                 return null;
    607 
    608             case VAL_STRING:
    609                 return readString();
    610 
    611             case VAL_INTEGER:
    612                 return readInt();
    613 
    614             case VAL_MAP:
    615                 return readHashMap(loader);
    616 
    617             case VAL_PARCELABLE:
    618                 return readParcelable(loader);
    619 
    620             case VAL_SHORT:
    621                 return (short) readInt();
    622 
    623             case VAL_LONG:
    624                 return readLong();
    625 
    626             case VAL_FLOAT:
    627                 return readFloat();
    628 
    629             case VAL_DOUBLE:
    630                 return readDouble();
    631 
    632             case VAL_BOOLEAN:
    633                 return readInt() == 1;
    634 
    635             case VAL_CHARSEQUENCE:
    636                 return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(realParcel);
    637 
    638             case VAL_BOOLEANARRAY:
    639                 return createBooleanArray();
    640 
    641             case VAL_BYTEARRAY:
    642                 return createByteArray();
    643 
    644             case VAL_STRINGARRAY:
    645                 return createStringArray();
    646 
    647             case VAL_OBJECTARRAY:
    648                 return readArray(loader);
    649 
    650             case VAL_INTARRAY:
    651                 return createIntArray();
    652 
    653             case VAL_LONGARRAY:
    654                 return createLongArray();
    655 
    656             case VAL_BYTE:
    657                 return readByte();
    658 
    659             case VAL_BUNDLE:
    660                 return readBundle(loader); // loading will be deferred
    661 
    662             default:
    663                 int off = dataPosition() - 4;
    664                 throw new RuntimeException(
    665                         "Parcel " + this + ": Unmarshalling unknown type code " + type
    666                         + " at offset " + off);
    667         }
    668     }
    669 
    670     @Implementation
    671     public Bundle readBundle() {
    672         return readBundle(null);
    673     }
    674 
    675     @Implementation
    676     public Bundle readBundle(ClassLoader loader) {
    677         int offset = dataPosition();
    678         int N = readInt();
    679         if (N < 0) {
    680             return null;
    681         }
    682         int magic = readInt();
    683         if (magic != 0x4C444E42) {
    684             throw new RuntimeException("Magic number missing from bundle stream");
    685         }
    686 
    687         Bundle bundle = new Bundle();
    688 
    689         // Read map
    690         HashMap m = new HashMap();
    691         readMap(m, null);
    692 
    693         shadowOf(bundle).map.putAll(m);
    694 
    695         return bundle;
    696     }
    697 
    698     @Implementation
    699     public void writeBundle(Bundle val) {
    700         if (val == null) {
    701             writeInt(-1);
    702             return;
    703         }
    704 
    705         writeInt(-1); // dummy, will hold length
    706         int oldPos = dataPosition();
    707         writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
    708 
    709         writeMapInternal(shadowOf(val).map);
    710         int newPos = dataPosition();
    711 
    712         // Backpatch length
    713         setDataPosition(oldPos - 4);
    714         int N = newPos - oldPos;
    715         writeInt(N);
    716         setDataPosition(newPos);
    717     }
    718 
    719     @Implementation
    720     public void writeParcelable(Parcelable p, int flags) {
    721         if (p == null) {
    722             writeString(null);
    723             return;
    724         }
    725         String name = p.getClass().getName();
    726         writeString(name);
    727         p.writeToParcel(realParcel, flags);
    728     }
    729 
    730     @Implementation
    731     public <T extends Parcelable> T readParcelable(ClassLoader loader) {
    732         String name = readString();
    733         if (name == null) {
    734             return null;
    735         }
    736         Parcelable.Creator<T> creator;
    737         try {
    738             Class c = loader == null ? Class.forName(name) : Class.forName(name, true, loader);
    739 
    740             // Use CREATOR from Shadow for Robolectric mocked classes.
    741             Class shadowClass = ShadowWrangler.getInstance().findShadowClass(c, loader);
    742             if (shadowClass != null) {
    743                 c = shadowClass;
    744                 name = shadowClass.getName();
    745             }
    746 
    747             Field f = c.getField("CREATOR");
    748             creator = (Parcelable.Creator) f.get(null);
    749         } catch (IllegalAccessException e) {
    750             Log.e("Parcel", "Class not found when unmarshalling: " + name + ", e: " + e);
    751             throw new RuntimeException("IllegalAccessException when unmarshalling: " + name);
    752         } catch (ClassNotFoundException e) {
    753             Log.e("Parcel", "Class not found when unmarshalling: " + name + ", e: " + e);
    754             throw new RuntimeException("ClassNotFoundException when unmarshalling: " + name);
    755         } catch (ClassCastException e) {
    756             throw new RuntimeException("Parcelable protocol requires a "
    757                     + "Parcelable.Creator object called " + " CREATOR on class " + name);
    758         } catch (NoSuchFieldException e) {
    759             throw new RuntimeException("Parcelable protocol requires a "
    760                     + "Parcelable.Creator object called " + " CREATOR on class " + name);
    761         }
    762         if (creator == null) {
    763             throw new RuntimeException("Parcelable protocol requires a "
    764                     + "Parcelable.Creator object called " + " CREATOR on class " + name);
    765         }
    766 
    767         return creator.createFromParcel(realParcel);
    768     }
    769 
    770     @Implementation
    771     public ArrayList createTypedArrayList(Parcelable.Creator c) {
    772         int N = readInt();
    773         if (N < 0) {
    774             return null;
    775         }
    776 
    777         ArrayList l = new ArrayList(N);
    778 
    779         while (N > 0) {
    780             if (readInt() != 0) {
    781                 l.add(c.createFromParcel(realParcel));
    782             } else {
    783                 l.add(null);
    784             }
    785             N--;
    786         }
    787         return l;
    788     }
    789 
    790     @Implementation
    791     public void writeTypedList(List val) {
    792         if (val == null) {
    793             writeInt(-1);
    794             return;
    795         }
    796 
    797         int N = val.size();
    798         int i = 0;
    799         writeInt(N);
    800         while (i < N) {
    801             Object item = val.get(i);
    802             if (item != null) {
    803                 writeInt(1);
    804                 ((Parcelable) item).writeToParcel(realParcel, 0);
    805             } else {
    806                 writeInt(0);
    807             }
    808             i++;
    809         }
    810     }
    811 
    812     @Implementation
    813     public void writeMap(Map val) {
    814         writeMapInternal(val);
    815     }
    816 
    817     @Implementation
    818     public void readMap(Map outVal, ClassLoader loader) {
    819         int N = readInt();
    820         readMapInternal(outVal, N, loader);
    821     }
    822 
    823     @Implementation
    824     public HashMap readHashMap(ClassLoader loader) {
    825         int N = readInt();
    826         if (N < 0) {
    827             return null;
    828         }
    829         HashMap m = new HashMap(N);
    830         readMapInternal(m, N, loader);
    831         return m;
    832     }
    833 
    834     private void writeMapInternal(Map<String, Object> val) {
    835         if (val == null) {
    836             writeInt(-1);
    837             return;
    838         }
    839 
    840         Set<Map.Entry<String, Object>> entries = val.entrySet();
    841         writeInt(entries.size());
    842         for (Map.Entry<String, Object> e : entries) {
    843             writeValue(e.getKey());
    844             writeValue(e.getValue());
    845         }
    846     }
    847 
    848     private void readMapInternal(Map outVal, int N, ClassLoader loader) {
    849         for (int i = 0; i < N; i++) {
    850             Object key = readValue(loader);
    851             Object value = readValue(loader);
    852             outVal.put(key, value);
    853         }
    854     }
    855 
    856     private void readArrayInternal(Object[] outVal, int N, ClassLoader loader) {
    857         for (int i = 0; i < N; i++) {
    858             Object value = readValue(loader);
    859             // Log.d("Parcel", "Unmarshalling value=" + value);
    860             outVal[i] = value;
    861         }
    862     }
    863 
    864     private void addValueToList(Pair<Integer, ?> value) {
    865         if (index < parcelData.size()) {
    866             parcelData.set(index, value);
    867         } else {
    868             parcelData.add(value);
    869         }
    870         index++;
    871     }
    872 
    873     private <T extends Object> T readValueFromList(T defaultValue) {
    874         if (index < parcelData.size()) {
    875             return (T) parcelData.get(index++).second;
    876         } else {
    877             return defaultValue;
    878         }
    879     }
    880 
    881     public int getIndex() {
    882         return index;
    883     }
    884 
    885     public List getParcelData() {
    886         return parcelData;
    887     }
    888 }
    889