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