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