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