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