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