• 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      * @return a boolean value
800      */
getBoolean(String key, boolean defaultValue)801     public boolean getBoolean(String key, boolean defaultValue) {
802         unparcel();
803         Object o = mMap.get(key);
804         if (o == null) {
805             return defaultValue;
806         }
807         try {
808             return (Boolean) o;
809         } catch (ClassCastException e) {
810             typeWarning(key, o, "Boolean", defaultValue, e);
811             return defaultValue;
812         }
813     }
814 
815     /**
816      * Returns the value associated with the given key, or (byte) 0 if
817      * no mapping of the desired type exists for the given key.
818      *
819      * @param key a String
820      * @return a byte value
821      */
getByte(String key)822     public byte getByte(String key) {
823         unparcel();
824         return getByte(key, (byte) 0);
825     }
826 
827     /**
828      * Returns the value associated with the given key, or defaultValue if
829      * no mapping of the desired type exists for the given key.
830      *
831      * @param key a String
832      * @return a byte value
833      */
getByte(String key, byte defaultValue)834     public Byte getByte(String key, byte defaultValue) {
835         unparcel();
836         Object o = mMap.get(key);
837         if (o == null) {
838             return defaultValue;
839         }
840         try {
841             return (Byte) o;
842         } catch (ClassCastException e) {
843             typeWarning(key, o, "Byte", defaultValue, e);
844             return defaultValue;
845         }
846     }
847 
848     /**
849      * Returns the value associated with the given key, or false if
850      * no mapping of the desired type exists for the given key.
851      *
852      * @param key a String
853      * @return a char value
854      */
getChar(String key)855     public char getChar(String key) {
856         unparcel();
857         return getChar(key, (char) 0);
858     }
859 
860     /**
861      * Returns the value associated with the given key, or (char) 0 if
862      * no mapping of the desired type exists for the given key.
863      *
864      * @param key a String
865      * @return a char value
866      */
getChar(String key, char defaultValue)867     public char getChar(String key, char defaultValue) {
868         unparcel();
869         Object o = mMap.get(key);
870         if (o == null) {
871             return defaultValue;
872         }
873         try {
874             return (Character) o;
875         } catch (ClassCastException e) {
876             typeWarning(key, o, "Character", defaultValue, e);
877             return defaultValue;
878         }
879     }
880 
881     /**
882      * Returns the value associated with the given key, or (short) 0 if
883      * no mapping of the desired type exists for the given key.
884      *
885      * @param key a String
886      * @return a short value
887      */
getShort(String key)888     public short getShort(String key) {
889         unparcel();
890         return getShort(key, (short) 0);
891     }
892 
893     /**
894      * Returns the value associated with the given key, or defaultValue if
895      * no mapping of the desired type exists for the given key.
896      *
897      * @param key a String
898      * @return a short value
899      */
getShort(String key, short defaultValue)900     public short getShort(String key, short defaultValue) {
901         unparcel();
902         Object o = mMap.get(key);
903         if (o == null) {
904             return defaultValue;
905         }
906         try {
907             return (Short) o;
908         } catch (ClassCastException e) {
909             typeWarning(key, o, "Short", defaultValue, e);
910             return defaultValue;
911         }
912     }
913 
914     /**
915      * Returns the value associated with the given key, or 0 if
916      * no mapping of the desired type exists for the given key.
917      *
918      * @param key a String
919      * @return an int value
920      */
getInt(String key)921     public int getInt(String key) {
922         unparcel();
923         return getInt(key, 0);
924     }
925 
926     /**
927      * Returns the value associated with the given key, or defaultValue if
928      * no mapping of the desired type exists for the given key.
929      *
930      * @param key a String
931      * @return an int value
932      */
getInt(String key, int defaultValue)933     public int getInt(String key, int defaultValue) {
934         unparcel();
935         Object o = mMap.get(key);
936         if (o == null) {
937             return defaultValue;
938         }
939         try {
940             return (Integer) o;
941         } catch (ClassCastException e) {
942             typeWarning(key, o, "Integer", defaultValue, e);
943             return defaultValue;
944         }
945     }
946 
947     /**
948      * Returns the value associated with the given key, or 0L if
949      * no mapping of the desired type exists for the given key.
950      *
951      * @param key a String
952      * @return a long value
953      */
getLong(String key)954     public long getLong(String key) {
955         unparcel();
956         return getLong(key, 0L);
957     }
958 
959     /**
960      * Returns the value associated with the given key, or defaultValue if
961      * no mapping of the desired type exists for the given key.
962      *
963      * @param key a String
964      * @return a long value
965      */
getLong(String key, long defaultValue)966     public long getLong(String key, long defaultValue) {
967         unparcel();
968         Object o = mMap.get(key);
969         if (o == null) {
970             return defaultValue;
971         }
972         try {
973             return (Long) o;
974         } catch (ClassCastException e) {
975             typeWarning(key, o, "Long", defaultValue, e);
976             return defaultValue;
977         }
978     }
979 
980     /**
981      * Returns the value associated with the given key, or 0.0f if
982      * no mapping of the desired type exists for the given key.
983      *
984      * @param key a String
985      * @return a float value
986      */
getFloat(String key)987     public float getFloat(String key) {
988         unparcel();
989         return getFloat(key, 0.0f);
990     }
991 
992     /**
993      * Returns the value associated with the given key, or defaultValue if
994      * no mapping of the desired type exists for the given key.
995      *
996      * @param key a String
997      * @return a float value
998      */
getFloat(String key, float defaultValue)999     public float getFloat(String key, float defaultValue) {
1000         unparcel();
1001         Object o = mMap.get(key);
1002         if (o == null) {
1003             return defaultValue;
1004         }
1005         try {
1006             return (Float) o;
1007         } catch (ClassCastException e) {
1008             typeWarning(key, o, "Float", defaultValue, e);
1009             return defaultValue;
1010         }
1011     }
1012 
1013     /**
1014      * Returns the value associated with the given key, or 0.0 if
1015      * no mapping of the desired type exists for the given key.
1016      *
1017      * @param key a String
1018      * @return a double value
1019      */
getDouble(String key)1020     public double getDouble(String key) {
1021         unparcel();
1022         return getDouble(key, 0.0);
1023     }
1024 
1025     /**
1026      * Returns the value associated with the given key, or defaultValue if
1027      * no mapping of the desired type exists for the given key.
1028      *
1029      * @param key a String
1030      * @return a double value
1031      */
getDouble(String key, double defaultValue)1032     public double getDouble(String key, double defaultValue) {
1033         unparcel();
1034         Object o = mMap.get(key);
1035         if (o == null) {
1036             return defaultValue;
1037         }
1038         try {
1039             return (Double) o;
1040         } catch (ClassCastException e) {
1041             typeWarning(key, o, "Double", defaultValue, e);
1042             return defaultValue;
1043         }
1044     }
1045 
1046     /**
1047      * Returns the value associated with the given key, or null if
1048      * no mapping of the desired type exists for the given key or a null
1049      * value is explicitly associated with the key.
1050      *
1051      * @param key a String, or null
1052      * @return a String value, or null
1053      */
getString(String key)1054     public String getString(String key) {
1055         unparcel();
1056         Object o = mMap.get(key);
1057         if (o == null) {
1058             return null;
1059         }
1060         try {
1061             return (String) o;
1062         } catch (ClassCastException e) {
1063             typeWarning(key, o, "String", e);
1064             return null;
1065         }
1066     }
1067 
1068     /**
1069      * Returns the value associated with the given key, or defaultValue if
1070      * no mapping of the desired type exists for the given key.
1071      *
1072      * @param key a String, or null
1073      * @param defaultValue Value to return if key does not exist
1074      * @return a String value, or null
1075      */
getString(String key, String defaultValue)1076     public String getString(String key, String defaultValue) {
1077         unparcel();
1078         Object o = mMap.get(key);
1079         if (o == null) {
1080             return defaultValue;
1081         }
1082         try {
1083             return (String) o;
1084         } catch (ClassCastException e) {
1085             typeWarning(key, o, "String", e);
1086             return defaultValue;
1087         }
1088     }
1089 
1090     /**
1091      * Returns the value associated with the given key, or null if
1092      * no mapping of the desired type exists for the given key or a null
1093      * value is explicitly associated with the key.
1094      *
1095      * @param key a String, or null
1096      * @return a CharSequence value, or null
1097      */
getCharSequence(String key)1098     public CharSequence getCharSequence(String key) {
1099         unparcel();
1100         Object o = mMap.get(key);
1101         if (o == null) {
1102             return null;
1103         }
1104         try {
1105             return (CharSequence) o;
1106         } catch (ClassCastException e) {
1107             typeWarning(key, o, "CharSequence", e);
1108             return null;
1109         }
1110     }
1111 
1112     /**
1113      * Returns the value associated with the given key, or defaultValue if
1114      * no mapping of the desired type exists for the given key.
1115      *
1116      * @param key a String, or null
1117      * @param defaultValue Value to return if key does not exist
1118      * @return a CharSequence value, or null
1119      */
getCharSequence(String key, CharSequence defaultValue)1120     public CharSequence getCharSequence(String key, CharSequence defaultValue) {
1121         unparcel();
1122         Object o = mMap.get(key);
1123         if (o == null) {
1124             return defaultValue;
1125         }
1126         try {
1127             return (CharSequence) o;
1128         } catch (ClassCastException e) {
1129             typeWarning(key, o, "CharSequence", e);
1130             return defaultValue;
1131         }
1132     }
1133 
1134     /**
1135      * Returns the value associated with the given key, or null if
1136      * no mapping of the desired type exists for the given key or a null
1137      * value is explicitly associated with the key.
1138      *
1139      * @param key a String, or null
1140      * @return a Bundle value, or null
1141      */
getBundle(String key)1142     public Bundle getBundle(String key) {
1143         unparcel();
1144         Object o = mMap.get(key);
1145         if (o == null) {
1146             return null;
1147         }
1148         try {
1149             return (Bundle) o;
1150         } catch (ClassCastException e) {
1151             typeWarning(key, o, "Bundle", e);
1152             return null;
1153         }
1154     }
1155 
1156     /**
1157      * Returns the value associated with the given key, or null if
1158      * no mapping of the desired type exists for the given key or a null
1159      * value is explicitly associated with the key.
1160      *
1161      * @param key a String, or null
1162      * @return a Parcelable value, or null
1163      */
getParcelable(String key)1164     public <T extends Parcelable> T getParcelable(String key) {
1165         unparcel();
1166         Object o = mMap.get(key);
1167         if (o == null) {
1168             return null;
1169         }
1170         try {
1171             return (T) o;
1172         } catch (ClassCastException e) {
1173             typeWarning(key, o, "Parcelable", e);
1174             return null;
1175         }
1176     }
1177 
1178     /**
1179      * Returns the value associated with the given key, or null if
1180      * no mapping of the desired type exists for the given key or a null
1181      * value is explicitly associated with the key.
1182      *
1183      * @param key a String, or null
1184      * @return a Parcelable[] value, or null
1185      */
getParcelableArray(String key)1186     public Parcelable[] getParcelableArray(String key) {
1187         unparcel();
1188         Object o = mMap.get(key);
1189         if (o == null) {
1190             return null;
1191         }
1192         try {
1193             return (Parcelable[]) o;
1194         } catch (ClassCastException e) {
1195             typeWarning(key, o, "Parcelable[]", e);
1196             return null;
1197         }
1198     }
1199 
1200     /**
1201      * Returns the value associated with the given key, or null if
1202      * no mapping of the desired type exists for the given key or a null
1203      * value is explicitly associated with the key.
1204      *
1205      * @param key a String, or null
1206      * @return an ArrayList<T> value, or null
1207      */
getParcelableArrayList(String key)1208     public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String key) {
1209         unparcel();
1210         Object o = mMap.get(key);
1211         if (o == null) {
1212             return null;
1213         }
1214         try {
1215             return (ArrayList<T>) o;
1216         } catch (ClassCastException e) {
1217             typeWarning(key, o, "ArrayList", e);
1218             return null;
1219         }
1220     }
1221 
1222     /**
1223      * Returns the value associated with the given key, or null if
1224      * no mapping of the desired type exists for the given key or a null
1225      * value is explicitly associated with the key.
1226      *
1227      * @param key a String, or null
1228      *
1229      * @return a SparseArray of T values, or null
1230      */
getSparseParcelableArray(String key)1231     public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(String key) {
1232         unparcel();
1233         Object o = mMap.get(key);
1234         if (o == null) {
1235             return null;
1236         }
1237         try {
1238             return (SparseArray<T>) o;
1239         } catch (ClassCastException e) {
1240             typeWarning(key, o, "SparseArray", e);
1241             return null;
1242         }
1243     }
1244 
1245     /**
1246      * Returns the value associated with the given key, or null if
1247      * no mapping of the desired type exists for the given key or a null
1248      * value is explicitly associated with the key.
1249      *
1250      * @param key a String, or null
1251      * @return a Serializable value, or null
1252      */
getSerializable(String key)1253     public Serializable getSerializable(String key) {
1254         unparcel();
1255         Object o = mMap.get(key);
1256         if (o == null) {
1257             return null;
1258         }
1259         try {
1260             return (Serializable) o;
1261         } catch (ClassCastException e) {
1262             typeWarning(key, o, "Serializable", e);
1263             return null;
1264         }
1265     }
1266 
1267     /**
1268      * Returns the value associated with the given key, or null if
1269      * no mapping of the desired type exists for the given key or a null
1270      * value is explicitly associated with the key.
1271      *
1272      * @param key a String, or null
1273      * @return an ArrayList<String> value, or null
1274      */
getIntegerArrayList(String key)1275     public ArrayList<Integer> getIntegerArrayList(String key) {
1276         unparcel();
1277         Object o = mMap.get(key);
1278         if (o == null) {
1279             return null;
1280         }
1281         try {
1282             return (ArrayList<Integer>) o;
1283         } catch (ClassCastException e) {
1284             typeWarning(key, o, "ArrayList<Integer>", e);
1285             return null;
1286         }
1287     }
1288 
1289     /**
1290      * Returns the value associated with the given key, or null if
1291      * no mapping of the desired type exists for the given key or a null
1292      * value is explicitly associated with the key.
1293      *
1294      * @param key a String, or null
1295      * @return an ArrayList<String> value, or null
1296      */
getStringArrayList(String key)1297     public ArrayList<String> getStringArrayList(String key) {
1298         unparcel();
1299         Object o = mMap.get(key);
1300         if (o == null) {
1301             return null;
1302         }
1303         try {
1304             return (ArrayList<String>) o;
1305         } catch (ClassCastException e) {
1306             typeWarning(key, o, "ArrayList<String>", e);
1307             return null;
1308         }
1309     }
1310 
1311     /**
1312      * Returns the value associated with the given key, or null if
1313      * no mapping of the desired type exists for the given key or a null
1314      * value is explicitly associated with the key.
1315      *
1316      * @param key a String, or null
1317      * @return an ArrayList<CharSequence> value, or null
1318      */
getCharSequenceArrayList(String key)1319     public ArrayList<CharSequence> getCharSequenceArrayList(String key) {
1320         unparcel();
1321         Object o = mMap.get(key);
1322         if (o == null) {
1323             return null;
1324         }
1325         try {
1326             return (ArrayList<CharSequence>) o;
1327         } catch (ClassCastException e) {
1328             typeWarning(key, o, "ArrayList<CharSequence>", e);
1329             return null;
1330         }
1331     }
1332 
1333     /**
1334      * Returns the value associated with the given key, or null if
1335      * no mapping of the desired type exists for the given key or a null
1336      * value is explicitly associated with the key.
1337      *
1338      * @param key a String, or null
1339      * @return a boolean[] value, or null
1340      */
getBooleanArray(String key)1341     public boolean[] getBooleanArray(String key) {
1342         unparcel();
1343         Object o = mMap.get(key);
1344         if (o == null) {
1345             return null;
1346         }
1347         try {
1348             return (boolean[]) o;
1349         } catch (ClassCastException e) {
1350             typeWarning(key, o, "byte[]", e);
1351             return null;
1352         }
1353     }
1354 
1355     /**
1356      * Returns the value associated with the given key, or null if
1357      * no mapping of the desired type exists for the given key or a null
1358      * value is explicitly associated with the key.
1359      *
1360      * @param key a String, or null
1361      * @return a byte[] value, or null
1362      */
getByteArray(String key)1363     public byte[] getByteArray(String key) {
1364         unparcel();
1365         Object o = mMap.get(key);
1366         if (o == null) {
1367             return null;
1368         }
1369         try {
1370             return (byte[]) o;
1371         } catch (ClassCastException e) {
1372             typeWarning(key, o, "byte[]", e);
1373             return null;
1374         }
1375     }
1376 
1377     /**
1378      * Returns the value associated with the given key, or null if
1379      * no mapping of the desired type exists for the given key or a null
1380      * value is explicitly associated with the key.
1381      *
1382      * @param key a String, or null
1383      * @return a short[] value, or null
1384      */
getShortArray(String key)1385     public short[] getShortArray(String key) {
1386         unparcel();
1387         Object o = mMap.get(key);
1388         if (o == null) {
1389             return null;
1390         }
1391         try {
1392             return (short[]) o;
1393         } catch (ClassCastException e) {
1394             typeWarning(key, o, "short[]", e);
1395             return null;
1396         }
1397     }
1398 
1399     /**
1400      * Returns the value associated with the given key, or null if
1401      * no mapping of the desired type exists for the given key or a null
1402      * value is explicitly associated with the key.
1403      *
1404      * @param key a String, or null
1405      * @return a char[] value, or null
1406      */
getCharArray(String key)1407     public char[] getCharArray(String key) {
1408         unparcel();
1409         Object o = mMap.get(key);
1410         if (o == null) {
1411             return null;
1412         }
1413         try {
1414             return (char[]) o;
1415         } catch (ClassCastException e) {
1416             typeWarning(key, o, "char[]", e);
1417             return null;
1418         }
1419     }
1420 
1421     /**
1422      * Returns the value associated with the given key, or null if
1423      * no mapping of the desired type exists for the given key or a null
1424      * value is explicitly associated with the key.
1425      *
1426      * @param key a String, or null
1427      * @return an int[] value, or null
1428      */
getIntArray(String key)1429     public int[] getIntArray(String key) {
1430         unparcel();
1431         Object o = mMap.get(key);
1432         if (o == null) {
1433             return null;
1434         }
1435         try {
1436             return (int[]) o;
1437         } catch (ClassCastException e) {
1438             typeWarning(key, o, "int[]", e);
1439             return null;
1440         }
1441     }
1442 
1443     /**
1444      * Returns the value associated with the given key, or null if
1445      * no mapping of the desired type exists for the given key or a null
1446      * value is explicitly associated with the key.
1447      *
1448      * @param key a String, or null
1449      * @return a long[] value, or null
1450      */
getLongArray(String key)1451     public long[] getLongArray(String key) {
1452         unparcel();
1453         Object o = mMap.get(key);
1454         if (o == null) {
1455             return null;
1456         }
1457         try {
1458             return (long[]) o;
1459         } catch (ClassCastException e) {
1460             typeWarning(key, o, "long[]", e);
1461             return null;
1462         }
1463     }
1464 
1465     /**
1466      * Returns the value associated with the given key, or null if
1467      * no mapping of the desired type exists for the given key or a null
1468      * value is explicitly associated with the key.
1469      *
1470      * @param key a String, or null
1471      * @return a float[] value, or null
1472      */
getFloatArray(String key)1473     public float[] getFloatArray(String key) {
1474         unparcel();
1475         Object o = mMap.get(key);
1476         if (o == null) {
1477             return null;
1478         }
1479         try {
1480             return (float[]) o;
1481         } catch (ClassCastException e) {
1482             typeWarning(key, o, "float[]", e);
1483             return null;
1484         }
1485     }
1486 
1487     /**
1488      * Returns the value associated with the given key, or null if
1489      * no mapping of the desired type exists for the given key or a null
1490      * value is explicitly associated with the key.
1491      *
1492      * @param key a String, or null
1493      * @return a double[] value, or null
1494      */
getDoubleArray(String key)1495     public double[] getDoubleArray(String key) {
1496         unparcel();
1497         Object o = mMap.get(key);
1498         if (o == null) {
1499             return null;
1500         }
1501         try {
1502             return (double[]) o;
1503         } catch (ClassCastException e) {
1504             typeWarning(key, o, "double[]", e);
1505             return null;
1506         }
1507     }
1508 
1509     /**
1510      * Returns the value associated with the given key, or null if
1511      * no mapping of the desired type exists for the given key or a null
1512      * value is explicitly associated with the key.
1513      *
1514      * @param key a String, or null
1515      * @return a String[] value, or null
1516      */
getStringArray(String key)1517     public String[] getStringArray(String key) {
1518         unparcel();
1519         Object o = mMap.get(key);
1520         if (o == null) {
1521             return null;
1522         }
1523         try {
1524             return (String[]) o;
1525         } catch (ClassCastException e) {
1526             typeWarning(key, o, "String[]", e);
1527             return null;
1528         }
1529     }
1530 
1531     /**
1532      * Returns the value associated with the given key, or null if
1533      * no mapping of the desired type exists for the given key or a null
1534      * value is explicitly associated with the key.
1535      *
1536      * @param key a String, or null
1537      * @return a CharSequence[] value, or null
1538      */
getCharSequenceArray(String key)1539     public CharSequence[] getCharSequenceArray(String key) {
1540         unparcel();
1541         Object o = mMap.get(key);
1542         if (o == null) {
1543             return null;
1544         }
1545         try {
1546             return (CharSequence[]) o;
1547         } catch (ClassCastException e) {
1548             typeWarning(key, o, "CharSequence[]", e);
1549             return null;
1550         }
1551     }
1552 
1553     /**
1554      * Returns the value associated with the given key, or null if
1555      * no mapping of the desired type exists for the given key or a null
1556      * value is explicitly associated with the key.
1557      *
1558      * @param key a String, or null
1559      * @return an IBinder value, or null
1560      *
1561      * @deprecated
1562      * @hide
1563      */
1564     @Deprecated
getIBinder(String key)1565     public IBinder getIBinder(String key) {
1566         unparcel();
1567         Object o = mMap.get(key);
1568         if (o == null) {
1569             return null;
1570         }
1571         try {
1572             return (IBinder) o;
1573         } catch (ClassCastException e) {
1574             typeWarning(key, o, "IBinder", e);
1575             return null;
1576         }
1577     }
1578 
1579     public static final Parcelable.Creator<Bundle> CREATOR =
1580         new Parcelable.Creator<Bundle>() {
1581         public Bundle createFromParcel(Parcel in) {
1582             return in.readBundle();
1583         }
1584 
1585         public Bundle[] newArray(int size) {
1586             return new Bundle[size];
1587         }
1588     };
1589 
1590     /**
1591      * Report the nature of this Parcelable's contents
1592      */
describeContents()1593     public int describeContents() {
1594         int mask = 0;
1595         if (hasFileDescriptors()) {
1596             mask |= Parcelable.CONTENTS_FILE_DESCRIPTOR;
1597         }
1598         return mask;
1599     }
1600 
1601     /**
1602      * Writes the Bundle contents to a Parcel, typically in order for
1603      * it to be passed through an IBinder connection.
1604      * @param parcel The parcel to copy this bundle to.
1605      */
writeToParcel(Parcel parcel, int flags)1606     public void writeToParcel(Parcel parcel, int flags) {
1607         final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
1608         try {
1609             if (mParcelledData != null) {
1610                 int length = mParcelledData.dataSize();
1611                 parcel.writeInt(length);
1612                 parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
1613                 parcel.appendFrom(mParcelledData, 0, length);
1614             } else {
1615                 parcel.writeInt(-1); // dummy, will hold length
1616                 parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
1617 
1618                 int oldPos = parcel.dataPosition();
1619                 parcel.writeMapInternal(mMap);
1620                 int newPos = parcel.dataPosition();
1621 
1622                 // Backpatch length
1623                 parcel.setDataPosition(oldPos - 8);
1624                 int length = newPos - oldPos;
1625                 parcel.writeInt(length);
1626                 parcel.setDataPosition(newPos);
1627             }
1628         } finally {
1629             parcel.restoreAllowFds(oldAllowFds);
1630         }
1631     }
1632 
1633     /**
1634      * Reads the Parcel contents into this Bundle, typically in order for
1635      * it to be passed through an IBinder connection.
1636      * @param parcel The parcel to overwrite this bundle from.
1637      */
readFromParcel(Parcel parcel)1638     public void readFromParcel(Parcel parcel) {
1639         int length = parcel.readInt();
1640         if (length < 0) {
1641             throw new RuntimeException("Bad length in parcel: " + length);
1642         }
1643         readFromParcelInner(parcel, length);
1644     }
1645 
readFromParcelInner(Parcel parcel, int length)1646     void readFromParcelInner(Parcel parcel, int length) {
1647         int magic = parcel.readInt();
1648         if (magic != 0x4C444E42) {
1649             //noinspection ThrowableInstanceNeverThrown
1650             String st = Log.getStackTraceString(new RuntimeException());
1651             Log.e("Bundle", "readBundle: bad magic number");
1652             Log.e("Bundle", "readBundle: trace = " + st);
1653         }
1654 
1655         // Advance within this Parcel
1656         int offset = parcel.dataPosition();
1657         parcel.setDataPosition(offset + length);
1658 
1659         Parcel p = Parcel.obtain();
1660         p.setDataPosition(0);
1661         p.appendFrom(parcel, offset, length);
1662         p.setDataPosition(0);
1663 
1664         mParcelledData = p;
1665         mHasFds = p.hasFileDescriptors();
1666         mFdsKnown = true;
1667     }
1668 
1669     @Override
toString()1670     public synchronized String toString() {
1671         if (mParcelledData != null) {
1672             return "Bundle[mParcelledData.dataSize=" +
1673                     mParcelledData.dataSize() + "]";
1674         }
1675         return "Bundle[" + mMap.toString() + "]";
1676     }
1677 }
1678