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