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