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