• 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.util.Log;
20 import android.util.SparseArray;
21 
22 import java.io.Serializable;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.Map;
28 import java.util.Set;
29 
30 /**
31  * A mapping from String values to various Parcelable types.
32  *
33  */
34 public final class Bundle implements Parcelable, Cloneable {
35     private static final String LOG_TAG = "Bundle";
36     public static final Bundle EMPTY;
37 
38     static {
39         EMPTY = new Bundle();
40         EMPTY.mMap = Collections.unmodifiableMap(new HashMap<String, Object>());
41     }
42 
43     // Invariant - exactly one of mMap / mParcelledData will be null
44     // (except inside a call to unparcel)
45 
46     /* package */ Map<String, Object> mMap = null;
47 
48     /*
49      * If mParcelledData is non-null, then mMap will be null and the
50      * data are stored as a Parcel containing a Bundle.  When the data
51      * are unparcelled, mParcelledData willbe set to null.
52      */
53     /* package */ Parcel mParcelledData = null;
54 
55     private boolean mHasFds = false;
56     private boolean mFdsKnown = true;
57 
58     /**
59      * The ClassLoader used when unparcelling data from mParcelledData.
60      */
61     private ClassLoader mClassLoader;
62 
63     /**
64      * Constructs a new, empty Bundle.
65      */
Bundle()66     public Bundle() {
67         mMap = new HashMap<String, Object>();
68         mClassLoader = getClass().getClassLoader();
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      */
Bundle(Parcel parcelledData)77     Bundle(Parcel parcelledData) {
78         readFromParcel(parcelledData);
79     }
80 
Bundle(Parcel parcelledData, int length)81     /* package */ Bundle(Parcel parcelledData, int length) {
82         readFromParcelInner(parcelledData, length);
83     }
84 
85     /**
86      * Constructs a new, empty Bundle that uses a specific ClassLoader for
87      * instantiating Parcelable and Serializable objects.
88      *
89      * @param loader An explicit ClassLoader to use when instantiating objects
90      * inside of the Bundle.
91      */
Bundle(ClassLoader loader)92     public Bundle(ClassLoader loader) {
93         mMap = new HashMap<String, Object>();
94         mClassLoader = loader;
95     }
96 
97     /**
98      * Constructs a new, empty Bundle sized to hold the given number of
99      * elements. The Bundle will grow as needed.
100      *
101      * @param capacity the initial capacity of the Bundle
102      */
Bundle(int capacity)103     public Bundle(int capacity) {
104         mMap = new HashMap<String, Object>(capacity);
105         mClassLoader = getClass().getClassLoader();
106     }
107 
108     /**
109      * Constructs a Bundle containing a copy of the mappings from the given
110      * Bundle.
111      *
112      * @param b a Bundle to be copied.
113      */
Bundle(Bundle b)114     public Bundle(Bundle b) {
115         if (b.mParcelledData != null) {
116             mParcelledData = Parcel.obtain();
117             mParcelledData.appendFrom(b.mParcelledData, 0, b.mParcelledData.dataSize());
118             mParcelledData.setDataPosition(0);
119         } else {
120             mParcelledData = null;
121         }
122 
123         if (b.mMap != null) {
124             mMap = new HashMap<String, Object>(b.mMap);
125         } else {
126             mMap = null;
127         }
128 
129         mHasFds = b.mHasFds;
130         mFdsKnown = b.mFdsKnown;
131         mClassLoader = b.mClassLoader;
132     }
133 
134     /**
135      * Make a Bundle for a single key/value pair.
136      *
137      * @hide
138      */
forPair(String key, String value)139     public static Bundle forPair(String key, String value) {
140         // TODO: optimize this case.
141         Bundle b = new Bundle(1);
142         b.putString(key, value);
143         return b;
144     }
145 
146     /**
147      * TODO: optimize this later (getting just the value part of a Bundle
148      * with a single pair) once Bundle.forPair() above is implemented
149      * with a special single-value Map implementation/serialization.
150      *
151      * Note: value in single-pair Bundle may be null.
152      *
153      * @hide
154      */
getPairValue()155     public String getPairValue() {
156         unparcel();
157         int size = mMap.size();
158         if (size > 1) {
159             Log.w(LOG_TAG, "getPairValue() used on Bundle with multiple pairs.");
160         }
161         if (size == 0) {
162             return null;
163         }
164         Object o = mMap.values().iterator().next();
165         try {
166             return (String) o;
167         } catch (ClassCastException e) {
168             typeWarning("getPairValue()", o, "String", e);
169             return null;
170         }
171     }
172 
173     /**
174      * Changes the ClassLoader this Bundle uses when instantiating objects.
175      *
176      * @param loader An explicit ClassLoader to use when instantiating objects
177      * inside of the Bundle.
178      */
setClassLoader(ClassLoader loader)179     public void setClassLoader(ClassLoader loader) {
180         mClassLoader = loader;
181     }
182 
183     /**
184      * Clones the current Bundle. The internal map is cloned, but the keys and
185      * values to which it refers are copied by reference.
186      */
187     @Override
clone()188     public Object clone() {
189         return new Bundle(this);
190     }
191 
192     /**
193      * If the underlying data are stored as a Parcel, unparcel them
194      * using the currently assigned class loader.
195      */
unparcel()196     /* package */ synchronized void unparcel() {
197         if (mParcelledData == null) {
198             return;
199         }
200 
201         int N = mParcelledData.readInt();
202         if (N < 0) {
203             return;
204         }
205         if (mMap == null) {
206             mMap = new HashMap<String, Object>();
207         }
208         mParcelledData.readMapInternal(mMap, N, mClassLoader);
209         mParcelledData.recycle();
210         mParcelledData = null;
211     }
212 
213     /**
214      * Returns the number of mappings contained in this Bundle.
215      *
216      * @return the number of mappings as an int.
217      */
size()218     public int size() {
219         unparcel();
220         return mMap.size();
221     }
222 
223     /**
224      * Returns true if the mapping of this Bundle is empty, false otherwise.
225      */
isEmpty()226     public boolean isEmpty() {
227         unparcel();
228         return mMap.isEmpty();
229     }
230 
231     /**
232      * Removes all elements from the mapping of this Bundle.
233      */
clear()234     public void clear() {
235         unparcel();
236         mMap.clear();
237         mHasFds = false;
238         mFdsKnown = true;
239     }
240 
241     /**
242      * Returns true if the given key is contained in the mapping
243      * of this Bundle.
244      *
245      * @param key a String key
246      * @return true if the key is part of the mapping, false otherwise
247      */
containsKey(String key)248     public boolean containsKey(String key) {
249         unparcel();
250         return mMap.containsKey(key);
251     }
252 
253     /**
254      * Returns the entry with the given key as an object.
255      *
256      * @param key a String key
257      * @return an Object, or null
258      */
get(String key)259     public Object get(String key) {
260         unparcel();
261         return mMap.get(key);
262     }
263 
264     /**
265      * Removes any entry with the given key from the mapping of this Bundle.
266      *
267      * @param key a String key
268      */
remove(String key)269     public void remove(String key) {
270         unparcel();
271         mMap.remove(key);
272     }
273 
274     /**
275      * Inserts all mappings from the given Bundle into this Bundle.
276      *
277      * @param map a Bundle
278      */
putAll(Bundle map)279     public void putAll(Bundle map) {
280         unparcel();
281         map.unparcel();
282         mMap.putAll(map.mMap);
283 
284         // fd state is now known if and only if both bundles already knew
285         mHasFds |= map.mHasFds;
286         mFdsKnown = mFdsKnown && map.mFdsKnown;
287     }
288 
289     /**
290      * Returns a Set containing the Strings used as keys in this Bundle.
291      *
292      * @return a Set of String keys
293      */
keySet()294     public Set<String> keySet() {
295         unparcel();
296         return mMap.keySet();
297     }
298 
299     /**
300      * Reports whether the bundle contains any parcelled file descriptors.
301      */
hasFileDescriptors()302     public boolean hasFileDescriptors() {
303         if (!mFdsKnown) {
304             boolean fdFound = false;    // keep going until we find one or run out of data
305 
306             if (mParcelledData != null) {
307                 if (mParcelledData.hasFileDescriptors()) {
308                     fdFound = true;
309                 }
310             } else {
311                 // It's been unparcelled, so we need to walk the map
312                 Iterator<Map.Entry<String, Object>> iter = mMap.entrySet().iterator();
313                 while (!fdFound && iter.hasNext()) {
314                     Object obj = iter.next().getValue();
315                     if (obj instanceof Parcelable) {
316                         if ((((Parcelable)obj).describeContents()
317                                 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
318                             fdFound = true;
319                             break;
320                         }
321                     } else if (obj instanceof Parcelable[]) {
322                         Parcelable[] array = (Parcelable[]) obj;
323                         for (int n = array.length - 1; n >= 0; n--) {
324                             if ((array[n].describeContents()
325                                     & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
326                                 fdFound = true;
327                                 break;
328                             }
329                         }
330                     } else if (obj instanceof SparseArray) {
331                         SparseArray<? extends Parcelable> array =
332                                 (SparseArray<? extends Parcelable>) obj;
333                         for (int n = array.size() - 1; n >= 0; n--) {
334                             if ((array.get(n).describeContents()
335                                     & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
336                                 fdFound = true;
337                                 break;
338                             }
339                         }
340                     } else if (obj instanceof ArrayList) {
341                         ArrayList array = (ArrayList) obj;
342                         // an ArrayList here might contain either Strings or
343                         // Parcelables; only look inside for Parcelables
344                         if ((array.size() > 0)
345                                 && (array.get(0) instanceof Parcelable)) {
346                             for (int n = array.size() - 1; n >= 0; n--) {
347                                 Parcelable p = (Parcelable) array.get(n);
348                                 if (p != null && ((p.describeContents()
349                                         & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
350                                     fdFound = true;
351                                     break;
352                                 }
353                             }
354                         }
355                     }
356                 }
357             }
358 
359             mHasFds = fdFound;
360             mFdsKnown = true;
361         }
362         return mHasFds;
363     }
364 
365     /**
366      * Inserts a Boolean value into the mapping of this Bundle, replacing
367      * any existing value for the given key.  Either key or value may be null.
368      *
369      * @param key a String, or null
370      * @param value a Boolean, or null
371      */
putBoolean(String key, boolean value)372     public void putBoolean(String key, boolean value) {
373         unparcel();
374         mMap.put(key, value);
375     }
376 
377     /**
378      * Inserts a byte value into the mapping of this Bundle, replacing
379      * any existing value for the given key.
380      *
381      * @param key a String, or null
382      * @param value a byte
383      */
putByte(String key, byte value)384     public void putByte(String key, byte value) {
385         unparcel();
386         mMap.put(key, value);
387     }
388 
389     /**
390      * Inserts a char value into the mapping of this Bundle, replacing
391      * any existing value for the given key.
392      *
393      * @param key a String, or null
394      * @param value a char, or null
395      */
putChar(String key, char value)396     public void putChar(String key, char value) {
397         unparcel();
398         mMap.put(key, value);
399     }
400 
401     /**
402      * Inserts a short value into the mapping of this Bundle, replacing
403      * any existing value for the given key.
404      *
405      * @param key a String, or null
406      * @param value a short
407      */
putShort(String key, short value)408     public void putShort(String key, short value) {
409         unparcel();
410         mMap.put(key, value);
411     }
412 
413     /**
414      * Inserts an int value into the mapping of this Bundle, replacing
415      * any existing value for the given key.
416      *
417      * @param key a String, or null
418      * @param value an int, or null
419      */
putInt(String key, int value)420     public void putInt(String key, int value) {
421         unparcel();
422         mMap.put(key, value);
423     }
424 
425     /**
426      * Inserts a long value into the mapping of this Bundle, replacing
427      * any existing value for the given key.
428      *
429      * @param key a String, or null
430      * @param value a long
431      */
putLong(String key, long value)432     public void putLong(String key, long value) {
433         unparcel();
434         mMap.put(key, value);
435     }
436 
437     /**
438      * Inserts a float value into the mapping of this Bundle, replacing
439      * any existing value for the given key.
440      *
441      * @param key a String, or null
442      * @param value a float
443      */
putFloat(String key, float value)444     public void putFloat(String key, float value) {
445         unparcel();
446         mMap.put(key, value);
447     }
448 
449     /**
450      * Inserts a double value into the mapping of this Bundle, replacing
451      * any existing value for the given key.
452      *
453      * @param key a String, or null
454      * @param value a double
455      */
putDouble(String key, double value)456     public void putDouble(String key, double value) {
457         unparcel();
458         mMap.put(key, value);
459     }
460 
461     /**
462      * Inserts a String value into the mapping of this Bundle, replacing
463      * any existing value for the given key.  Either key or value may be null.
464      *
465      * @param key a String, or null
466      * @param value a String, or null
467      */
putString(String key, String value)468     public void putString(String key, String value) {
469         unparcel();
470         mMap.put(key, value);
471     }
472 
473     /**
474      * Inserts a CharSequence value into the mapping of this Bundle, replacing
475      * any existing value for the given key.  Either key or value may be null.
476      *
477      * @param key a String, or null
478      * @param value a CharSequence, or null
479      */
putCharSequence(String key, CharSequence value)480     public void putCharSequence(String key, CharSequence value) {
481         unparcel();
482         mMap.put(key, value);
483     }
484 
485     /**
486      * Inserts a Parcelable value into the mapping of this Bundle, replacing
487      * any existing value for the given key.  Either key or value may be null.
488      *
489      * @param key a String, or null
490      * @param value a Parcelable object, or null
491      */
putParcelable(String key, Parcelable value)492     public void putParcelable(String key, Parcelable value) {
493         unparcel();
494         mMap.put(key, value);
495         mFdsKnown = false;
496     }
497 
498     /**
499      * Inserts an array of Parcelable values into the mapping of this Bundle,
500      * replacing any existing value for the given key.  Either key or value may
501      * be null.
502      *
503      * @param key a String, or null
504      * @param value an array of Parcelable objects, or null
505      */
putParcelableArray(String key, Parcelable[] value)506     public void putParcelableArray(String key, Parcelable[] value) {
507         unparcel();
508         mMap.put(key, value);
509         mFdsKnown = false;
510     }
511 
512     /**
513      * Inserts a List of Parcelable values into the mapping of this Bundle,
514      * replacing any existing value for the given key.  Either key or value may
515      * be null.
516      *
517      * @param key a String, or null
518      * @param value an ArrayList of Parcelable objects, or null
519      */
putParcelableArrayList(String key, ArrayList<? extends Parcelable> value)520     public void putParcelableArrayList(String key,
521         ArrayList<? extends Parcelable> value) {
522         unparcel();
523         mMap.put(key, value);
524         mFdsKnown = false;
525     }
526 
527     /**
528      * Inserts a SparceArray of Parcelable values into the mapping of this
529      * Bundle, replacing any existing value for the given key.  Either key
530      * or value may be null.
531      *
532      * @param key a String, or null
533      * @param value a SparseArray of Parcelable objects, or null
534      */
putSparseParcelableArray(String key, SparseArray<? extends Parcelable> value)535     public void putSparseParcelableArray(String key,
536             SparseArray<? extends Parcelable> value) {
537         unparcel();
538         mMap.put(key, value);
539         mFdsKnown = false;
540     }
541 
542     /**
543      * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing
544      * any existing value for the given key.  Either key or value may be null.
545      *
546      * @param key a String, or null
547      * @param value an ArrayList<Integer> object, or null
548      */
putIntegerArrayList(String key, ArrayList<Integer> value)549     public void putIntegerArrayList(String key, ArrayList<Integer> value) {
550         unparcel();
551         mMap.put(key, value);
552     }
553 
554     /**
555      * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing
556      * any existing value for the given key.  Either key or value may be null.
557      *
558      * @param key a String, or null
559      * @param value an ArrayList<String> object, or null
560      */
putStringArrayList(String key, ArrayList<String> value)561     public void putStringArrayList(String key, ArrayList<String> value) {
562         unparcel();
563         mMap.put(key, value);
564     }
565 
566     /**
567      * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing
568      * any existing value for the given key.  Either key or value may be null.
569      *
570      * @param key a String, or null
571      * @param value an ArrayList<CharSequence> object, or null
572      */
putCharSequenceArrayList(String key, ArrayList<CharSequence> value)573     public void putCharSequenceArrayList(String key, ArrayList<CharSequence> value) {
574         unparcel();
575         mMap.put(key, value);
576     }
577 
578     /**
579      * Inserts a Serializable value into the mapping of this Bundle, replacing
580      * any existing value for the given key.  Either key or value may be null.
581      *
582      * @param key a String, or null
583      * @param value a Serializable object, or null
584      */
putSerializable(String key, Serializable value)585     public void putSerializable(String key, Serializable value) {
586         unparcel();
587         mMap.put(key, value);
588     }
589 
590     /**
591      * Inserts a boolean array value into the mapping of this Bundle, replacing
592      * any existing value for the given key.  Either key or value may be null.
593      *
594      * @param key a String, or null
595      * @param value a boolean array object, or null
596      */
putBooleanArray(String key, boolean[] value)597     public void putBooleanArray(String key, boolean[] value) {
598         unparcel();
599         mMap.put(key, value);
600     }
601 
602     /**
603      * Inserts a byte array value into the mapping of this Bundle, replacing
604      * any existing value for the given key.  Either key or value may be null.
605      *
606      * @param key a String, or null
607      * @param value a byte array object, or null
608      */
putByteArray(String key, byte[] value)609     public void putByteArray(String key, byte[] value) {
610         unparcel();
611         mMap.put(key, value);
612     }
613 
614     /**
615      * Inserts a short array value into the mapping of this Bundle, replacing
616      * any existing value for the given key.  Either key or value may be null.
617      *
618      * @param key a String, or null
619      * @param value a short array object, or null
620      */
putShortArray(String key, short[] value)621     public void putShortArray(String key, short[] value) {
622         unparcel();
623         mMap.put(key, value);
624     }
625 
626     /**
627      * Inserts a char array value into the mapping of this Bundle, replacing
628      * any existing value for the given key.  Either key or value may be null.
629      *
630      * @param key a String, or null
631      * @param value a char array object, or null
632      */
putCharArray(String key, char[] value)633     public void putCharArray(String key, char[] value) {
634         unparcel();
635         mMap.put(key, value);
636     }
637 
638     /**
639      * Inserts an int array value into the mapping of this Bundle, replacing
640      * any existing value for the given key.  Either key or value may be null.
641      *
642      * @param key a String, or null
643      * @param value an int array object, or null
644      */
putIntArray(String key, int[] value)645     public void putIntArray(String key, int[] value) {
646         unparcel();
647         mMap.put(key, value);
648     }
649 
650     /**
651      * Inserts a long array value into the mapping of this Bundle, replacing
652      * any existing value for the given key.  Either key or value may be null.
653      *
654      * @param key a String, or null
655      * @param value a long array object, or null
656      */
putLongArray(String key, long[] value)657     public void putLongArray(String key, long[] value) {
658         unparcel();
659         mMap.put(key, value);
660     }
661 
662     /**
663      * Inserts a float array value into the mapping of this Bundle, replacing
664      * any existing value for the given key.  Either key or value may be null.
665      *
666      * @param key a String, or null
667      * @param value a float array object, or null
668      */
putFloatArray(String key, float[] value)669     public void putFloatArray(String key, float[] value) {
670         unparcel();
671         mMap.put(key, value);
672     }
673 
674     /**
675      * Inserts a double array value into the mapping of this Bundle, replacing
676      * any existing value for the given key.  Either key or value may be null.
677      *
678      * @param key a String, or null
679      * @param value a double array object, or null
680      */
putDoubleArray(String key, double[] value)681     public void putDoubleArray(String key, double[] value) {
682         unparcel();
683         mMap.put(key, value);
684     }
685 
686     /**
687      * Inserts a String array value into the mapping of this Bundle, replacing
688      * any existing value for the given key.  Either key or value may be null.
689      *
690      * @param key a String, or null
691      * @param value a String array object, or null
692      */
putStringArray(String key, String[] value)693     public void putStringArray(String key, String[] value) {
694         unparcel();
695         mMap.put(key, value);
696     }
697 
698     /**
699      * Inserts a CharSequence array value into the mapping of this Bundle, replacing
700      * any existing value for the given key.  Either key or value may be null.
701      *
702      * @param key a String, or null
703      * @param value a CharSequence array object, or null
704      */
putCharSequenceArray(String key, CharSequence[] value)705     public void putCharSequenceArray(String key, CharSequence[] value) {
706         unparcel();
707         mMap.put(key, value);
708     }
709 
710     /**
711      * Inserts a Bundle value into the mapping of this Bundle, replacing
712      * any existing value for the given key.  Either key or value may be null.
713      *
714      * @param key a String, or null
715      * @param value a Bundle object, or null
716      */
putBundle(String key, Bundle value)717     public void putBundle(String key, Bundle value) {
718         unparcel();
719         mMap.put(key, value);
720     }
721 
722     /**
723      * Inserts an IBinder value into the mapping of this Bundle, replacing
724      * any existing value for the given key.  Either key or value may be null.
725      *
726      * @param key a String, or null
727      * @param value an IBinder object, or null
728      *
729      * @deprecated
730      * @hide
731      */
732     @Deprecated
putIBinder(String key, IBinder value)733     public void putIBinder(String key, IBinder value) {
734         unparcel();
735         mMap.put(key, value);
736     }
737 
738     /**
739      * Returns the value associated with the given key, or false if
740      * no mapping of the desired type exists for the given key.
741      *
742      * @param key a String
743      * @return a boolean value
744      */
getBoolean(String key)745     public boolean getBoolean(String key) {
746         unparcel();
747         return getBoolean(key, false);
748     }
749 
750     // Log a message if the value was non-null but not of the expected type
typeWarning(String key, Object value, String className, Object defaultValue, ClassCastException e)751     private void typeWarning(String key, Object value, String className,
752         Object defaultValue, ClassCastException e) {
753         StringBuilder sb = new StringBuilder();
754         sb.append("Key ");
755         sb.append(key);
756         sb.append(" expected ");
757         sb.append(className);
758         sb.append(" but value was a ");
759         sb.append(value.getClass().getName());
760         sb.append(".  The default value ");
761         sb.append(defaultValue);
762         sb.append(" was returned.");
763         Log.w(LOG_TAG, sb.toString());
764         Log.w(LOG_TAG, "Attempt to cast generated internal exception:", e);
765     }
766 
typeWarning(String key, Object value, String className, ClassCastException e)767     private void typeWarning(String key, Object value, String className,
768         ClassCastException e) {
769         typeWarning(key, value, className, "<null>", e);
770     }
771 
772     /**
773      * Returns the value associated with the given key, or defaultValue if
774      * no mapping of the desired type exists for the given key.
775      *
776      * @param key a String
777      * @return a boolean value
778      */
getBoolean(String key, boolean defaultValue)779     public boolean getBoolean(String key, boolean defaultValue) {
780         unparcel();
781         Object o = mMap.get(key);
782         if (o == null) {
783             return defaultValue;
784         }
785         try {
786             return (Boolean) o;
787         } catch (ClassCastException e) {
788             typeWarning(key, o, "Boolean", defaultValue, e);
789             return defaultValue;
790         }
791     }
792 
793     /**
794      * Returns the value associated with the given key, or (byte) 0 if
795      * no mapping of the desired type exists for the given key.
796      *
797      * @param key a String
798      * @return a byte value
799      */
getByte(String key)800     public byte getByte(String key) {
801         unparcel();
802         return getByte(key, (byte) 0);
803     }
804 
805     /**
806      * Returns the value associated with the given key, or defaultValue if
807      * no mapping of the desired type exists for the given key.
808      *
809      * @param key a String
810      * @return a byte value
811      */
getByte(String key, byte defaultValue)812     public Byte getByte(String key, byte defaultValue) {
813         unparcel();
814         Object o = mMap.get(key);
815         if (o == null) {
816             return defaultValue;
817         }
818         try {
819             return (Byte) o;
820         } catch (ClassCastException e) {
821             typeWarning(key, o, "Byte", defaultValue, e);
822             return defaultValue;
823         }
824     }
825 
826     /**
827      * Returns the value associated with the given key, or false if
828      * no mapping of the desired type exists for the given key.
829      *
830      * @param key a String
831      * @return a char value
832      */
getChar(String key)833     public char getChar(String key) {
834         unparcel();
835         return getChar(key, (char) 0);
836     }
837 
838     /**
839      * Returns the value associated with the given key, or (char) 0 if
840      * no mapping of the desired type exists for the given key.
841      *
842      * @param key a String
843      * @return a char value
844      */
getChar(String key, char defaultValue)845     public char getChar(String key, char defaultValue) {
846         unparcel();
847         Object o = mMap.get(key);
848         if (o == null) {
849             return defaultValue;
850         }
851         try {
852             return (Character) o;
853         } catch (ClassCastException e) {
854             typeWarning(key, o, "Character", defaultValue, e);
855             return defaultValue;
856         }
857     }
858 
859     /**
860      * Returns the value associated with the given key, or (short) 0 if
861      * no mapping of the desired type exists for the given key.
862      *
863      * @param key a String
864      * @return a short value
865      */
getShort(String key)866     public short getShort(String key) {
867         unparcel();
868         return getShort(key, (short) 0);
869     }
870 
871     /**
872      * Returns the value associated with the given key, or defaultValue if
873      * no mapping of the desired type exists for the given key.
874      *
875      * @param key a String
876      * @return a short value
877      */
getShort(String key, short defaultValue)878     public short getShort(String key, short defaultValue) {
879         unparcel();
880         Object o = mMap.get(key);
881         if (o == null) {
882             return defaultValue;
883         }
884         try {
885             return (Short) o;
886         } catch (ClassCastException e) {
887             typeWarning(key, o, "Short", defaultValue, e);
888             return defaultValue;
889         }
890     }
891 
892     /**
893      * Returns the value associated with the given key, or 0 if
894      * no mapping of the desired type exists for the given key.
895      *
896      * @param key a String
897      * @return an int value
898      */
getInt(String key)899     public int getInt(String key) {
900         unparcel();
901         return getInt(key, 0);
902     }
903 
904     /**
905      * Returns the value associated with the given key, or defaultValue if
906      * no mapping of the desired type exists for the given key.
907      *
908      * @param key a String
909      * @return an int value
910      */
getInt(String key, int defaultValue)911     public int getInt(String key, int defaultValue) {
912         unparcel();
913         Object o = mMap.get(key);
914         if (o == null) {
915             return defaultValue;
916         }
917         try {
918             return (Integer) o;
919         } catch (ClassCastException e) {
920             typeWarning(key, o, "Integer", defaultValue, e);
921             return defaultValue;
922         }
923     }
924 
925     /**
926      * Returns the value associated with the given key, or 0L if
927      * no mapping of the desired type exists for the given key.
928      *
929      * @param key a String
930      * @return a long value
931      */
getLong(String key)932     public long getLong(String key) {
933         unparcel();
934         return getLong(key, 0L);
935     }
936 
937     /**
938      * Returns the value associated with the given key, or defaultValue if
939      * no mapping of the desired type exists for the given key.
940      *
941      * @param key a String
942      * @return a long value
943      */
getLong(String key, long defaultValue)944     public long getLong(String key, long defaultValue) {
945         unparcel();
946         Object o = mMap.get(key);
947         if (o == null) {
948             return defaultValue;
949         }
950         try {
951             return (Long) o;
952         } catch (ClassCastException e) {
953             typeWarning(key, o, "Long", defaultValue, e);
954             return defaultValue;
955         }
956     }
957 
958     /**
959      * Returns the value associated with the given key, or 0.0f if
960      * no mapping of the desired type exists for the given key.
961      *
962      * @param key a String
963      * @return a float value
964      */
getFloat(String key)965     public float getFloat(String key) {
966         unparcel();
967         return getFloat(key, 0.0f);
968     }
969 
970     /**
971      * Returns the value associated with the given key, or defaultValue if
972      * no mapping of the desired type exists for the given key.
973      *
974      * @param key a String
975      * @return a float value
976      */
getFloat(String key, float defaultValue)977     public float getFloat(String key, float defaultValue) {
978         unparcel();
979         Object o = mMap.get(key);
980         if (o == null) {
981             return defaultValue;
982         }
983         try {
984             return (Float) o;
985         } catch (ClassCastException e) {
986             typeWarning(key, o, "Float", defaultValue, e);
987             return defaultValue;
988         }
989     }
990 
991     /**
992      * Returns the value associated with the given key, or 0.0 if
993      * no mapping of the desired type exists for the given key.
994      *
995      * @param key a String
996      * @return a double value
997      */
getDouble(String key)998     public double getDouble(String key) {
999         unparcel();
1000         return getDouble(key, 0.0);
1001     }
1002 
1003     /**
1004      * Returns the value associated with the given key, or defaultValue if
1005      * no mapping of the desired type exists for the given key.
1006      *
1007      * @param key a String
1008      * @return a double value
1009      */
getDouble(String key, double defaultValue)1010     public double getDouble(String key, double defaultValue) {
1011         unparcel();
1012         Object o = mMap.get(key);
1013         if (o == null) {
1014             return defaultValue;
1015         }
1016         try {
1017             return (Double) o;
1018         } catch (ClassCastException e) {
1019             typeWarning(key, o, "Double", defaultValue, e);
1020             return defaultValue;
1021         }
1022     }
1023 
1024 
1025     /**
1026      * Returns the value associated with the given key, or null if
1027      * no mapping of the desired type exists for the given key or a null
1028      * value is explicitly associated with the key.
1029      *
1030      * @param key a String, or null
1031      * @return a String value, or null
1032      */
getString(String key)1033     public String getString(String key) {
1034         unparcel();
1035         Object o = mMap.get(key);
1036         if (o == null) {
1037             return null;
1038         }
1039         try {
1040             return (String) o;
1041         } catch (ClassCastException e) {
1042             typeWarning(key, o, "String", e);
1043             return null;
1044         }
1045     }
1046 
1047     /**
1048      * Returns the value associated with the given key, or null if
1049      * no mapping of the desired type exists for the given key or a null
1050      * value is explicitly associated with the key.
1051      *
1052      * @param key a String, or null
1053      * @return a CharSequence value, or null
1054      */
getCharSequence(String key)1055     public CharSequence getCharSequence(String key) {
1056         unparcel();
1057         Object o = mMap.get(key);
1058         if (o == null) {
1059             return null;
1060         }
1061         try {
1062             return (CharSequence) o;
1063         } catch (ClassCastException e) {
1064             typeWarning(key, o, "CharSequence", e);
1065             return null;
1066         }
1067     }
1068 
1069     /**
1070      * Returns the value associated with the given key, or null if
1071      * no mapping of the desired type exists for the given key or a null
1072      * value is explicitly associated with the key.
1073      *
1074      * @param key a String, or null
1075      * @return a Bundle value, or null
1076      */
getBundle(String key)1077     public Bundle getBundle(String key) {
1078         unparcel();
1079         Object o = mMap.get(key);
1080         if (o == null) {
1081             return null;
1082         }
1083         try {
1084             return (Bundle) o;
1085         } catch (ClassCastException e) {
1086             typeWarning(key, o, "Bundle", e);
1087             return null;
1088         }
1089     }
1090 
1091     /**
1092      * Returns the value associated with the given key, or null if
1093      * no mapping of the desired type exists for the given key or a null
1094      * value is explicitly associated with the key.
1095      *
1096      * @param key a String, or null
1097      * @return a Parcelable value, or null
1098      */
getParcelable(String key)1099     public <T extends Parcelable> T getParcelable(String key) {
1100         unparcel();
1101         Object o = mMap.get(key);
1102         if (o == null) {
1103             return null;
1104         }
1105         try {
1106             return (T) o;
1107         } catch (ClassCastException e) {
1108             typeWarning(key, o, "Parcelable", e);
1109             return null;
1110         }
1111     }
1112 
1113     /**
1114      * Returns the value associated with the given key, or null if
1115      * no mapping of the desired type exists for the given key or a null
1116      * value is explicitly associated with the key.
1117      *
1118      * @param key a String, or null
1119      * @return a Parcelable[] value, or null
1120      */
getParcelableArray(String key)1121     public Parcelable[] getParcelableArray(String key) {
1122         unparcel();
1123         Object o = mMap.get(key);
1124         if (o == null) {
1125             return null;
1126         }
1127         try {
1128             return (Parcelable[]) o;
1129         } catch (ClassCastException e) {
1130             typeWarning(key, o, "Parcelable[]", e);
1131             return null;
1132         }
1133     }
1134 
1135     /**
1136      * Returns the value associated with the given key, or null if
1137      * no mapping of the desired type exists for the given key or a null
1138      * value is explicitly associated with the key.
1139      *
1140      * @param key a String, or null
1141      * @return an ArrayList<T> value, or null
1142      */
getParcelableArrayList(String key)1143     public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String key) {
1144         unparcel();
1145         Object o = mMap.get(key);
1146         if (o == null) {
1147             return null;
1148         }
1149         try {
1150             return (ArrayList<T>) o;
1151         } catch (ClassCastException e) {
1152             typeWarning(key, o, "ArrayList", e);
1153             return null;
1154         }
1155     }
1156 
1157     /**
1158      * Returns the value associated with the given key, or null if
1159      * no mapping of the desired type exists for the given key or a null
1160      * value is explicitly associated with the key.
1161      *
1162      * @param key a String, or null
1163      *
1164      * @return a SparseArray of T values, or null
1165      */
getSparseParcelableArray(String key)1166     public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(String key) {
1167         unparcel();
1168         Object o = mMap.get(key);
1169         if (o == null) {
1170             return null;
1171         }
1172         try {
1173             return (SparseArray<T>) o;
1174         } catch (ClassCastException e) {
1175             typeWarning(key, o, "SparseArray", e);
1176             return null;
1177         }
1178     }
1179 
1180     /**
1181      * Returns the value associated with the given key, or null if
1182      * no mapping of the desired type exists for the given key or a null
1183      * value is explicitly associated with the key.
1184      *
1185      * @param key a String, or null
1186      * @return a Serializable value, or null
1187      */
getSerializable(String key)1188     public Serializable getSerializable(String key) {
1189         unparcel();
1190         Object o = mMap.get(key);
1191         if (o == null) {
1192             return null;
1193         }
1194         try {
1195             return (Serializable) o;
1196         } catch (ClassCastException e) {
1197             typeWarning(key, o, "Serializable", e);
1198             return null;
1199         }
1200     }
1201 
1202     /**
1203      * Returns the value associated with the given key, or null if
1204      * no mapping of the desired type exists for the given key or a null
1205      * value is explicitly associated with the key.
1206      *
1207      * @param key a String, or null
1208      * @return an ArrayList<String> value, or null
1209      */
getIntegerArrayList(String key)1210     public ArrayList<Integer> getIntegerArrayList(String key) {
1211         unparcel();
1212         Object o = mMap.get(key);
1213         if (o == null) {
1214             return null;
1215         }
1216         try {
1217             return (ArrayList<Integer>) o;
1218         } catch (ClassCastException e) {
1219             typeWarning(key, o, "ArrayList<Integer>", e);
1220             return null;
1221         }
1222     }
1223 
1224     /**
1225      * Returns the value associated with the given key, or null if
1226      * no mapping of the desired type exists for the given key or a null
1227      * value is explicitly associated with the key.
1228      *
1229      * @param key a String, or null
1230      * @return an ArrayList<String> value, or null
1231      */
getStringArrayList(String key)1232     public ArrayList<String> getStringArrayList(String key) {
1233         unparcel();
1234         Object o = mMap.get(key);
1235         if (o == null) {
1236             return null;
1237         }
1238         try {
1239             return (ArrayList<String>) o;
1240         } catch (ClassCastException e) {
1241             typeWarning(key, o, "ArrayList<String>", e);
1242             return null;
1243         }
1244     }
1245 
1246     /**
1247      * Returns the value associated with the given key, or null if
1248      * no mapping of the desired type exists for the given key or a null
1249      * value is explicitly associated with the key.
1250      *
1251      * @param key a String, or null
1252      * @return an ArrayList<CharSequence> value, or null
1253      */
getCharSequenceArrayList(String key)1254     public ArrayList<CharSequence> getCharSequenceArrayList(String key) {
1255         unparcel();
1256         Object o = mMap.get(key);
1257         if (o == null) {
1258             return null;
1259         }
1260         try {
1261             return (ArrayList<CharSequence>) o;
1262         } catch (ClassCastException e) {
1263             typeWarning(key, o, "ArrayList<CharSequence>", e);
1264             return null;
1265         }
1266     }
1267 
1268     /**
1269      * Returns the value associated with the given key, or null if
1270      * no mapping of the desired type exists for the given key or a null
1271      * value is explicitly associated with the key.
1272      *
1273      * @param key a String, or null
1274      * @return a boolean[] value, or null
1275      */
getBooleanArray(String key)1276     public boolean[] getBooleanArray(String key) {
1277         unparcel();
1278         Object o = mMap.get(key);
1279         if (o == null) {
1280             return null;
1281         }
1282         try {
1283             return (boolean[]) o;
1284         } catch (ClassCastException e) {
1285             typeWarning(key, o, "byte[]", e);
1286             return null;
1287         }
1288     }
1289 
1290     /**
1291      * Returns the value associated with the given key, or null if
1292      * no mapping of the desired type exists for the given key or a null
1293      * value is explicitly associated with the key.
1294      *
1295      * @param key a String, or null
1296      * @return a byte[] value, or null
1297      */
getByteArray(String key)1298     public byte[] getByteArray(String key) {
1299         unparcel();
1300         Object o = mMap.get(key);
1301         if (o == null) {
1302             return null;
1303         }
1304         try {
1305             return (byte[]) o;
1306         } catch (ClassCastException e) {
1307             typeWarning(key, o, "byte[]", e);
1308             return null;
1309         }
1310     }
1311 
1312     /**
1313      * Returns the value associated with the given key, or null if
1314      * no mapping of the desired type exists for the given key or a null
1315      * value is explicitly associated with the key.
1316      *
1317      * @param key a String, or null
1318      * @return a short[] value, or null
1319      */
getShortArray(String key)1320     public short[] getShortArray(String key) {
1321         unparcel();
1322         Object o = mMap.get(key);
1323         if (o == null) {
1324             return null;
1325         }
1326         try {
1327             return (short[]) o;
1328         } catch (ClassCastException e) {
1329             typeWarning(key, o, "short[]", e);
1330             return null;
1331         }
1332     }
1333 
1334     /**
1335      * Returns the value associated with the given key, or null if
1336      * no mapping of the desired type exists for the given key or a null
1337      * value is explicitly associated with the key.
1338      *
1339      * @param key a String, or null
1340      * @return a char[] value, or null
1341      */
getCharArray(String key)1342     public char[] getCharArray(String key) {
1343         unparcel();
1344         Object o = mMap.get(key);
1345         if (o == null) {
1346             return null;
1347         }
1348         try {
1349             return (char[]) o;
1350         } catch (ClassCastException e) {
1351             typeWarning(key, o, "char[]", e);
1352             return null;
1353         }
1354     }
1355 
1356     /**
1357      * Returns the value associated with the given key, or null if
1358      * no mapping of the desired type exists for the given key or a null
1359      * value is explicitly associated with the key.
1360      *
1361      * @param key a String, or null
1362      * @return an int[] value, or null
1363      */
getIntArray(String key)1364     public int[] getIntArray(String key) {
1365         unparcel();
1366         Object o = mMap.get(key);
1367         if (o == null) {
1368             return null;
1369         }
1370         try {
1371             return (int[]) o;
1372         } catch (ClassCastException e) {
1373             typeWarning(key, o, "int[]", e);
1374             return null;
1375         }
1376     }
1377 
1378     /**
1379      * Returns the value associated with the given key, or null if
1380      * no mapping of the desired type exists for the given key or a null
1381      * value is explicitly associated with the key.
1382      *
1383      * @param key a String, or null
1384      * @return a long[] value, or null
1385      */
getLongArray(String key)1386     public long[] getLongArray(String key) {
1387         unparcel();
1388         Object o = mMap.get(key);
1389         if (o == null) {
1390             return null;
1391         }
1392         try {
1393             return (long[]) o;
1394         } catch (ClassCastException e) {
1395             typeWarning(key, o, "long[]", e);
1396             return null;
1397         }
1398     }
1399 
1400     /**
1401      * Returns the value associated with the given key, or null if
1402      * no mapping of the desired type exists for the given key or a null
1403      * value is explicitly associated with the key.
1404      *
1405      * @param key a String, or null
1406      * @return a float[] value, or null
1407      */
getFloatArray(String key)1408     public float[] getFloatArray(String key) {
1409         unparcel();
1410         Object o = mMap.get(key);
1411         if (o == null) {
1412             return null;
1413         }
1414         try {
1415             return (float[]) o;
1416         } catch (ClassCastException e) {
1417             typeWarning(key, o, "float[]", e);
1418             return null;
1419         }
1420     }
1421 
1422     /**
1423      * Returns the value associated with the given key, or null if
1424      * no mapping of the desired type exists for the given key or a null
1425      * value is explicitly associated with the key.
1426      *
1427      * @param key a String, or null
1428      * @return a double[] value, or null
1429      */
getDoubleArray(String key)1430     public double[] getDoubleArray(String key) {
1431         unparcel();
1432         Object o = mMap.get(key);
1433         if (o == null) {
1434             return null;
1435         }
1436         try {
1437             return (double[]) o;
1438         } catch (ClassCastException e) {
1439             typeWarning(key, o, "double[]", e);
1440             return null;
1441         }
1442     }
1443 
1444     /**
1445      * Returns the value associated with the given key, or null if
1446      * no mapping of the desired type exists for the given key or a null
1447      * value is explicitly associated with the key.
1448      *
1449      * @param key a String, or null
1450      * @return a String[] value, or null
1451      */
getStringArray(String key)1452     public String[] getStringArray(String key) {
1453         unparcel();
1454         Object o = mMap.get(key);
1455         if (o == null) {
1456             return null;
1457         }
1458         try {
1459             return (String[]) o;
1460         } catch (ClassCastException e) {
1461             typeWarning(key, o, "String[]", e);
1462             return null;
1463         }
1464     }
1465 
1466     /**
1467      * Returns the value associated with the given key, or null if
1468      * no mapping of the desired type exists for the given key or a null
1469      * value is explicitly associated with the key.
1470      *
1471      * @param key a String, or null
1472      * @return a CharSequence[] value, or null
1473      */
getCharSequenceArray(String key)1474     public CharSequence[] getCharSequenceArray(String key) {
1475         unparcel();
1476         Object o = mMap.get(key);
1477         if (o == null) {
1478             return null;
1479         }
1480         try {
1481             return (CharSequence[]) o;
1482         } catch (ClassCastException e) {
1483             typeWarning(key, o, "CharSequence[]", e);
1484             return null;
1485         }
1486     }
1487 
1488     /**
1489      * Returns the value associated with the given key, or null if
1490      * no mapping of the desired type exists for the given key or a null
1491      * value is explicitly associated with the key.
1492      *
1493      * @param key a String, or null
1494      * @return an IBinder value, or null
1495      *
1496      * @deprecated
1497      * @hide
1498      */
1499     @Deprecated
getIBinder(String key)1500     public IBinder getIBinder(String key) {
1501         unparcel();
1502         Object o = mMap.get(key);
1503         if (o == null) {
1504             return null;
1505         }
1506         try {
1507             return (IBinder) o;
1508         } catch (ClassCastException e) {
1509             typeWarning(key, o, "IBinder", e);
1510             return null;
1511         }
1512     }
1513 
1514     public static final Parcelable.Creator<Bundle> CREATOR =
1515         new Parcelable.Creator<Bundle>() {
1516         public Bundle createFromParcel(Parcel in) {
1517             return in.readBundle();
1518         }
1519 
1520         public Bundle[] newArray(int size) {
1521             return new Bundle[size];
1522         }
1523     };
1524 
1525     /**
1526      * Report the nature of this Parcelable's contents
1527      */
describeContents()1528     public int describeContents() {
1529         int mask = 0;
1530         if (hasFileDescriptors()) {
1531             mask |= Parcelable.CONTENTS_FILE_DESCRIPTOR;
1532         }
1533         return mask;
1534     }
1535 
1536     /**
1537      * Writes the Bundle contents to a Parcel, typically in order for
1538      * it to be passed through an IBinder connection.
1539      * @param parcel The parcel to copy this bundle to.
1540      */
writeToParcel(Parcel parcel, int flags)1541     public void writeToParcel(Parcel parcel, int flags) {
1542         if (mParcelledData != null) {
1543             int length = mParcelledData.dataSize();
1544             parcel.writeInt(length);
1545             parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
1546             parcel.appendFrom(mParcelledData, 0, length);
1547         } else {
1548             parcel.writeInt(-1); // dummy, will hold length
1549             parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
1550 
1551             int oldPos = parcel.dataPosition();
1552             parcel.writeMapInternal(mMap);
1553             int newPos = parcel.dataPosition();
1554 
1555             // Backpatch length
1556             parcel.setDataPosition(oldPos - 8);
1557             int length = newPos - oldPos;
1558             parcel.writeInt(length);
1559             parcel.setDataPosition(newPos);
1560         }
1561     }
1562 
1563     /**
1564      * Reads the Parcel contents into this Bundle, typically in order for
1565      * it to be passed through an IBinder connection.
1566      * @param parcel The parcel to overwrite this bundle from.
1567      */
readFromParcel(Parcel parcel)1568     public void readFromParcel(Parcel parcel) {
1569         int length = parcel.readInt();
1570         if (length < 0) {
1571             throw new RuntimeException("Bad length in parcel: " + length);
1572         }
1573         readFromParcelInner(parcel, length);
1574     }
1575 
readFromParcelInner(Parcel parcel, int length)1576     void readFromParcelInner(Parcel parcel, int length) {
1577         int magic = parcel.readInt();
1578         if (magic != 0x4C444E42) {
1579             //noinspection ThrowableInstanceNeverThrown
1580             String st = Log.getStackTraceString(new RuntimeException());
1581             Log.e("Bundle", "readBundle: bad magic number");
1582             Log.e("Bundle", "readBundle: trace = " + st);
1583         }
1584 
1585         // Advance within this Parcel
1586         int offset = parcel.dataPosition();
1587         parcel.setDataPosition(offset + length);
1588 
1589         Parcel p = Parcel.obtain();
1590         p.setDataPosition(0);
1591         p.appendFrom(parcel, offset, length);
1592         p.setDataPosition(0);
1593 
1594         mParcelledData = p;
1595         mHasFds = p.hasFileDescriptors();
1596         mFdsKnown = true;
1597     }
1598 
1599     @Override
toString()1600     public synchronized String toString() {
1601         if (mParcelledData != null) {
1602             return "Bundle[mParcelledData.dataSize=" +
1603                     mParcelledData.dataSize() + "]";
1604         }
1605         return "Bundle[" + mMap.toString() + "]";
1606     }
1607 }
1608