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