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