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