1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
19import android.annotation.Nullable;
20import android.util.ArrayMap;
21import android.util.Size;
22import android.util.SizeF;
23import android.util.SparseArray;
24
25import java.io.Serializable;
26import java.util.ArrayList;
27import java.util.List;
28
29/**
30 * A mapping from String values to various Parcelable types.
31 *
32 */
33public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
34    public static final Bundle EMPTY;
35    static final Parcel EMPTY_PARCEL;
36
37    static {
38        EMPTY = new Bundle();
39        EMPTY.mMap = ArrayMap.EMPTY;
40        EMPTY_PARCEL = BaseBundle.EMPTY_PARCEL;
41    }
42
43    private boolean mHasFds = false;
44    private boolean mFdsKnown = true;
45    private boolean mAllowFds = true;
46
47    /**
48     * Constructs a new, empty Bundle.
49     */
50    public Bundle() {
51        super();
52    }
53
54    /**
55     * Constructs a Bundle whose data is stored as a Parcel.  The data
56     * will be unparcelled on first contact, using the assigned ClassLoader.
57     *
58     * @param parcelledData a Parcel containing a Bundle
59     */
60    Bundle(Parcel parcelledData) {
61        super(parcelledData);
62
63        mHasFds = mParcelledData.hasFileDescriptors();
64        mFdsKnown = true;
65    }
66
67    /* package */ Bundle(Parcel parcelledData, int length) {
68        super(parcelledData, length);
69
70        mHasFds = mParcelledData.hasFileDescriptors();
71        mFdsKnown = true;
72    }
73
74    /**
75     * Constructs a new, empty Bundle that uses a specific ClassLoader for
76     * instantiating Parcelable and Serializable objects.
77     *
78     * @param loader An explicit ClassLoader to use when instantiating objects
79     * inside of the Bundle.
80     */
81    public Bundle(ClassLoader loader) {
82        super(loader);
83    }
84
85    /**
86     * Constructs a new, empty Bundle sized to hold the given number of
87     * elements. The Bundle will grow as needed.
88     *
89     * @param capacity the initial capacity of the Bundle
90     */
91    public Bundle(int capacity) {
92        super(capacity);
93    }
94
95    /**
96     * Constructs a Bundle containing a copy of the mappings from the given
97     * Bundle.
98     *
99     * @param b a Bundle to be copied.
100     */
101    public Bundle(Bundle b) {
102        super(b);
103
104        mHasFds = b.mHasFds;
105        mFdsKnown = b.mFdsKnown;
106    }
107
108    /**
109     * Constructs a Bundle containing a copy of the mappings from the given
110     * PersistableBundle.
111     *
112     * @param b a Bundle to be copied.
113     */
114    public Bundle(PersistableBundle b) {
115        super(b);
116    }
117
118    /**
119     * Make a Bundle for a single key/value pair.
120     *
121     * @hide
122     */
123    public static Bundle forPair(String key, String value) {
124        Bundle b = new Bundle(1);
125        b.putString(key, value);
126        return b;
127    }
128
129    /**
130     * Changes the ClassLoader this Bundle uses when instantiating objects.
131     *
132     * @param loader An explicit ClassLoader to use when instantiating objects
133     * inside of the Bundle.
134     */
135    @Override
136    public void setClassLoader(ClassLoader loader) {
137        super.setClassLoader(loader);
138    }
139
140    /**
141     * Return the ClassLoader currently associated with this Bundle.
142     */
143    @Override
144    public ClassLoader getClassLoader() {
145        return super.getClassLoader();
146    }
147
148    /** @hide */
149    public boolean setAllowFds(boolean allowFds) {
150        boolean orig = mAllowFds;
151        mAllowFds = allowFds;
152        return orig;
153    }
154
155    /**
156     * Clones the current Bundle. The internal map is cloned, but the keys and
157     * values to which it refers are copied by reference.
158     */
159    @Override
160    public Object clone() {
161        return new Bundle(this);
162    }
163
164    /**
165     * Removes all elements from the mapping of this Bundle.
166     */
167    @Override
168    public void clear() {
169        super.clear();
170
171        mHasFds = false;
172        mFdsKnown = true;
173    }
174
175    /**
176     * Inserts all mappings from the given Bundle into this Bundle.
177     *
178     * @param bundle a Bundle
179     */
180    public void putAll(Bundle bundle) {
181        unparcel();
182        bundle.unparcel();
183        mMap.putAll(bundle.mMap);
184
185        // fd state is now known if and only if both bundles already knew
186        mHasFds |= bundle.mHasFds;
187        mFdsKnown = mFdsKnown && bundle.mFdsKnown;
188    }
189
190    /**
191     * Reports whether the bundle contains any parcelled file descriptors.
192     */
193    public boolean hasFileDescriptors() {
194        if (!mFdsKnown) {
195            boolean fdFound = false;    // keep going until we find one or run out of data
196
197            if (mParcelledData != null) {
198                if (mParcelledData.hasFileDescriptors()) {
199                    fdFound = true;
200                }
201            } else {
202                // It's been unparcelled, so we need to walk the map
203                for (int i=mMap.size()-1; i>=0; i--) {
204                    Object obj = mMap.valueAt(i);
205                    if (obj instanceof Parcelable) {
206                        if ((((Parcelable)obj).describeContents()
207                                & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
208                            fdFound = true;
209                            break;
210                        }
211                    } else if (obj instanceof Parcelable[]) {
212                        Parcelable[] array = (Parcelable[]) obj;
213                        for (int n = array.length - 1; n >= 0; n--) {
214                            Parcelable p = array[n];
215                            if (p != null && ((p.describeContents()
216                                    & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
217                                fdFound = true;
218                                break;
219                            }
220                        }
221                    } else if (obj instanceof SparseArray) {
222                        SparseArray<? extends Parcelable> array =
223                                (SparseArray<? extends Parcelable>) obj;
224                        for (int n = array.size() - 1; n >= 0; n--) {
225                            Parcelable p = array.valueAt(n);
226                            if (p != null && (p.describeContents()
227                                    & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
228                                fdFound = true;
229                                break;
230                            }
231                        }
232                    } else if (obj instanceof ArrayList) {
233                        ArrayList array = (ArrayList) obj;
234                        // an ArrayList here might contain either Strings or
235                        // Parcelables; only look inside for Parcelables
236                        if (!array.isEmpty() && (array.get(0) instanceof Parcelable)) {
237                            for (int n = array.size() - 1; n >= 0; n--) {
238                                Parcelable p = (Parcelable) array.get(n);
239                                if (p != null && ((p.describeContents()
240                                        & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
241                                    fdFound = true;
242                                    break;
243                                }
244                            }
245                        }
246                    }
247                }
248            }
249
250            mHasFds = fdFound;
251            mFdsKnown = true;
252        }
253        return mHasFds;
254    }
255
256    /**
257     * Filter values in Bundle to only basic types.
258     * @hide
259     */
260    public void filterValues() {
261        unparcel();
262        if (mMap != null) {
263            for (int i = mMap.size() - 1; i >= 0; i--) {
264                Object value = mMap.valueAt(i);
265                if (PersistableBundle.isValidType(value)) {
266                    continue;
267                }
268                if (value instanceof Bundle) {
269                    ((Bundle)value).filterValues();
270                }
271                if (value.getClass().getName().startsWith("android.")) {
272                    continue;
273                }
274                mMap.removeAt(i);
275            }
276        }
277    }
278
279    /**
280     * Inserts a byte value into the mapping of this Bundle, replacing
281     * any existing value for the given key.
282     *
283     * @param key a String, or null
284     * @param value a byte
285     */
286    @Override
287    public void putByte(@Nullable String key, byte value) {
288        super.putByte(key, value);
289    }
290
291    /**
292     * Inserts a char value into the mapping of this Bundle, replacing
293     * any existing value for the given key.
294     *
295     * @param key a String, or null
296     * @param value a char
297     */
298    @Override
299    public void putChar(@Nullable String key, char value) {
300        super.putChar(key, value);
301    }
302
303    /**
304     * Inserts a short value into the mapping of this Bundle, replacing
305     * any existing value for the given key.
306     *
307     * @param key a String, or null
308     * @param value a short
309     */
310    @Override
311    public void putShort(@Nullable String key, short value) {
312        super.putShort(key, value);
313    }
314
315    /**
316     * Inserts a float value into the mapping of this Bundle, replacing
317     * any existing value for the given key.
318     *
319     * @param key a String, or null
320     * @param value a float
321     */
322    @Override
323    public void putFloat(@Nullable String key, float value) {
324        super.putFloat(key, value);
325    }
326
327    /**
328     * Inserts a CharSequence value into the mapping of this Bundle, replacing
329     * any existing value for the given key.  Either key or value may be null.
330     *
331     * @param key a String, or null
332     * @param value a CharSequence, or null
333     */
334    @Override
335    public void putCharSequence(@Nullable String key, @Nullable CharSequence value) {
336        super.putCharSequence(key, value);
337    }
338
339    /**
340     * Inserts a Parcelable value into the mapping of this Bundle, replacing
341     * any existing value for the given key.  Either key or value may be null.
342     *
343     * @param key a String, or null
344     * @param value a Parcelable object, or null
345     */
346    public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
347        unparcel();
348        mMap.put(key, value);
349        mFdsKnown = false;
350    }
351
352    /**
353     * Inserts a Size value into the mapping of this Bundle, replacing
354     * any existing value for the given key.  Either key or value may be null.
355     *
356     * @param key a String, or null
357     * @param value a Size object, or null
358     */
359    public void putSize(@Nullable String key, @Nullable Size value) {
360        unparcel();
361        mMap.put(key, value);
362    }
363
364    /**
365     * Inserts a SizeF value into the mapping of this Bundle, replacing
366     * any existing value for the given key.  Either key or value may be null.
367     *
368     * @param key a String, or null
369     * @param value a SizeF object, or null
370     */
371    public void putSizeF(@Nullable String key, @Nullable SizeF value) {
372        unparcel();
373        mMap.put(key, value);
374    }
375
376    /**
377     * Inserts an array of Parcelable values into the mapping of this Bundle,
378     * replacing any existing value for the given key.  Either key or value may
379     * be null.
380     *
381     * @param key a String, or null
382     * @param value an array of Parcelable objects, or null
383     */
384    public void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
385        unparcel();
386        mMap.put(key, value);
387        mFdsKnown = false;
388    }
389
390    /**
391     * Inserts a List of Parcelable values into the mapping of this Bundle,
392     * replacing any existing value for the given key.  Either key or value may
393     * be null.
394     *
395     * @param key a String, or null
396     * @param value an ArrayList of Parcelable objects, or null
397     */
398    public void putParcelableArrayList(@Nullable String key,
399            @Nullable ArrayList<? extends Parcelable> value) {
400        unparcel();
401        mMap.put(key, value);
402        mFdsKnown = false;
403    }
404
405    /** {@hide} */
406    public void putParcelableList(String key, List<? extends Parcelable> value) {
407        unparcel();
408        mMap.put(key, value);
409        mFdsKnown = false;
410    }
411
412    /**
413     * Inserts a SparceArray of Parcelable values into the mapping of this
414     * Bundle, replacing any existing value for the given key.  Either key
415     * or value may be null.
416     *
417     * @param key a String, or null
418     * @param value a SparseArray of Parcelable objects, or null
419     */
420    public void putSparseParcelableArray(@Nullable String key,
421            @Nullable SparseArray<? extends Parcelable> value) {
422        unparcel();
423        mMap.put(key, value);
424        mFdsKnown = false;
425    }
426
427    /**
428     * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing
429     * any existing value for the given key.  Either key or value may be null.
430     *
431     * @param key a String, or null
432     * @param value an ArrayList<Integer> object, or null
433     */
434    @Override
435    public void putIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) {
436        super.putIntegerArrayList(key, value);
437    }
438
439    /**
440     * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing
441     * any existing value for the given key.  Either key or value may be null.
442     *
443     * @param key a String, or null
444     * @param value an ArrayList<String> object, or null
445     */
446    @Override
447    public void putStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) {
448        super.putStringArrayList(key, value);
449    }
450
451    /**
452     * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing
453     * any existing value for the given key.  Either key or value may be null.
454     *
455     * @param key a String, or null
456     * @param value an ArrayList<CharSequence> object, or null
457     */
458    @Override
459    public void putCharSequenceArrayList(@Nullable String key,
460            @Nullable ArrayList<CharSequence> value) {
461        super.putCharSequenceArrayList(key, value);
462    }
463
464    /**
465     * Inserts a Serializable value into the mapping of this Bundle, replacing
466     * any existing value for the given key.  Either key or value may be null.
467     *
468     * @param key a String, or null
469     * @param value a Serializable object, or null
470     */
471    @Override
472    public void putSerializable(@Nullable String key, @Nullable Serializable value) {
473        super.putSerializable(key, value);
474    }
475
476    /**
477     * Inserts a byte array value into the mapping of this Bundle, replacing
478     * any existing value for the given key.  Either key or value may be null.
479     *
480     * @param key a String, or null
481     * @param value a byte array object, or null
482     */
483    @Override
484    public void putByteArray(@Nullable String key, @Nullable byte[] value) {
485        super.putByteArray(key, value);
486    }
487
488    /**
489     * Inserts a short array value into the mapping of this Bundle, replacing
490     * any existing value for the given key.  Either key or value may be null.
491     *
492     * @param key a String, or null
493     * @param value a short array object, or null
494     */
495    @Override
496    public void putShortArray(@Nullable String key, @Nullable short[] value) {
497        super.putShortArray(key, value);
498    }
499
500    /**
501     * Inserts a char array value into the mapping of this Bundle, replacing
502     * any existing value for the given key.  Either key or value may be null.
503     *
504     * @param key a String, or null
505     * @param value a char array object, or null
506     */
507    @Override
508    public void putCharArray(@Nullable String key, @Nullable char[] value) {
509        super.putCharArray(key, value);
510    }
511
512    /**
513     * Inserts a float array value into the mapping of this Bundle, replacing
514     * any existing value for the given key.  Either key or value may be null.
515     *
516     * @param key a String, or null
517     * @param value a float array object, or null
518     */
519    @Override
520    public void putFloatArray(@Nullable String key, @Nullable float[] value) {
521        super.putFloatArray(key, value);
522    }
523
524    /**
525     * Inserts a CharSequence array value into the mapping of this Bundle, replacing
526     * any existing value for the given key.  Either key or value may be null.
527     *
528     * @param key a String, or null
529     * @param value a CharSequence array object, or null
530     */
531    @Override
532    public void putCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) {
533        super.putCharSequenceArray(key, value);
534    }
535
536    /**
537     * Inserts a Bundle value into the mapping of this Bundle, replacing
538     * any existing value for the given key.  Either key or value may be null.
539     *
540     * @param key a String, or null
541     * @param value a Bundle object, or null
542     */
543    public void putBundle(@Nullable String key, @Nullable Bundle value) {
544        unparcel();
545        mMap.put(key, value);
546    }
547
548    /**
549     * Inserts an {@link IBinder} value into the mapping of this Bundle, replacing
550     * any existing value for the given key.  Either key or value may be null.
551     *
552     * <p class="note">You should be very careful when using this function.  In many
553     * places where Bundles are used (such as inside of Intent objects), the Bundle
554     * can live longer inside of another process than the process that had originally
555     * created it.  In that case, the IBinder you supply here will become invalid
556     * when your process goes away, and no longer usable, even if a new process is
557     * created for you later on.</p>
558     *
559     * @param key a String, or null
560     * @param value an IBinder object, or null
561     */
562    public void putBinder(@Nullable String key, @Nullable IBinder value) {
563        unparcel();
564        mMap.put(key, value);
565    }
566
567    /**
568     * Inserts an IBinder value into the mapping of this Bundle, replacing
569     * any existing value for the given key.  Either key or value may be null.
570     *
571     * @param key a String, or null
572     * @param value an IBinder object, or null
573     *
574     * @deprecated
575     * @hide This is the old name of the function.
576     */
577    @Deprecated
578    public void putIBinder(@Nullable String key, @Nullable IBinder value) {
579        unparcel();
580        mMap.put(key, value);
581    }
582
583    /**
584     * Returns the value associated with the given key, or (byte) 0 if
585     * no mapping of the desired type exists for the given key.
586     *
587     * @param key a String
588     * @return a byte value
589     */
590    @Override
591    public byte getByte(String key) {
592        return super.getByte(key);
593    }
594
595    /**
596     * Returns the value associated with the given key, or defaultValue if
597     * no mapping of the desired type exists for the given key.
598     *
599     * @param key a String
600     * @param defaultValue Value to return if key does not exist
601     * @return a byte value
602     */
603    @Override
604    public Byte getByte(String key, byte defaultValue) {
605        return super.getByte(key, defaultValue);
606    }
607
608    /**
609     * Returns the value associated with the given key, or (char) 0 if
610     * no mapping of the desired type exists for the given key.
611     *
612     * @param key a String
613     * @return a char value
614     */
615    @Override
616    public char getChar(String key) {
617        return super.getChar(key);
618    }
619
620    /**
621     * Returns the value associated with the given key, or defaultValue if
622     * no mapping of the desired type exists for the given key.
623     *
624     * @param key a String
625     * @param defaultValue Value to return if key does not exist
626     * @return a char value
627     */
628    @Override
629    public char getChar(String key, char defaultValue) {
630        return super.getChar(key, defaultValue);
631    }
632
633    /**
634     * Returns the value associated with the given key, or (short) 0 if
635     * no mapping of the desired type exists for the given key.
636     *
637     * @param key a String
638     * @return a short value
639     */
640    @Override
641    public short getShort(String key) {
642        return super.getShort(key);
643    }
644
645    /**
646     * Returns the value associated with the given key, or defaultValue if
647     * no mapping of the desired type exists for the given key.
648     *
649     * @param key a String
650     * @param defaultValue Value to return if key does not exist
651     * @return a short value
652     */
653    @Override
654    public short getShort(String key, short defaultValue) {
655        return super.getShort(key, defaultValue);
656    }
657
658    /**
659     * Returns the value associated with the given key, or 0.0f if
660     * no mapping of the desired type exists for the given key.
661     *
662     * @param key a String
663     * @return a float value
664     */
665    @Override
666    public float getFloat(String key) {
667        return super.getFloat(key);
668    }
669
670    /**
671     * Returns the value associated with the given key, or defaultValue if
672     * no mapping of the desired type exists for the given key.
673     *
674     * @param key a String
675     * @param defaultValue Value to return if key does not exist
676     * @return a float value
677     */
678    @Override
679    public float getFloat(String key, float defaultValue) {
680        return super.getFloat(key, defaultValue);
681    }
682
683    /**
684     * Returns the value associated with the given key, or null if
685     * no mapping of the desired type exists for the given key or a null
686     * value is explicitly associated with the key.
687     *
688     * @param key a String, or null
689     * @return a CharSequence value, or null
690     */
691    @Override
692    @Nullable
693    public CharSequence getCharSequence(@Nullable String key) {
694        return super.getCharSequence(key);
695    }
696
697    /**
698     * Returns the value associated with the given key, or defaultValue if
699     * no mapping of the desired type exists for the given key or if a null
700     * value is explicitly associatd with the given key.
701     *
702     * @param key a String, or null
703     * @param defaultValue Value to return if key does not exist or if a null
704     *     value is associated with the given key.
705     * @return the CharSequence value associated with the given key, or defaultValue
706     *     if no valid CharSequence object is currently mapped to that key.
707     */
708    @Override
709    public CharSequence getCharSequence(@Nullable String key, CharSequence defaultValue) {
710        return super.getCharSequence(key, defaultValue);
711    }
712
713    /**
714     * Returns the value associated with the given key, or null if
715     * no mapping of the desired type exists for the given key or a null
716     * value is explicitly associated with the key.
717     *
718     * @param key a String, or null
719     * @return a Size value, or null
720     */
721    @Nullable
722    public Size getSize(@Nullable String key) {
723        unparcel();
724        final Object o = mMap.get(key);
725        try {
726            return (Size) o;
727        } catch (ClassCastException e) {
728            typeWarning(key, o, "Size", e);
729            return null;
730        }
731    }
732
733    /**
734     * Returns the value associated with the given key, or null if
735     * no mapping of the desired type exists for the given key or a null
736     * value is explicitly associated with the key.
737     *
738     * @param key a String, or null
739     * @return a Size value, or null
740     */
741    @Nullable
742    public SizeF getSizeF(@Nullable String key) {
743        unparcel();
744        final Object o = mMap.get(key);
745        try {
746            return (SizeF) o;
747        } catch (ClassCastException e) {
748            typeWarning(key, o, "SizeF", e);
749            return null;
750        }
751    }
752
753    /**
754     * Returns the value associated with the given key, or null if
755     * no mapping of the desired type exists for the given key or a null
756     * value is explicitly associated with the key.
757     *
758     * @param key a String, or null
759     * @return a Bundle value, or null
760     */
761    @Nullable
762    public Bundle getBundle(@Nullable String key) {
763        unparcel();
764        Object o = mMap.get(key);
765        if (o == null) {
766            return null;
767        }
768        try {
769            return (Bundle) o;
770        } catch (ClassCastException e) {
771            typeWarning(key, o, "Bundle", e);
772            return null;
773        }
774    }
775
776    /**
777     * Returns the value associated with the given key, or null if
778     * no mapping of the desired type exists for the given key or a null
779     * value is explicitly associated with the key.
780     *
781     * @param key a String, or null
782     * @return a Parcelable value, or null
783     */
784    @Nullable
785    public <T extends Parcelable> T getParcelable(@Nullable String key) {
786        unparcel();
787        Object o = mMap.get(key);
788        if (o == null) {
789            return null;
790        }
791        try {
792            return (T) o;
793        } catch (ClassCastException e) {
794            typeWarning(key, o, "Parcelable", e);
795            return null;
796        }
797    }
798
799    /**
800     * Returns the value associated with the given key, or null if
801     * no mapping of the desired type exists for the given key or a null
802     * value is explicitly associated with the key.
803     *
804     * @param key a String, or null
805     * @return a Parcelable[] value, or null
806     */
807    @Nullable
808    public Parcelable[] getParcelableArray(@Nullable String key) {
809        unparcel();
810        Object o = mMap.get(key);
811        if (o == null) {
812            return null;
813        }
814        try {
815            return (Parcelable[]) o;
816        } catch (ClassCastException e) {
817            typeWarning(key, o, "Parcelable[]", e);
818            return null;
819        }
820    }
821
822    /**
823     * Returns the value associated with the given key, or null if
824     * no mapping of the desired type exists for the given key or a null
825     * value is explicitly associated with the key.
826     *
827     * @param key a String, or null
828     * @return an ArrayList<T> value, or null
829     */
830    @Nullable
831    public <T extends Parcelable> ArrayList<T> getParcelableArrayList(@Nullable String key) {
832        unparcel();
833        Object o = mMap.get(key);
834        if (o == null) {
835            return null;
836        }
837        try {
838            return (ArrayList<T>) o;
839        } catch (ClassCastException e) {
840            typeWarning(key, o, "ArrayList", e);
841            return null;
842        }
843    }
844
845    /**
846     * Returns the value associated with the given key, or null if
847     * no mapping of the desired type exists for the given key or a null
848     * value is explicitly associated with the key.
849     *
850     * @param key a String, or null
851     *
852     * @return a SparseArray of T values, or null
853     */
854    @Nullable
855    public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(@Nullable String key) {
856        unparcel();
857        Object o = mMap.get(key);
858        if (o == null) {
859            return null;
860        }
861        try {
862            return (SparseArray<T>) o;
863        } catch (ClassCastException e) {
864            typeWarning(key, o, "SparseArray", e);
865            return null;
866        }
867    }
868
869    /**
870     * Returns the value associated with the given key, or null if
871     * no mapping of the desired type exists for the given key or a null
872     * value is explicitly associated with the key.
873     *
874     * @param key a String, or null
875     * @return a Serializable value, or null
876     */
877    @Override
878    @Nullable
879    public Serializable getSerializable(@Nullable String key) {
880        return super.getSerializable(key);
881    }
882
883    /**
884     * Returns the value associated with the given key, or null if
885     * no mapping of the desired type exists for the given key or a null
886     * value is explicitly associated with the key.
887     *
888     * @param key a String, or null
889     * @return an ArrayList<String> value, or null
890     */
891    @Override
892    @Nullable
893    public ArrayList<Integer> getIntegerArrayList(@Nullable String key) {
894        return super.getIntegerArrayList(key);
895    }
896
897    /**
898     * Returns the value associated with the given key, or null if
899     * no mapping of the desired type exists for the given key or a null
900     * value is explicitly associated with the key.
901     *
902     * @param key a String, or null
903     * @return an ArrayList<String> value, or null
904     */
905    @Override
906    @Nullable
907    public ArrayList<String> getStringArrayList(@Nullable String key) {
908        return super.getStringArrayList(key);
909    }
910
911    /**
912     * Returns the value associated with the given key, or null if
913     * no mapping of the desired type exists for the given key or a null
914     * value is explicitly associated with the key.
915     *
916     * @param key a String, or null
917     * @return an ArrayList<CharSequence> value, or null
918     */
919    @Override
920    @Nullable
921    public ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) {
922        return super.getCharSequenceArrayList(key);
923    }
924
925    /**
926     * Returns the value associated with the given key, or null if
927     * no mapping of the desired type exists for the given key or a null
928     * value is explicitly associated with the key.
929     *
930     * @param key a String, or null
931     * @return a byte[] value, or null
932     */
933    @Override
934    @Nullable
935    public byte[] getByteArray(@Nullable String key) {
936        return super.getByteArray(key);
937    }
938
939    /**
940     * Returns the value associated with the given key, or null if
941     * no mapping of the desired type exists for the given key or a null
942     * value is explicitly associated with the key.
943     *
944     * @param key a String, or null
945     * @return a short[] value, or null
946     */
947    @Override
948    @Nullable
949    public short[] getShortArray(@Nullable String key) {
950        return super.getShortArray(key);
951    }
952
953    /**
954     * Returns the value associated with the given key, or null if
955     * no mapping of the desired type exists for the given key or a null
956     * value is explicitly associated with the key.
957     *
958     * @param key a String, or null
959     * @return a char[] value, or null
960     */
961    @Override
962    @Nullable
963    public char[] getCharArray(@Nullable String key) {
964        return super.getCharArray(key);
965    }
966
967    /**
968     * Returns the value associated with the given key, or null if
969     * no mapping of the desired type exists for the given key or a null
970     * value is explicitly associated with the key.
971     *
972     * @param key a String, or null
973     * @return a float[] value, or null
974     */
975    @Override
976    @Nullable
977    public float[] getFloatArray(@Nullable String key) {
978        return super.getFloatArray(key);
979    }
980
981    /**
982     * Returns the value associated with the given key, or null if
983     * no mapping of the desired type exists for the given key or a null
984     * value is explicitly associated with the key.
985     *
986     * @param key a String, or null
987     * @return a CharSequence[] value, or null
988     */
989    @Override
990    @Nullable
991    public CharSequence[] getCharSequenceArray(@Nullable String key) {
992        return super.getCharSequenceArray(key);
993    }
994
995    /**
996     * Returns the value associated with the given key, or null if
997     * no mapping of the desired type exists for the given key or a null
998     * value is explicitly associated with the key.
999     *
1000     * @param key a String, or null
1001     * @return an IBinder value, or null
1002     */
1003    @Nullable
1004    public IBinder getBinder(@Nullable String key) {
1005        unparcel();
1006        Object o = mMap.get(key);
1007        if (o == null) {
1008            return null;
1009        }
1010        try {
1011            return (IBinder) o;
1012        } catch (ClassCastException e) {
1013            typeWarning(key, o, "IBinder", e);
1014            return null;
1015        }
1016    }
1017
1018    /**
1019     * Returns the value associated with the given key, or null if
1020     * no mapping of the desired type exists for the given key or a null
1021     * value is explicitly associated with the key.
1022     *
1023     * @param key a String, or null
1024     * @return an IBinder value, or null
1025     *
1026     * @deprecated
1027     * @hide This is the old name of the function.
1028     */
1029    @Deprecated
1030    @Nullable
1031    public IBinder getIBinder(@Nullable String key) {
1032        unparcel();
1033        Object o = mMap.get(key);
1034        if (o == null) {
1035            return null;
1036        }
1037        try {
1038            return (IBinder) o;
1039        } catch (ClassCastException e) {
1040            typeWarning(key, o, "IBinder", e);
1041            return null;
1042        }
1043    }
1044
1045    public static final Parcelable.Creator<Bundle> CREATOR =
1046        new Parcelable.Creator<Bundle>() {
1047        @Override
1048        public Bundle createFromParcel(Parcel in) {
1049            return in.readBundle();
1050        }
1051
1052        @Override
1053        public Bundle[] newArray(int size) {
1054            return new Bundle[size];
1055        }
1056    };
1057
1058    /**
1059     * Report the nature of this Parcelable's contents
1060     */
1061    @Override
1062    public int describeContents() {
1063        int mask = 0;
1064        if (hasFileDescriptors()) {
1065            mask |= Parcelable.CONTENTS_FILE_DESCRIPTOR;
1066        }
1067        return mask;
1068    }
1069
1070    /**
1071     * Writes the Bundle contents to a Parcel, typically in order for
1072     * it to be passed through an IBinder connection.
1073     * @param parcel The parcel to copy this bundle to.
1074     */
1075    @Override
1076    public void writeToParcel(Parcel parcel, int flags) {
1077        final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
1078        try {
1079            super.writeToParcelInner(parcel, flags);
1080        } finally {
1081            parcel.restoreAllowFds(oldAllowFds);
1082        }
1083    }
1084
1085    /**
1086     * Reads the Parcel contents into this Bundle, typically in order for
1087     * it to be passed through an IBinder connection.
1088     * @param parcel The parcel to overwrite this bundle from.
1089     */
1090    public void readFromParcel(Parcel parcel) {
1091        super.readFromParcelInner(parcel);
1092        mHasFds = mParcelledData.hasFileDescriptors();
1093        mFdsKnown = true;
1094    }
1095
1096    @Override
1097    public synchronized String toString() {
1098        if (mParcelledData != null) {
1099            if (mParcelledData == EMPTY_PARCEL) {
1100                return "Bundle[EMPTY_PARCEL]";
1101            } else {
1102                return "Bundle[mParcelledData.dataSize=" +
1103                        mParcelledData.dataSize() + "]";
1104            }
1105        }
1106        return "Bundle[" + mMap.toString() + "]";
1107    }
1108
1109}
1110