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