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