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