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