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