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