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