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