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