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