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     /**
439      * Inserts a byte value into the mapping of this Bundle, replacing
440      * any existing value for the given key.
441      *
442      * @param key a String, or null
443      * @param value a byte
444      */
445     @Override
putByte(@ullable String key, byte value)446     public void putByte(@Nullable String key, byte value) {
447         super.putByte(key, value);
448     }
449 
450     /**
451      * Inserts a char value into the mapping of this Bundle, replacing
452      * any existing value for the given key.
453      *
454      * @param key a String, or null
455      * @param value a char
456      */
457     @Override
putChar(@ullable String key, char value)458     public void putChar(@Nullable String key, char value) {
459         super.putChar(key, value);
460     }
461 
462     /**
463      * Inserts a short value into the mapping of this Bundle, replacing
464      * any existing value for the given key.
465      *
466      * @param key a String, or null
467      * @param value a short
468      */
469     @Override
putShort(@ullable String key, short value)470     public void putShort(@Nullable String key, short value) {
471         super.putShort(key, value);
472     }
473 
474     /**
475      * Inserts a float value into the mapping of this Bundle, replacing
476      * any existing value for the given key.
477      *
478      * @param key a String, or null
479      * @param value a float
480      */
481     @Override
putFloat(@ullable String key, float value)482     public void putFloat(@Nullable String key, float value) {
483         super.putFloat(key, value);
484     }
485 
486     /**
487      * Inserts a CharSequence value into the mapping of this Bundle, replacing
488      * any existing value for the given key.  Either key or value may be null.
489      *
490      * @param key a String, or null
491      * @param value a CharSequence, or null
492      */
493     @Override
putCharSequence(@ullable String key, @Nullable CharSequence value)494     public void putCharSequence(@Nullable String key, @Nullable CharSequence value) {
495         super.putCharSequence(key, value);
496     }
497 
498     /**
499      * Inserts a Parcelable value into the mapping of this Bundle, replacing
500      * any existing value for the given key.  Either key or value may be null.
501      *
502      * @param key a String, or null
503      * @param value a Parcelable object, or null
504      */
putParcelable(@ullable String key, @Nullable Parcelable value)505     public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
506         unparcel();
507         mMap.put(key, value);
508         mFlags &= ~FLAG_HAS_FDS_KNOWN;
509     }
510 
511     /**
512      * Inserts a Size value into the mapping of this Bundle, replacing
513      * any existing value for the given key.  Either key or value may be null.
514      *
515      * @param key a String, or null
516      * @param value a Size object, or null
517      */
putSize(@ullable String key, @Nullable Size value)518     public void putSize(@Nullable String key, @Nullable Size value) {
519         unparcel();
520         mMap.put(key, value);
521     }
522 
523     /**
524      * Inserts a SizeF value into the mapping of this Bundle, replacing
525      * any existing value for the given key.  Either key or value may be null.
526      *
527      * @param key a String, or null
528      * @param value a SizeF object, or null
529      */
putSizeF(@ullable String key, @Nullable SizeF value)530     public void putSizeF(@Nullable String key, @Nullable SizeF value) {
531         unparcel();
532         mMap.put(key, value);
533     }
534 
535     /**
536      * Inserts an array of Parcelable values into the mapping of this Bundle,
537      * replacing any existing value for the given key.  Either key or value may
538      * be null.
539      *
540      * @param key a String, or null
541      * @param value an array of Parcelable objects, or null
542      */
putParcelableArray(@ullable String key, @Nullable Parcelable[] value)543     public void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
544         unparcel();
545         mMap.put(key, value);
546         mFlags &= ~FLAG_HAS_FDS_KNOWN;
547     }
548 
549     /**
550      * Inserts a List of Parcelable values into the mapping of this Bundle,
551      * replacing any existing value for the given key.  Either key or value may
552      * be null.
553      *
554      * @param key a String, or null
555      * @param value an ArrayList of Parcelable objects, or null
556      */
putParcelableArrayList(@ullable String key, @Nullable ArrayList<? extends Parcelable> value)557     public void putParcelableArrayList(@Nullable String key,
558             @Nullable ArrayList<? extends Parcelable> value) {
559         unparcel();
560         mMap.put(key, value);
561         mFlags &= ~FLAG_HAS_FDS_KNOWN;
562     }
563 
564     /** {@hide} */
565     @UnsupportedAppUsage
putParcelableList(String key, List<? extends Parcelable> value)566     public void putParcelableList(String key, List<? extends Parcelable> value) {
567         unparcel();
568         mMap.put(key, value);
569         mFlags &= ~FLAG_HAS_FDS_KNOWN;
570     }
571 
572     /**
573      * Inserts a SparceArray of Parcelable values into the mapping of this
574      * Bundle, replacing any existing value for the given key.  Either key
575      * or value may be null.
576      *
577      * @param key a String, or null
578      * @param value a SparseArray of Parcelable objects, or null
579      */
putSparseParcelableArray(@ullable String key, @Nullable SparseArray<? extends Parcelable> value)580     public void putSparseParcelableArray(@Nullable String key,
581             @Nullable SparseArray<? extends Parcelable> value) {
582         unparcel();
583         mMap.put(key, value);
584         mFlags &= ~FLAG_HAS_FDS_KNOWN;
585     }
586 
587     /**
588      * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing
589      * any existing value for the given key.  Either key or value may be null.
590      *
591      * @param key a String, or null
592      * @param value an ArrayList<Integer> object, or null
593      */
594     @Override
putIntegerArrayList(@ullable String key, @Nullable ArrayList<Integer> value)595     public void putIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) {
596         super.putIntegerArrayList(key, value);
597     }
598 
599     /**
600      * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing
601      * any existing value for the given key.  Either key or value may be null.
602      *
603      * @param key a String, or null
604      * @param value an ArrayList<String> object, or null
605      */
606     @Override
putStringArrayList(@ullable String key, @Nullable ArrayList<String> value)607     public void putStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) {
608         super.putStringArrayList(key, value);
609     }
610 
611     /**
612      * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing
613      * any existing value for the given key.  Either key or value may be null.
614      *
615      * @param key a String, or null
616      * @param value an ArrayList<CharSequence> object, or null
617      */
618     @Override
putCharSequenceArrayList(@ullable String key, @Nullable ArrayList<CharSequence> value)619     public void putCharSequenceArrayList(@Nullable String key,
620             @Nullable ArrayList<CharSequence> value) {
621         super.putCharSequenceArrayList(key, value);
622     }
623 
624     /**
625      * Inserts a Serializable value into the mapping of this Bundle, replacing
626      * any existing value for the given key.  Either key or value may be null.
627      *
628      * @param key a String, or null
629      * @param value a Serializable object, or null
630      */
631     @Override
putSerializable(@ullable String key, @Nullable Serializable value)632     public void putSerializable(@Nullable String key, @Nullable Serializable value) {
633         super.putSerializable(key, value);
634     }
635 
636     /**
637      * Inserts a byte array value into the mapping of this Bundle, replacing
638      * any existing value for the given key.  Either key or value may be null.
639      *
640      * @param key a String, or null
641      * @param value a byte array object, or null
642      */
643     @Override
putByteArray(@ullable String key, @Nullable byte[] value)644     public void putByteArray(@Nullable String key, @Nullable byte[] value) {
645         super.putByteArray(key, value);
646     }
647 
648     /**
649      * Inserts a short array value into the mapping of this Bundle, replacing
650      * any existing value for the given key.  Either key or value may be null.
651      *
652      * @param key a String, or null
653      * @param value a short array object, or null
654      */
655     @Override
putShortArray(@ullable String key, @Nullable short[] value)656     public void putShortArray(@Nullable String key, @Nullable short[] value) {
657         super.putShortArray(key, value);
658     }
659 
660     /**
661      * Inserts a char array value into the mapping of this Bundle, replacing
662      * any existing value for the given key.  Either key or value may be null.
663      *
664      * @param key a String, or null
665      * @param value a char array object, or null
666      */
667     @Override
putCharArray(@ullable String key, @Nullable char[] value)668     public void putCharArray(@Nullable String key, @Nullable char[] value) {
669         super.putCharArray(key, value);
670     }
671 
672     /**
673      * Inserts a float array value into the mapping of this Bundle, replacing
674      * any existing value for the given key.  Either key or value may be null.
675      *
676      * @param key a String, or null
677      * @param value a float array object, or null
678      */
679     @Override
putFloatArray(@ullable String key, @Nullable float[] value)680     public void putFloatArray(@Nullable String key, @Nullable float[] value) {
681         super.putFloatArray(key, value);
682     }
683 
684     /**
685      * Inserts a CharSequence array value into the mapping of this Bundle, replacing
686      * any existing value for the given key.  Either key or value may be null.
687      *
688      * @param key a String, or null
689      * @param value a CharSequence array object, or null
690      */
691     @Override
putCharSequenceArray(@ullable String key, @Nullable CharSequence[] value)692     public void putCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) {
693         super.putCharSequenceArray(key, value);
694     }
695 
696     /**
697      * Inserts a Bundle value into the mapping of this Bundle, replacing
698      * any existing value for the given key.  Either key or value may be null.
699      *
700      * @param key a String, or null
701      * @param value a Bundle object, or null
702      */
putBundle(@ullable String key, @Nullable Bundle value)703     public void putBundle(@Nullable String key, @Nullable Bundle value) {
704         unparcel();
705         mMap.put(key, value);
706     }
707 
708     /**
709      * Inserts an {@link IBinder} value into the mapping of this Bundle, replacing
710      * any existing value for the given key.  Either key or value may be null.
711      *
712      * <p class="note">You should be very careful when using this function.  In many
713      * places where Bundles are used (such as inside of Intent objects), the Bundle
714      * can live longer inside of another process than the process that had originally
715      * created it.  In that case, the IBinder you supply here will become invalid
716      * when your process goes away, and no longer usable, even if a new process is
717      * created for you later on.</p>
718      *
719      * @param key a String, or null
720      * @param value an IBinder object, or null
721      */
putBinder(@ullable String key, @Nullable IBinder value)722     public void putBinder(@Nullable String key, @Nullable IBinder value) {
723         unparcel();
724         mMap.put(key, value);
725     }
726 
727     /**
728      * Inserts an IBinder value into the mapping of this Bundle, replacing
729      * any existing value for the given key.  Either key or value may be null.
730      *
731      * @param key a String, or null
732      * @param value an IBinder object, or null
733      *
734      * @deprecated
735      * @hide This is the old name of the function.
736      */
737     @UnsupportedAppUsage
738     @Deprecated
putIBinder(@ullable String key, @Nullable IBinder value)739     public void putIBinder(@Nullable String key, @Nullable IBinder value) {
740         unparcel();
741         mMap.put(key, value);
742     }
743 
744     /**
745      * Returns the value associated with the given key, or (byte) 0 if
746      * no mapping of the desired type exists for the given key.
747      *
748      * @param key a String
749      * @return a byte value
750      */
751     @Override
getByte(String key)752     public byte getByte(String key) {
753         return super.getByte(key);
754     }
755 
756     /**
757      * Returns the value associated with the given key, or defaultValue if
758      * no mapping of the desired type exists for the given key.
759      *
760      * @param key a String
761      * @param defaultValue Value to return if key does not exist
762      * @return a byte value
763      */
764     @Override
getByte(String key, byte defaultValue)765     public Byte getByte(String key, byte defaultValue) {
766         return super.getByte(key, defaultValue);
767     }
768 
769     /**
770      * Returns the value associated with the given key, or (char) 0 if
771      * no mapping of the desired type exists for the given key.
772      *
773      * @param key a String
774      * @return a char value
775      */
776     @Override
getChar(String key)777     public char getChar(String key) {
778         return super.getChar(key);
779     }
780 
781     /**
782      * Returns the value associated with the given key, or defaultValue if
783      * no mapping of the desired type exists for the given key.
784      *
785      * @param key a String
786      * @param defaultValue Value to return if key does not exist
787      * @return a char value
788      */
789     @Override
getChar(String key, char defaultValue)790     public char getChar(String key, char defaultValue) {
791         return super.getChar(key, defaultValue);
792     }
793 
794     /**
795      * Returns the value associated with the given key, or (short) 0 if
796      * no mapping of the desired type exists for the given key.
797      *
798      * @param key a String
799      * @return a short value
800      */
801     @Override
getShort(String key)802     public short getShort(String key) {
803         return super.getShort(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 short value
813      */
814     @Override
getShort(String key, short defaultValue)815     public short getShort(String key, short defaultValue) {
816         return super.getShort(key, defaultValue);
817     }
818 
819     /**
820      * Returns the value associated with the given key, or 0.0f if
821      * no mapping of the desired type exists for the given key.
822      *
823      * @param key a String
824      * @return a float value
825      */
826     @Override
getFloat(String key)827     public float getFloat(String key) {
828         return super.getFloat(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 float value
838      */
839     @Override
getFloat(String key, float defaultValue)840     public float getFloat(String key, float defaultValue) {
841         return super.getFloat(key, defaultValue);
842     }
843 
844     /**
845      * Returns the value associated with the given key, or null if
846      * no mapping of the desired type exists for the given key or a null
847      * value is explicitly associated with the key.
848      *
849      * @param key a String, or null
850      * @return a CharSequence value, or null
851      */
852     @Override
853     @Nullable
getCharSequence(@ullable String key)854     public CharSequence getCharSequence(@Nullable String key) {
855         return super.getCharSequence(key);
856     }
857 
858     /**
859      * Returns the value associated with the given key, or defaultValue if
860      * no mapping of the desired type exists for the given key or if a null
861      * value is explicitly associatd with the given key.
862      *
863      * @param key a String, or null
864      * @param defaultValue Value to return if key does not exist or if a null
865      *     value is associated with the given key.
866      * @return the CharSequence value associated with the given key, or defaultValue
867      *     if no valid CharSequence object is currently mapped to that key.
868      */
869     @Override
getCharSequence(@ullable String key, CharSequence defaultValue)870     public CharSequence getCharSequence(@Nullable String key, CharSequence defaultValue) {
871         return super.getCharSequence(key, defaultValue);
872     }
873 
874     /**
875      * Returns the value associated with the given key, or null if
876      * no mapping of the desired type exists for the given key or a null
877      * value is explicitly associated with the key.
878      *
879      * @param key a String, or null
880      * @return a Size value, or null
881      */
882     @Nullable
getSize(@ullable String key)883     public Size getSize(@Nullable String key) {
884         unparcel();
885         final Object o = mMap.get(key);
886         try {
887             return (Size) o;
888         } catch (ClassCastException e) {
889             typeWarning(key, o, "Size", e);
890             return null;
891         }
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 Size value, or null
901      */
902     @Nullable
getSizeF(@ullable String key)903     public SizeF getSizeF(@Nullable String key) {
904         unparcel();
905         final Object o = mMap.get(key);
906         try {
907             return (SizeF) o;
908         } catch (ClassCastException e) {
909             typeWarning(key, o, "SizeF", e);
910             return null;
911         }
912     }
913 
914     /**
915      * Returns the value associated with the given key, or null if
916      * no mapping of the desired type exists for the given key or a null
917      * value is explicitly associated with the key.
918      *
919      * @param key a String, or null
920      * @return a Bundle value, or null
921      */
922     @Nullable
getBundle(@ullable String key)923     public Bundle getBundle(@Nullable String key) {
924         unparcel();
925         Object o = mMap.get(key);
926         if (o == null) {
927             return null;
928         }
929         try {
930             return (Bundle) o;
931         } catch (ClassCastException e) {
932             typeWarning(key, o, "Bundle", e);
933             return null;
934         }
935     }
936 
937     /**
938      * Returns the value associated with the given key, or {@code null} if
939      * no mapping of the desired type exists for the given key or a {@code null}
940      * value is explicitly associated with the key.
941      *
942      * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
943      * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
944      * Otherwise, this method might throw an exception or return {@code null}.
945      *
946      * @param key a String, or {@code null}
947      * @return a Parcelable value, or {@code null}
948      */
949     @Nullable
getParcelable(@ullable String key)950     public <T extends Parcelable> T getParcelable(@Nullable String key) {
951         unparcel();
952         Object o = mMap.get(key);
953         if (o == null) {
954             return null;
955         }
956         try {
957             return (T) o;
958         } catch (ClassCastException e) {
959             typeWarning(key, o, "Parcelable", e);
960             return null;
961         }
962     }
963 
964     /**
965      * Returns the value associated with the given key, or {@code 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      * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
970      * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
971      * Otherwise, this method might throw an exception or return {@code null}.
972      *
973      * @param key a String, or {@code null}
974      * @return a Parcelable[] value, or {@code null}
975      */
976     @Nullable
getParcelableArray(@ullable String key)977     public Parcelable[] getParcelableArray(@Nullable String key) {
978         unparcel();
979         Object o = mMap.get(key);
980         if (o == null) {
981             return null;
982         }
983         try {
984             return (Parcelable[]) o;
985         } catch (ClassCastException e) {
986             typeWarning(key, o, "Parcelable[]", e);
987             return null;
988         }
989     }
990 
991     /**
992      * Returns the value associated with the given key, or {@code null} if
993      * no mapping of the desired type exists for the given key or a {@code null}
994      * value is explicitly associated with the key.
995      *
996      * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
997      * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
998      * Otherwise, this method might throw an exception or return {@code null}.
999      *
1000      * @param key a String, or {@code null}
1001      * @return an ArrayList<T> value, or {@code null}
1002      */
1003     @Nullable
getParcelableArrayList(@ullable String key)1004     public <T extends Parcelable> ArrayList<T> getParcelableArrayList(@Nullable String key) {
1005         unparcel();
1006         Object o = mMap.get(key);
1007         if (o == null) {
1008             return null;
1009         }
1010         try {
1011             return (ArrayList<T>) o;
1012         } catch (ClassCastException e) {
1013             typeWarning(key, o, "ArrayList", e);
1014             return null;
1015         }
1016     }
1017 
1018     /**
1019      * Returns the value associated with the given key, or null if
1020      * no mapping of the desired type exists for the given key or a null
1021      * value is explicitly associated with the key.
1022      *
1023      * @param key a String, or null
1024      *
1025      * @return a SparseArray of T values, or null
1026      */
1027     @Nullable
getSparseParcelableArray(@ullable String key)1028     public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(@Nullable String key) {
1029         unparcel();
1030         Object o = mMap.get(key);
1031         if (o == null) {
1032             return null;
1033         }
1034         try {
1035             return (SparseArray<T>) o;
1036         } catch (ClassCastException e) {
1037             typeWarning(key, o, "SparseArray", e);
1038             return null;
1039         }
1040     }
1041 
1042     /**
1043      * Returns the value associated with the given key, or null if
1044      * no mapping of the desired type exists for the given key or a null
1045      * value is explicitly associated with the key.
1046      *
1047      * @param key a String, or null
1048      * @return a Serializable value, or null
1049      */
1050     @Override
1051     @Nullable
getSerializable(@ullable String key)1052     public Serializable getSerializable(@Nullable String key) {
1053         return super.getSerializable(key);
1054     }
1055 
1056     /**
1057      * Returns the value associated with the given key, or null if
1058      * no mapping of the desired type exists for the given key or a null
1059      * value is explicitly associated with the key.
1060      *
1061      * @param key a String, or null
1062      * @return an ArrayList<String> value, or null
1063      */
1064     @Override
1065     @Nullable
getIntegerArrayList(@ullable String key)1066     public ArrayList<Integer> getIntegerArrayList(@Nullable String key) {
1067         return super.getIntegerArrayList(key);
1068     }
1069 
1070     /**
1071      * Returns the value associated with the given key, or null if
1072      * no mapping of the desired type exists for the given key or a null
1073      * value is explicitly associated with the key.
1074      *
1075      * @param key a String, or null
1076      * @return an ArrayList<String> value, or null
1077      */
1078     @Override
1079     @Nullable
getStringArrayList(@ullable String key)1080     public ArrayList<String> getStringArrayList(@Nullable String key) {
1081         return super.getStringArrayList(key);
1082     }
1083 
1084     /**
1085      * Returns the value associated with the given key, or null if
1086      * no mapping of the desired type exists for the given key or a null
1087      * value is explicitly associated with the key.
1088      *
1089      * @param key a String, or null
1090      * @return an ArrayList<CharSequence> value, or null
1091      */
1092     @Override
1093     @Nullable
getCharSequenceArrayList(@ullable String key)1094     public ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) {
1095         return super.getCharSequenceArrayList(key);
1096     }
1097 
1098     /**
1099      * Returns the value associated with the given key, or null if
1100      * no mapping of the desired type exists for the given key or a null
1101      * value is explicitly associated with the key.
1102      *
1103      * @param key a String, or null
1104      * @return a byte[] value, or null
1105      */
1106     @Override
1107     @Nullable
getByteArray(@ullable String key)1108     public byte[] getByteArray(@Nullable String key) {
1109         return super.getByteArray(key);
1110     }
1111 
1112     /**
1113      * Returns the value associated with the given key, or null if
1114      * no mapping of the desired type exists for the given key or a null
1115      * value is explicitly associated with the key.
1116      *
1117      * @param key a String, or null
1118      * @return a short[] value, or null
1119      */
1120     @Override
1121     @Nullable
getShortArray(@ullable String key)1122     public short[] getShortArray(@Nullable String key) {
1123         return super.getShortArray(key);
1124     }
1125 
1126     /**
1127      * Returns the value associated with the given key, or null if
1128      * no mapping of the desired type exists for the given key or a null
1129      * value is explicitly associated with the key.
1130      *
1131      * @param key a String, or null
1132      * @return a char[] value, or null
1133      */
1134     @Override
1135     @Nullable
getCharArray(@ullable String key)1136     public char[] getCharArray(@Nullable String key) {
1137         return super.getCharArray(key);
1138     }
1139 
1140     /**
1141      * Returns the value associated with the given key, or null if
1142      * no mapping of the desired type exists for the given key or a null
1143      * value is explicitly associated with the key.
1144      *
1145      * @param key a String, or null
1146      * @return a float[] value, or null
1147      */
1148     @Override
1149     @Nullable
getFloatArray(@ullable String key)1150     public float[] getFloatArray(@Nullable String key) {
1151         return super.getFloatArray(key);
1152     }
1153 
1154     /**
1155      * Returns the value associated with the given key, or null if
1156      * no mapping of the desired type exists for the given key or a null
1157      * value is explicitly associated with the key.
1158      *
1159      * @param key a String, or null
1160      * @return a CharSequence[] value, or null
1161      */
1162     @Override
1163     @Nullable
getCharSequenceArray(@ullable String key)1164     public CharSequence[] getCharSequenceArray(@Nullable String key) {
1165         return super.getCharSequenceArray(key);
1166     }
1167 
1168     /**
1169      * Returns the value associated with the given key, or null if
1170      * no mapping of the desired type exists for the given key or a null
1171      * value is explicitly associated with the key.
1172      *
1173      * @param key a String, or null
1174      * @return an IBinder value, or null
1175      */
1176     @Nullable
getBinder(@ullable String key)1177     public IBinder getBinder(@Nullable String key) {
1178         unparcel();
1179         Object o = mMap.get(key);
1180         if (o == null) {
1181             return null;
1182         }
1183         try {
1184             return (IBinder) o;
1185         } catch (ClassCastException e) {
1186             typeWarning(key, o, "IBinder", e);
1187             return null;
1188         }
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 an IBinder value, or null
1198      *
1199      * @deprecated
1200      * @hide This is the old name of the function.
1201      */
1202     @UnsupportedAppUsage
1203     @Deprecated
1204     @Nullable
getIBinder(@ullable String key)1205     public IBinder getIBinder(@Nullable String key) {
1206         unparcel();
1207         Object o = mMap.get(key);
1208         if (o == null) {
1209             return null;
1210         }
1211         try {
1212             return (IBinder) o;
1213         } catch (ClassCastException e) {
1214             typeWarning(key, o, "IBinder", e);
1215             return null;
1216         }
1217     }
1218 
1219     public static final @android.annotation.NonNull Parcelable.Creator<Bundle> CREATOR =
1220         new Parcelable.Creator<Bundle>() {
1221         @Override
1222         public Bundle createFromParcel(Parcel in) {
1223             return in.readBundle();
1224         }
1225 
1226         @Override
1227         public Bundle[] newArray(int size) {
1228             return new Bundle[size];
1229         }
1230     };
1231 
1232     /**
1233      * Report the nature of this Parcelable's contents
1234      */
1235     @Override
describeContents()1236     public int describeContents() {
1237         int mask = 0;
1238         if (hasFileDescriptors()) {
1239             mask |= Parcelable.CONTENTS_FILE_DESCRIPTOR;
1240         }
1241         return mask;
1242     }
1243 
1244     /**
1245      * Writes the Bundle contents to a Parcel, typically in order for
1246      * it to be passed through an IBinder connection.
1247      * @param parcel The parcel to copy this bundle to.
1248      */
1249     @Override
writeToParcel(Parcel parcel, int flags)1250     public void writeToParcel(Parcel parcel, int flags) {
1251         final boolean oldAllowFds = parcel.pushAllowFds((mFlags & FLAG_ALLOW_FDS) != 0);
1252         try {
1253             super.writeToParcelInner(parcel, flags);
1254         } finally {
1255             parcel.restoreAllowFds(oldAllowFds);
1256         }
1257     }
1258 
1259     /**
1260      * Reads the Parcel contents into this Bundle, typically in order for
1261      * it to be passed through an IBinder connection.
1262      * @param parcel The parcel to overwrite this bundle from.
1263      */
readFromParcel(Parcel parcel)1264     public void readFromParcel(Parcel parcel) {
1265         super.readFromParcelInner(parcel);
1266         mFlags = FLAG_ALLOW_FDS;
1267         maybePrefillHasFds();
1268     }
1269 
1270     @Override
toString()1271     public synchronized String toString() {
1272         if (mParcelledData != null) {
1273             if (isEmptyParcel()) {
1274                 return "Bundle[EMPTY_PARCEL]";
1275             } else {
1276                 return "Bundle[mParcelledData.dataSize=" +
1277                         mParcelledData.dataSize() + "]";
1278             }
1279         }
1280         return "Bundle[" + mMap.toString() + "]";
1281     }
1282 
1283     /**
1284      * @hide
1285      */
toShortString()1286     public synchronized String toShortString() {
1287         if (mParcelledData != null) {
1288             if (isEmptyParcel()) {
1289                 return "EMPTY_PARCEL";
1290             } else {
1291                 return "mParcelledData.dataSize=" + mParcelledData.dataSize();
1292             }
1293         }
1294         return mMap.toString();
1295     }
1296 
1297     /** @hide */
writeToProto(ProtoOutputStream proto, long fieldId)1298     public void writeToProto(ProtoOutputStream proto, long fieldId) {
1299         final long token = proto.start(fieldId);
1300 
1301         if (mParcelledData != null) {
1302             if (isEmptyParcel()) {
1303                 proto.write(BundleProto.PARCELLED_DATA_SIZE, 0);
1304             } else {
1305                 proto.write(BundleProto.PARCELLED_DATA_SIZE, mParcelledData.dataSize());
1306             }
1307         } else {
1308             proto.write(BundleProto.MAP_DATA, mMap.toString());
1309         }
1310 
1311         proto.end(token);
1312     }
1313 }
1314