1 /*
2  * Copyright (C) 2014 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.annotation.Nullable;
20 import android.util.ArrayMap;
21 import android.util.Log;
22 import android.util.MathUtils;
23 import android.util.Slog;
24 
25 import java.io.Serializable;
26 import java.util.ArrayList;
27 import java.util.Set;
28 
29 /**
30  * A mapping from String keys to values of various types. In most cases, you
31  * should work directly with either the {@link Bundle} or
32  * {@link PersistableBundle} subclass.
33  */
34 public class BaseBundle {
35     private static final String TAG = "Bundle";
36     static final boolean DEBUG = false;
37 
38     // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
39     static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
40 
41     /**
42      * Flag indicating that this Bundle is okay to "defuse." That is, it's okay
43      * for system processes to ignore any {@link BadParcelableException}
44      * encountered when unparceling it, leaving an empty bundle in its place.
45      * <p>
46      * This should <em>only</em> be set when the Bundle reaches its final
47      * destination, otherwise a system process may clobber contents that were
48      * destined for an app that could have unparceled them.
49      */
50     static final int FLAG_DEFUSABLE = 1 << 0;
51 
52     private static final boolean LOG_DEFUSABLE = false;
53 
54     private static volatile boolean sShouldDefuse = false;
55 
56     /**
57      * Set global variable indicating that any Bundles parsed in this process
58      * should be "defused." That is, any {@link BadParcelableException}
59      * encountered will be suppressed and logged, leaving an empty Bundle
60      * instead of crashing.
61      *
62      * @hide
63      */
setShouldDefuse(boolean shouldDefuse)64     public static void setShouldDefuse(boolean shouldDefuse) {
65         sShouldDefuse = shouldDefuse;
66     }
67 
68     // A parcel cannot be obtained during compile-time initialization. Put the
69     // empty parcel into an inner class that can be initialized separately. This
70     // allows to initialize BaseBundle, and classes depending on it.
71     /** {@hide} */
72     static final class NoImagePreloadHolder {
73         public static final Parcel EMPTY_PARCEL = Parcel.obtain();
74     }
75 
76     // Invariant - exactly one of mMap / mParcelledData will be null
77     // (except inside a call to unparcel)
78 
79     ArrayMap<String, Object> mMap = null;
80 
81     /*
82      * If mParcelledData is non-null, then mMap will be null and the
83      * data are stored as a Parcel containing a Bundle.  When the data
84      * are unparcelled, mParcelledData willbe set to null.
85      */
86     Parcel mParcelledData = null;
87 
88     /**
89      * The ClassLoader used when unparcelling data from mParcelledData.
90      */
91     private ClassLoader mClassLoader;
92 
93     /** {@hide} */
94     int mFlags;
95 
96     /**
97      * Constructs a new, empty Bundle that uses a specific ClassLoader for
98      * instantiating Parcelable and Serializable objects.
99      *
100      * @param loader An explicit ClassLoader to use when instantiating objects
101      * inside of the Bundle.
102      * @param capacity Initial size of the ArrayMap.
103      */
BaseBundle(@ullable ClassLoader loader, int capacity)104     BaseBundle(@Nullable ClassLoader loader, int capacity) {
105         mMap = capacity > 0 ?
106                 new ArrayMap<String, Object>(capacity) : new ArrayMap<String, Object>();
107         mClassLoader = loader == null ? getClass().getClassLoader() : loader;
108     }
109 
110     /**
111      * Constructs a new, empty Bundle.
112      */
BaseBundle()113     BaseBundle() {
114         this((ClassLoader) null, 0);
115     }
116 
117     /**
118      * Constructs a Bundle whose data is stored as a Parcel.  The data
119      * will be unparcelled on first contact, using the assigned ClassLoader.
120      *
121      * @param parcelledData a Parcel containing a Bundle
122      */
BaseBundle(Parcel parcelledData)123     BaseBundle(Parcel parcelledData) {
124         readFromParcelInner(parcelledData);
125     }
126 
BaseBundle(Parcel parcelledData, int length)127     BaseBundle(Parcel parcelledData, int length) {
128         readFromParcelInner(parcelledData, length);
129     }
130 
131     /**
132      * Constructs a new, empty Bundle that uses a specific ClassLoader for
133      * instantiating Parcelable and Serializable objects.
134      *
135      * @param loader An explicit ClassLoader to use when instantiating objects
136      * inside of the Bundle.
137      */
BaseBundle(ClassLoader loader)138     BaseBundle(ClassLoader loader) {
139         this(loader, 0);
140     }
141 
142     /**
143      * Constructs a new, empty Bundle sized to hold the given number of
144      * elements. The Bundle will grow as needed.
145      *
146      * @param capacity the initial capacity of the Bundle
147      */
BaseBundle(int capacity)148     BaseBundle(int capacity) {
149         this((ClassLoader) null, capacity);
150     }
151 
152     /**
153      * Constructs a Bundle containing a copy of the mappings from the given
154      * Bundle.
155      *
156      * @param b a Bundle to be copied.
157      */
BaseBundle(BaseBundle b)158     BaseBundle(BaseBundle b) {
159         copyInternal(b, false);
160     }
161 
162     /**
163      * Special constructor that does not initialize the bundle.
164      */
BaseBundle(boolean doInit)165     BaseBundle(boolean doInit) {
166     }
167 
168     /**
169      * TODO: optimize this later (getting just the value part of a Bundle
170      * with a single pair) once Bundle.forPair() above is implemented
171      * with a special single-value Map implementation/serialization.
172      *
173      * Note: value in single-pair Bundle may be null.
174      *
175      * @hide
176      */
getPairValue()177     public String getPairValue() {
178         unparcel();
179         int size = mMap.size();
180         if (size > 1) {
181             Log.w(TAG, "getPairValue() used on Bundle with multiple pairs.");
182         }
183         if (size == 0) {
184             return null;
185         }
186         Object o = mMap.valueAt(0);
187         try {
188             return (String) o;
189         } catch (ClassCastException e) {
190             typeWarning("getPairValue()", o, "String", e);
191             return null;
192         }
193     }
194 
195     /**
196      * Changes the ClassLoader this Bundle uses when instantiating objects.
197      *
198      * @param loader An explicit ClassLoader to use when instantiating objects
199      * inside of the Bundle.
200      */
setClassLoader(ClassLoader loader)201     void setClassLoader(ClassLoader loader) {
202         mClassLoader = loader;
203     }
204 
205     /**
206      * Return the ClassLoader currently associated with this Bundle.
207      */
getClassLoader()208     ClassLoader getClassLoader() {
209         return mClassLoader;
210     }
211 
212     /**
213      * If the underlying data are stored as a Parcel, unparcel them
214      * using the currently assigned class loader.
215      */
unparcel()216     /* package */ void unparcel() {
217         synchronized (this) {
218             final Parcel parcelledData = mParcelledData;
219             if (parcelledData == null) {
220                 if (DEBUG) Log.d(TAG, "unparcel "
221                         + Integer.toHexString(System.identityHashCode(this))
222                         + ": no parcelled data");
223                 return;
224             }
225 
226             if (LOG_DEFUSABLE && sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) {
227                 Slog.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may "
228                         + "clobber all data inside!", new Throwable());
229             }
230 
231             if (isEmptyParcel()) {
232                 if (DEBUG) Log.d(TAG, "unparcel "
233                         + Integer.toHexString(System.identityHashCode(this)) + ": empty");
234                 if (mMap == null) {
235                     mMap = new ArrayMap<>(1);
236                 } else {
237                     mMap.erase();
238                 }
239                 mParcelledData = null;
240                 return;
241             }
242 
243             int N = parcelledData.readInt();
244             if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
245                     + ": reading " + N + " maps");
246             if (N < 0) {
247                 return;
248             }
249             ArrayMap<String, Object> map = mMap;
250             if (map == null) {
251                 map = new ArrayMap<>(N);
252             } else {
253                 map.erase();
254                 map.ensureCapacity(N);
255             }
256             try {
257                 parcelledData.readArrayMapInternal(map, N, mClassLoader);
258             } catch (BadParcelableException e) {
259                 if (sShouldDefuse) {
260                     Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
261                     map.erase();
262                 } else {
263                     throw e;
264                 }
265             } finally {
266                 mMap = map;
267                 parcelledData.recycle();
268                 mParcelledData = null;
269             }
270             if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
271                     + " final map: " + mMap);
272         }
273     }
274 
275     /**
276      * @hide
277      */
isParcelled()278     public boolean isParcelled() {
279         return mParcelledData != null;
280     }
281 
282     /**
283      * @hide
284      */
isEmptyParcel()285     public boolean isEmptyParcel() {
286         return mParcelledData == NoImagePreloadHolder.EMPTY_PARCEL;
287     }
288 
289     /** @hide */
getMap()290     ArrayMap<String, Object> getMap() {
291         unparcel();
292         return mMap;
293     }
294 
295     /**
296      * Returns the number of mappings contained in this Bundle.
297      *
298      * @return the number of mappings as an int.
299      */
size()300     public int size() {
301         unparcel();
302         return mMap.size();
303     }
304 
305     /**
306      * Returns true if the mapping of this Bundle is empty, false otherwise.
307      */
isEmpty()308     public boolean isEmpty() {
309         unparcel();
310         return mMap.isEmpty();
311     }
312 
313     /**
314      * @hide this should probably be the implementation of isEmpty().  To do that we
315      * need to ensure we always use the special empty parcel form when the bundle is
316      * empty.  (This may already be the case, but to be safe we'll do this later when
317      * we aren't trying to stabilize.)
318      */
maybeIsEmpty()319     public boolean maybeIsEmpty() {
320         if (isParcelled()) {
321             return isEmptyParcel();
322         } else {
323             return isEmpty();
324         }
325     }
326 
327     /**
328      * @hide This kind-of does an equality comparison.  Kind-of.
329      */
kindofEquals(BaseBundle other)330     public boolean kindofEquals(BaseBundle other) {
331         if (other == null) {
332             return false;
333         }
334         if (isParcelled() != other.isParcelled()) {
335             // Big kind-of here!
336             return false;
337         } else if (isParcelled()) {
338             return mParcelledData.compareData(other.mParcelledData) == 0;
339         } else {
340             return mMap.equals(other.mMap);
341         }
342     }
343 
344     /**
345      * Removes all elements from the mapping of this Bundle.
346      */
clear()347     public void clear() {
348         unparcel();
349         mMap.clear();
350     }
351 
copyInternal(BaseBundle from, boolean deep)352     void copyInternal(BaseBundle from, boolean deep) {
353         synchronized (from) {
354             if (from.mParcelledData != null) {
355                 if (from.isEmptyParcel()) {
356                     mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
357                 } else {
358                     mParcelledData = Parcel.obtain();
359                     mParcelledData.appendFrom(from.mParcelledData, 0,
360                             from.mParcelledData.dataSize());
361                     mParcelledData.setDataPosition(0);
362                 }
363             } else {
364                 mParcelledData = null;
365             }
366 
367             if (from.mMap != null) {
368                 if (!deep) {
369                     mMap = new ArrayMap<>(from.mMap);
370                 } else {
371                     final ArrayMap<String, Object> fromMap = from.mMap;
372                     final int N = fromMap.size();
373                     mMap = new ArrayMap<>(N);
374                     for (int i = 0; i < N; i++) {
375                         mMap.append(fromMap.keyAt(i), deepCopyValue(fromMap.valueAt(i)));
376                     }
377                 }
378             } else {
379                 mMap = null;
380             }
381 
382             mClassLoader = from.mClassLoader;
383         }
384     }
385 
deepCopyValue(Object value)386     Object deepCopyValue(Object value) {
387         if (value == null) {
388             return null;
389         }
390         if (value instanceof Bundle) {
391             return ((Bundle)value).deepCopy();
392         } else if (value instanceof PersistableBundle) {
393             return ((PersistableBundle)value).deepCopy();
394         } else if (value instanceof ArrayList) {
395             return deepcopyArrayList((ArrayList) value);
396         } else if (value.getClass().isArray()) {
397             if (value instanceof int[]) {
398                 return ((int[])value).clone();
399             } else if (value instanceof long[]) {
400                 return ((long[])value).clone();
401             } else if (value instanceof float[]) {
402                 return ((float[])value).clone();
403             } else if (value instanceof double[]) {
404                 return ((double[])value).clone();
405             } else if (value instanceof Object[]) {
406                 return ((Object[])value).clone();
407             } else if (value instanceof byte[]) {
408                 return ((byte[])value).clone();
409             } else if (value instanceof short[]) {
410                 return ((short[])value).clone();
411             } else if (value instanceof char[]) {
412                 return ((char[]) value).clone();
413             }
414         }
415         return value;
416     }
417 
deepcopyArrayList(ArrayList from)418     ArrayList deepcopyArrayList(ArrayList from) {
419         final int N = from.size();
420         ArrayList out = new ArrayList(N);
421         for (int i=0; i<N; i++) {
422             out.add(deepCopyValue(from.get(i)));
423         }
424         return out;
425     }
426 
427     /**
428      * Returns true if the given key is contained in the mapping
429      * of this Bundle.
430      *
431      * @param key a String key
432      * @return true if the key is part of the mapping, false otherwise
433      */
containsKey(String key)434     public boolean containsKey(String key) {
435         unparcel();
436         return mMap.containsKey(key);
437     }
438 
439     /**
440      * Returns the entry with the given key as an object.
441      *
442      * @param key a String key
443      * @return an Object, or null
444      */
445     @Nullable
get(String key)446     public Object get(String key) {
447         unparcel();
448         return mMap.get(key);
449     }
450 
451     /**
452      * Removes any entry with the given key from the mapping of this Bundle.
453      *
454      * @param key a String key
455      */
remove(String key)456     public void remove(String key) {
457         unparcel();
458         mMap.remove(key);
459     }
460 
461     /**
462      * Inserts all mappings from the given PersistableBundle into this BaseBundle.
463      *
464      * @param bundle a PersistableBundle
465      */
putAll(PersistableBundle bundle)466     public void putAll(PersistableBundle bundle) {
467         unparcel();
468         bundle.unparcel();
469         mMap.putAll(bundle.mMap);
470     }
471 
472     /**
473      * Inserts all mappings from the given Map into this BaseBundle.
474      *
475      * @param map a Map
476      */
putAll(ArrayMap map)477     void putAll(ArrayMap map) {
478         unparcel();
479         mMap.putAll(map);
480     }
481 
482     /**
483      * Returns a Set containing the Strings used as keys in this Bundle.
484      *
485      * @return a Set of String keys
486      */
keySet()487     public Set<String> keySet() {
488         unparcel();
489         return mMap.keySet();
490     }
491 
492     /**
493      * Inserts a Boolean 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 boolean
498      */
putBoolean(@ullable String key, boolean value)499     public void putBoolean(@Nullable String key, boolean value) {
500         unparcel();
501         mMap.put(key, value);
502     }
503 
504     /**
505      * Inserts a byte value into the mapping of this Bundle, replacing
506      * any existing value for the given key.
507      *
508      * @param key a String, or null
509      * @param value a byte
510      */
putByte(@ullable String key, byte value)511     void putByte(@Nullable String key, byte value) {
512         unparcel();
513         mMap.put(key, value);
514     }
515 
516     /**
517      * Inserts a char value into the mapping of this Bundle, replacing
518      * any existing value for the given key.
519      *
520      * @param key a String, or null
521      * @param value a char
522      */
putChar(@ullable String key, char value)523     void putChar(@Nullable String key, char value) {
524         unparcel();
525         mMap.put(key, value);
526     }
527 
528     /**
529      * Inserts a short value into the mapping of this Bundle, replacing
530      * any existing value for the given key.
531      *
532      * @param key a String, or null
533      * @param value a short
534      */
putShort(@ullable String key, short value)535     void putShort(@Nullable String key, short value) {
536         unparcel();
537         mMap.put(key, value);
538     }
539 
540     /**
541      * Inserts an int value into the mapping of this Bundle, replacing
542      * any existing value for the given key.
543      *
544      * @param key a String, or null
545      * @param value an int
546      */
putInt(@ullable String key, int value)547     public void putInt(@Nullable String key, int value) {
548         unparcel();
549         mMap.put(key, value);
550     }
551 
552     /**
553      * Inserts a long value into the mapping of this Bundle, replacing
554      * any existing value for the given key.
555      *
556      * @param key a String, or null
557      * @param value a long
558      */
putLong(@ullable String key, long value)559     public void putLong(@Nullable String key, long value) {
560         unparcel();
561         mMap.put(key, value);
562     }
563 
564     /**
565      * Inserts a float value into the mapping of this Bundle, replacing
566      * any existing value for the given key.
567      *
568      * @param key a String, or null
569      * @param value a float
570      */
putFloat(@ullable String key, float value)571     void putFloat(@Nullable String key, float value) {
572         unparcel();
573         mMap.put(key, value);
574     }
575 
576     /**
577      * Inserts a double value into the mapping of this Bundle, replacing
578      * any existing value for the given key.
579      *
580      * @param key a String, or null
581      * @param value a double
582      */
putDouble(@ullable String key, double value)583     public void putDouble(@Nullable String key, double value) {
584         unparcel();
585         mMap.put(key, value);
586     }
587 
588     /**
589      * Inserts a String 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 a String, or null
594      */
putString(@ullable String key, @Nullable String value)595     public void putString(@Nullable String key, @Nullable String value) {
596         unparcel();
597         mMap.put(key, value);
598     }
599 
600     /**
601      * Inserts a CharSequence 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 CharSequence, or null
606      */
putCharSequence(@ullable String key, @Nullable CharSequence value)607     void putCharSequence(@Nullable String key, @Nullable CharSequence value) {
608         unparcel();
609         mMap.put(key, value);
610     }
611 
612     /**
613      * Inserts an ArrayList<Integer> 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 an ArrayList<Integer> object, or null
618      */
putIntegerArrayList(@ullable String key, @Nullable ArrayList<Integer> value)619     void putIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) {
620         unparcel();
621         mMap.put(key, value);
622     }
623 
624     /**
625      * Inserts an ArrayList<String> 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 an ArrayList<String> object, or null
630      */
putStringArrayList(@ullable String key, @Nullable ArrayList<String> value)631     void putStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) {
632         unparcel();
633         mMap.put(key, value);
634     }
635 
636     /**
637      * Inserts an ArrayList<CharSequence> 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 an ArrayList<CharSequence> object, or null
642      */
putCharSequenceArrayList(@ullable String key, @Nullable ArrayList<CharSequence> value)643     void putCharSequenceArrayList(@Nullable String key, @Nullable ArrayList<CharSequence> value) {
644         unparcel();
645         mMap.put(key, value);
646     }
647 
648     /**
649      * Inserts a Serializable 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 Serializable object, or null
654      */
putSerializable(@ullable String key, @Nullable Serializable value)655     void putSerializable(@Nullable String key, @Nullable Serializable value) {
656         unparcel();
657         mMap.put(key, value);
658     }
659 
660     /**
661      * Inserts a boolean 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 a boolean array object, or null
666      */
putBooleanArray(@ullable String key, @Nullable boolean[] value)667     public void putBooleanArray(@Nullable String key, @Nullable boolean[] value) {
668         unparcel();
669         mMap.put(key, value);
670     }
671 
672     /**
673      * Inserts a byte 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 byte array object, or null
678      */
putByteArray(@ullable String key, @Nullable byte[] value)679     void putByteArray(@Nullable String key, @Nullable byte[] value) {
680         unparcel();
681         mMap.put(key, value);
682     }
683 
684     /**
685      * Inserts a short 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 short array object, or null
690      */
putShortArray(@ullable String key, @Nullable short[] value)691     void putShortArray(@Nullable String key, @Nullable short[] value) {
692         unparcel();
693         mMap.put(key, value);
694     }
695 
696     /**
697      * Inserts a char 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 char array object, or null
702      */
putCharArray(@ullable String key, @Nullable char[] value)703     void putCharArray(@Nullable String key, @Nullable char[] value) {
704         unparcel();
705         mMap.put(key, value);
706     }
707 
708     /**
709      * Inserts an int 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 an int array object, or null
714      */
putIntArray(@ullable String key, @Nullable int[] value)715     public void putIntArray(@Nullable String key, @Nullable int[] value) {
716         unparcel();
717         mMap.put(key, value);
718     }
719 
720     /**
721      * Inserts a long 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 long array object, or null
726      */
putLongArray(@ullable String key, @Nullable long[] value)727     public void putLongArray(@Nullable String key, @Nullable long[] value) {
728         unparcel();
729         mMap.put(key, value);
730     }
731 
732     /**
733      * Inserts a float array 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 float array object, or null
738      */
putFloatArray(@ullable String key, @Nullable float[] value)739     void putFloatArray(@Nullable String key, @Nullable float[] value) {
740         unparcel();
741         mMap.put(key, value);
742     }
743 
744     /**
745      * Inserts a double array value into the mapping of this Bundle, replacing
746      * any existing value for the given key.  Either key or value may be null.
747      *
748      * @param key a String, or null
749      * @param value a double array object, or null
750      */
putDoubleArray(@ullable String key, @Nullable double[] value)751     public void putDoubleArray(@Nullable String key, @Nullable double[] value) {
752         unparcel();
753         mMap.put(key, value);
754     }
755 
756     /**
757      * Inserts a String array value into the mapping of this Bundle, replacing
758      * any existing value for the given key.  Either key or value may be null.
759      *
760      * @param key a String, or null
761      * @param value a String array object, or null
762      */
putStringArray(@ullable String key, @Nullable String[] value)763     public void putStringArray(@Nullable String key, @Nullable String[] value) {
764         unparcel();
765         mMap.put(key, value);
766     }
767 
768     /**
769      * Inserts a CharSequence array value into the mapping of this Bundle, replacing
770      * any existing value for the given key.  Either key or value may be null.
771      *
772      * @param key a String, or null
773      * @param value a CharSequence array object, or null
774      */
putCharSequenceArray(@ullable String key, @Nullable CharSequence[] value)775     void putCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) {
776         unparcel();
777         mMap.put(key, value);
778     }
779 
780     /**
781      * Returns the value associated with the given key, or false if
782      * no mapping of the desired type exists for the given key.
783      *
784      * @param key a String
785      * @return a boolean value
786      */
getBoolean(String key)787     public boolean getBoolean(String key) {
788         unparcel();
789         if (DEBUG) Log.d(TAG, "Getting boolean in "
790                 + Integer.toHexString(System.identityHashCode(this)));
791         return getBoolean(key, false);
792     }
793 
794     // 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)795     void typeWarning(String key, Object value, String className,
796             Object defaultValue, ClassCastException e) {
797         StringBuilder sb = new StringBuilder();
798         sb.append("Key ");
799         sb.append(key);
800         sb.append(" expected ");
801         sb.append(className);
802         sb.append(" but value was a ");
803         sb.append(value.getClass().getName());
804         sb.append(".  The default value ");
805         sb.append(defaultValue);
806         sb.append(" was returned.");
807         Log.w(TAG, sb.toString());
808         Log.w(TAG, "Attempt to cast generated internal exception:", e);
809     }
810 
typeWarning(String key, Object value, String className, ClassCastException e)811     void typeWarning(String key, Object value, String className,
812             ClassCastException e) {
813         typeWarning(key, value, className, "<null>", e);
814     }
815 
816     /**
817      * Returns the value associated with the given key, or defaultValue if
818      * no mapping of the desired type exists for the given key.
819      *
820      * @param key a String
821      * @param defaultValue Value to return if key does not exist
822      * @return a boolean value
823      */
getBoolean(String key, boolean defaultValue)824     public boolean getBoolean(String key, boolean defaultValue) {
825         unparcel();
826         Object o = mMap.get(key);
827         if (o == null) {
828             return defaultValue;
829         }
830         try {
831             return (Boolean) o;
832         } catch (ClassCastException e) {
833             typeWarning(key, o, "Boolean", defaultValue, e);
834             return defaultValue;
835         }
836     }
837 
838     /**
839      * Returns the value associated with the given key, or (byte) 0 if
840      * no mapping of the desired type exists for the given key.
841      *
842      * @param key a String
843      * @return a byte value
844      */
getByte(String key)845     byte getByte(String key) {
846         unparcel();
847         return getByte(key, (byte) 0);
848     }
849 
850     /**
851      * Returns the value associated with the given key, or defaultValue if
852      * no mapping of the desired type exists for the given key.
853      *
854      * @param key a String
855      * @param defaultValue Value to return if key does not exist
856      * @return a byte value
857      */
getByte(String key, byte defaultValue)858     Byte getByte(String key, byte defaultValue) {
859         unparcel();
860         Object o = mMap.get(key);
861         if (o == null) {
862             return defaultValue;
863         }
864         try {
865             return (Byte) o;
866         } catch (ClassCastException e) {
867             typeWarning(key, o, "Byte", defaultValue, e);
868             return defaultValue;
869         }
870     }
871 
872     /**
873      * Returns the value associated with the given key, or (char) 0 if
874      * no mapping of the desired type exists for the given key.
875      *
876      * @param key a String
877      * @return a char value
878      */
getChar(String key)879     char getChar(String key) {
880         unparcel();
881         return getChar(key, (char) 0);
882     }
883 
884     /**
885      * Returns the value associated with the given key, or defaultValue if
886      * no mapping of the desired type exists for the given key.
887      *
888      * @param key a String
889      * @param defaultValue Value to return if key does not exist
890      * @return a char value
891      */
getChar(String key, char defaultValue)892     char getChar(String key, char defaultValue) {
893         unparcel();
894         Object o = mMap.get(key);
895         if (o == null) {
896             return defaultValue;
897         }
898         try {
899             return (Character) o;
900         } catch (ClassCastException e) {
901             typeWarning(key, o, "Character", defaultValue, e);
902             return defaultValue;
903         }
904     }
905 
906     /**
907      * Returns the value associated with the given key, or (short) 0 if
908      * no mapping of the desired type exists for the given key.
909      *
910      * @param key a String
911      * @return a short value
912      */
getShort(String key)913     short getShort(String key) {
914         unparcel();
915         return getShort(key, (short) 0);
916     }
917 
918     /**
919      * Returns the value associated with the given key, or defaultValue if
920      * no mapping of the desired type exists for the given key.
921      *
922      * @param key a String
923      * @param defaultValue Value to return if key does not exist
924      * @return a short value
925      */
getShort(String key, short defaultValue)926     short getShort(String key, short defaultValue) {
927         unparcel();
928         Object o = mMap.get(key);
929         if (o == null) {
930             return defaultValue;
931         }
932         try {
933             return (Short) o;
934         } catch (ClassCastException e) {
935             typeWarning(key, o, "Short", defaultValue, e);
936             return defaultValue;
937         }
938     }
939 
940     /**
941      * Returns the value associated with the given key, or 0 if
942      * no mapping of the desired type exists for the given key.
943      *
944      * @param key a String
945      * @return an int value
946      */
getInt(String key)947     public int getInt(String key) {
948         unparcel();
949         return getInt(key, 0);
950     }
951 
952     /**
953      * Returns the value associated with the given key, or defaultValue if
954      * no mapping of the desired type exists for the given key.
955      *
956      * @param key a String
957      * @param defaultValue Value to return if key does not exist
958      * @return an int value
959      */
getInt(String key, int defaultValue)960    public int getInt(String key, int defaultValue) {
961         unparcel();
962         Object o = mMap.get(key);
963         if (o == null) {
964             return defaultValue;
965         }
966         try {
967             return (Integer) o;
968         } catch (ClassCastException e) {
969             typeWarning(key, o, "Integer", defaultValue, e);
970             return defaultValue;
971         }
972     }
973 
974     /**
975      * Returns the value associated with the given key, or 0L if
976      * no mapping of the desired type exists for the given key.
977      *
978      * @param key a String
979      * @return a long value
980      */
getLong(String key)981     public long getLong(String key) {
982         unparcel();
983         return getLong(key, 0L);
984     }
985 
986     /**
987      * Returns the value associated with the given key, or defaultValue if
988      * no mapping of the desired type exists for the given key.
989      *
990      * @param key a String
991      * @param defaultValue Value to return if key does not exist
992      * @return a long value
993      */
getLong(String key, long defaultValue)994     public long getLong(String key, long defaultValue) {
995         unparcel();
996         Object o = mMap.get(key);
997         if (o == null) {
998             return defaultValue;
999         }
1000         try {
1001             return (Long) o;
1002         } catch (ClassCastException e) {
1003             typeWarning(key, o, "Long", defaultValue, e);
1004             return defaultValue;
1005         }
1006     }
1007 
1008     /**
1009      * Returns the value associated with the given key, or 0.0f if
1010      * no mapping of the desired type exists for the given key.
1011      *
1012      * @param key a String
1013      * @return a float value
1014      */
getFloat(String key)1015     float getFloat(String key) {
1016         unparcel();
1017         return getFloat(key, 0.0f);
1018     }
1019 
1020     /**
1021      * Returns the value associated with the given key, or defaultValue if
1022      * no mapping of the desired type exists for the given key.
1023      *
1024      * @param key a String
1025      * @param defaultValue Value to return if key does not exist
1026      * @return a float value
1027      */
getFloat(String key, float defaultValue)1028     float getFloat(String key, float defaultValue) {
1029         unparcel();
1030         Object o = mMap.get(key);
1031         if (o == null) {
1032             return defaultValue;
1033         }
1034         try {
1035             return (Float) o;
1036         } catch (ClassCastException e) {
1037             typeWarning(key, o, "Float", defaultValue, e);
1038             return defaultValue;
1039         }
1040     }
1041 
1042     /**
1043      * Returns the value associated with the given key, or 0.0 if
1044      * no mapping of the desired type exists for the given key.
1045      *
1046      * @param key a String
1047      * @return a double value
1048      */
getDouble(String key)1049     public double getDouble(String key) {
1050         unparcel();
1051         return getDouble(key, 0.0);
1052     }
1053 
1054     /**
1055      * Returns the value associated with the given key, or defaultValue if
1056      * no mapping of the desired type exists for the given key.
1057      *
1058      * @param key a String
1059      * @param defaultValue Value to return if key does not exist
1060      * @return a double value
1061      */
getDouble(String key, double defaultValue)1062     public double getDouble(String key, double defaultValue) {
1063         unparcel();
1064         Object o = mMap.get(key);
1065         if (o == null) {
1066             return defaultValue;
1067         }
1068         try {
1069             return (Double) o;
1070         } catch (ClassCastException e) {
1071             typeWarning(key, o, "Double", defaultValue, e);
1072             return defaultValue;
1073         }
1074     }
1075 
1076     /**
1077      * Returns the value associated with the given key, or null if
1078      * no mapping of the desired type exists for the given key or a null
1079      * value is explicitly associated with the key.
1080      *
1081      * @param key a String, or null
1082      * @return a String value, or null
1083      */
1084     @Nullable
getString(@ullable String key)1085     public String getString(@Nullable String key) {
1086         unparcel();
1087         final Object o = mMap.get(key);
1088         try {
1089             return (String) o;
1090         } catch (ClassCastException e) {
1091             typeWarning(key, o, "String", e);
1092             return null;
1093         }
1094     }
1095 
1096     /**
1097      * Returns the value associated with the given key, or defaultValue if
1098      * no mapping of the desired type exists for the given key or if a null
1099      * value is explicitly associated with the given key.
1100      *
1101      * @param key a String, or null
1102      * @param defaultValue Value to return if key does not exist or if a null
1103      *     value is associated with the given key.
1104      * @return the String value associated with the given key, or defaultValue
1105      *     if no valid String object is currently mapped to that key.
1106      */
getString(@ullable String key, String defaultValue)1107     public String getString(@Nullable String key, String defaultValue) {
1108         final String s = getString(key);
1109         return (s == null) ? defaultValue : s;
1110     }
1111 
1112     /**
1113      * Returns the value associated with the given key, or null if
1114      * no mapping of the desired type exists for the given key or a null
1115      * value is explicitly associated with the key.
1116      *
1117      * @param key a String, or null
1118      * @return a CharSequence value, or null
1119      */
1120     @Nullable
getCharSequence(@ullable String key)1121     CharSequence getCharSequence(@Nullable String key) {
1122         unparcel();
1123         final Object o = mMap.get(key);
1124         try {
1125             return (CharSequence) o;
1126         } catch (ClassCastException e) {
1127             typeWarning(key, o, "CharSequence", e);
1128             return null;
1129         }
1130     }
1131 
1132     /**
1133      * Returns the value associated with the given key, or defaultValue if
1134      * no mapping of the desired type exists for the given key or if a null
1135      * value is explicitly associated with the given key.
1136      *
1137      * @param key a String, or null
1138      * @param defaultValue Value to return if key does not exist or if a null
1139      *     value is associated with the given key.
1140      * @return the CharSequence value associated with the given key, or defaultValue
1141      *     if no valid CharSequence object is currently mapped to that key.
1142      */
getCharSequence(@ullable String key, CharSequence defaultValue)1143     CharSequence getCharSequence(@Nullable String key, CharSequence defaultValue) {
1144         final CharSequence cs = getCharSequence(key);
1145         return (cs == null) ? defaultValue : cs;
1146     }
1147 
1148     /**
1149      * Returns the value associated with the given key, or null if
1150      * no mapping of the desired type exists for the given key or a null
1151      * value is explicitly associated with the key.
1152      *
1153      * @param key a String, or null
1154      * @return a Serializable value, or null
1155      */
1156     @Nullable
getSerializable(@ullable String key)1157     Serializable getSerializable(@Nullable String key) {
1158         unparcel();
1159         Object o = mMap.get(key);
1160         if (o == null) {
1161             return null;
1162         }
1163         try {
1164             return (Serializable) o;
1165         } catch (ClassCastException e) {
1166             typeWarning(key, o, "Serializable", e);
1167             return null;
1168         }
1169     }
1170 
1171     /**
1172      * Returns the value associated with the given key, or null if
1173      * no mapping of the desired type exists for the given key or a null
1174      * value is explicitly associated with the key.
1175      *
1176      * @param key a String, or null
1177      * @return an ArrayList<String> value, or null
1178      */
1179     @Nullable
getIntegerArrayList(@ullable String key)1180     ArrayList<Integer> getIntegerArrayList(@Nullable String key) {
1181         unparcel();
1182         Object o = mMap.get(key);
1183         if (o == null) {
1184             return null;
1185         }
1186         try {
1187             return (ArrayList<Integer>) o;
1188         } catch (ClassCastException e) {
1189             typeWarning(key, o, "ArrayList<Integer>", e);
1190             return null;
1191         }
1192     }
1193 
1194     /**
1195      * Returns the value associated with the given key, or null if
1196      * no mapping of the desired type exists for the given key or a null
1197      * value is explicitly associated with the key.
1198      *
1199      * @param key a String, or null
1200      * @return an ArrayList<String> value, or null
1201      */
1202     @Nullable
getStringArrayList(@ullable String key)1203     ArrayList<String> getStringArrayList(@Nullable String key) {
1204         unparcel();
1205         Object o = mMap.get(key);
1206         if (o == null) {
1207             return null;
1208         }
1209         try {
1210             return (ArrayList<String>) o;
1211         } catch (ClassCastException e) {
1212             typeWarning(key, o, "ArrayList<String>", e);
1213             return null;
1214         }
1215     }
1216 
1217     /**
1218      * Returns the value associated with the given key, or null if
1219      * no mapping of the desired type exists for the given key or a null
1220      * value is explicitly associated with the key.
1221      *
1222      * @param key a String, or null
1223      * @return an ArrayList<CharSequence> value, or null
1224      */
1225     @Nullable
getCharSequenceArrayList(@ullable String key)1226     ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) {
1227         unparcel();
1228         Object o = mMap.get(key);
1229         if (o == null) {
1230             return null;
1231         }
1232         try {
1233             return (ArrayList<CharSequence>) o;
1234         } catch (ClassCastException e) {
1235             typeWarning(key, o, "ArrayList<CharSequence>", e);
1236             return null;
1237         }
1238     }
1239 
1240     /**
1241      * Returns the value associated with the given key, or null if
1242      * no mapping of the desired type exists for the given key or a null
1243      * value is explicitly associated with the key.
1244      *
1245      * @param key a String, or null
1246      * @return a boolean[] value, or null
1247      */
1248     @Nullable
getBooleanArray(@ullable String key)1249     public boolean[] getBooleanArray(@Nullable String key) {
1250         unparcel();
1251         Object o = mMap.get(key);
1252         if (o == null) {
1253             return null;
1254         }
1255         try {
1256             return (boolean[]) o;
1257         } catch (ClassCastException e) {
1258             typeWarning(key, o, "byte[]", e);
1259             return null;
1260         }
1261     }
1262 
1263     /**
1264      * Returns the value associated with the given key, or null if
1265      * no mapping of the desired type exists for the given key or a null
1266      * value is explicitly associated with the key.
1267      *
1268      * @param key a String, or null
1269      * @return a byte[] value, or null
1270      */
1271     @Nullable
getByteArray(@ullable String key)1272     byte[] getByteArray(@Nullable String key) {
1273         unparcel();
1274         Object o = mMap.get(key);
1275         if (o == null) {
1276             return null;
1277         }
1278         try {
1279             return (byte[]) o;
1280         } catch (ClassCastException e) {
1281             typeWarning(key, o, "byte[]", e);
1282             return null;
1283         }
1284     }
1285 
1286     /**
1287      * Returns the value associated with the given key, or null if
1288      * no mapping of the desired type exists for the given key or a null
1289      * value is explicitly associated with the key.
1290      *
1291      * @param key a String, or null
1292      * @return a short[] value, or null
1293      */
1294     @Nullable
getShortArray(@ullable String key)1295     short[] getShortArray(@Nullable String key) {
1296         unparcel();
1297         Object o = mMap.get(key);
1298         if (o == null) {
1299             return null;
1300         }
1301         try {
1302             return (short[]) o;
1303         } catch (ClassCastException e) {
1304             typeWarning(key, o, "short[]", e);
1305             return null;
1306         }
1307     }
1308 
1309     /**
1310      * Returns the value associated with the given key, or null if
1311      * no mapping of the desired type exists for the given key or a null
1312      * value is explicitly associated with the key.
1313      *
1314      * @param key a String, or null
1315      * @return a char[] value, or null
1316      */
1317     @Nullable
getCharArray(@ullable String key)1318     char[] getCharArray(@Nullable String key) {
1319         unparcel();
1320         Object o = mMap.get(key);
1321         if (o == null) {
1322             return null;
1323         }
1324         try {
1325             return (char[]) o;
1326         } catch (ClassCastException e) {
1327             typeWarning(key, o, "char[]", e);
1328             return null;
1329         }
1330     }
1331 
1332     /**
1333      * Returns the value associated with the given key, or null if
1334      * no mapping of the desired type exists for the given key or a null
1335      * value is explicitly associated with the key.
1336      *
1337      * @param key a String, or null
1338      * @return an int[] value, or null
1339      */
1340     @Nullable
getIntArray(@ullable String key)1341     public int[] getIntArray(@Nullable String key) {
1342         unparcel();
1343         Object o = mMap.get(key);
1344         if (o == null) {
1345             return null;
1346         }
1347         try {
1348             return (int[]) o;
1349         } catch (ClassCastException e) {
1350             typeWarning(key, o, "int[]", e);
1351             return null;
1352         }
1353     }
1354 
1355     /**
1356      * Returns the value associated with the given key, or null if
1357      * no mapping of the desired type exists for the given key or a null
1358      * value is explicitly associated with the key.
1359      *
1360      * @param key a String, or null
1361      * @return a long[] value, or null
1362      */
1363     @Nullable
getLongArray(@ullable String key)1364     public long[] getLongArray(@Nullable String key) {
1365         unparcel();
1366         Object o = mMap.get(key);
1367         if (o == null) {
1368             return null;
1369         }
1370         try {
1371             return (long[]) o;
1372         } catch (ClassCastException e) {
1373             typeWarning(key, o, "long[]", 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 float[] value, or null
1385      */
1386     @Nullable
getFloatArray(@ullable String key)1387     float[] getFloatArray(@Nullable String key) {
1388         unparcel();
1389         Object o = mMap.get(key);
1390         if (o == null) {
1391             return null;
1392         }
1393         try {
1394             return (float[]) o;
1395         } catch (ClassCastException e) {
1396             typeWarning(key, o, "float[]", e);
1397             return null;
1398         }
1399     }
1400 
1401     /**
1402      * Returns the value associated with the given key, or null if
1403      * no mapping of the desired type exists for the given key or a null
1404      * value is explicitly associated with the key.
1405      *
1406      * @param key a String, or null
1407      * @return a double[] value, or null
1408      */
1409     @Nullable
getDoubleArray(@ullable String key)1410     public double[] getDoubleArray(@Nullable String key) {
1411         unparcel();
1412         Object o = mMap.get(key);
1413         if (o == null) {
1414             return null;
1415         }
1416         try {
1417             return (double[]) o;
1418         } catch (ClassCastException e) {
1419             typeWarning(key, o, "double[]", e);
1420             return null;
1421         }
1422     }
1423 
1424     /**
1425      * Returns the value associated with the given key, or null if
1426      * no mapping of the desired type exists for the given key or a null
1427      * value is explicitly associated with the key.
1428      *
1429      * @param key a String, or null
1430      * @return a String[] value, or null
1431      */
1432     @Nullable
getStringArray(@ullable String key)1433     public String[] getStringArray(@Nullable String key) {
1434         unparcel();
1435         Object o = mMap.get(key);
1436         if (o == null) {
1437             return null;
1438         }
1439         try {
1440             return (String[]) o;
1441         } catch (ClassCastException e) {
1442             typeWarning(key, o, "String[]", e);
1443             return null;
1444         }
1445     }
1446 
1447     /**
1448      * Returns the value associated with the given key, or null if
1449      * no mapping of the desired type exists for the given key or a null
1450      * value is explicitly associated with the key.
1451      *
1452      * @param key a String, or null
1453      * @return a CharSequence[] value, or null
1454      */
1455     @Nullable
getCharSequenceArray(@ullable String key)1456     CharSequence[] getCharSequenceArray(@Nullable String key) {
1457         unparcel();
1458         Object o = mMap.get(key);
1459         if (o == null) {
1460             return null;
1461         }
1462         try {
1463             return (CharSequence[]) o;
1464         } catch (ClassCastException e) {
1465             typeWarning(key, o, "CharSequence[]", e);
1466             return null;
1467         }
1468     }
1469 
1470     /**
1471      * Writes the Bundle contents to a Parcel, typically in order for
1472      * it to be passed through an IBinder connection.
1473      * @param parcel The parcel to copy this bundle to.
1474      */
writeToParcelInner(Parcel parcel, int flags)1475     void writeToParcelInner(Parcel parcel, int flags) {
1476         // Keep implementation in sync with writeToParcel() in
1477         // frameworks/native/libs/binder/PersistableBundle.cpp.
1478         final ArrayMap<String, Object> map;
1479         synchronized (this) {
1480             // unparcel() can race with this method and cause the parcel to recycle
1481             // at the wrong time. So synchronize access the mParcelledData's content.
1482             if (mParcelledData != null) {
1483                 if (mParcelledData == NoImagePreloadHolder.EMPTY_PARCEL) {
1484                     parcel.writeInt(0);
1485                 } else {
1486                     int length = mParcelledData.dataSize();
1487                     parcel.writeInt(length);
1488                     parcel.writeInt(BUNDLE_MAGIC);
1489                     parcel.appendFrom(mParcelledData, 0, length);
1490                 }
1491                 return;
1492             }
1493             map = mMap;
1494         }
1495 
1496         // Special case for empty bundles.
1497         if (map == null || map.size() <= 0) {
1498             parcel.writeInt(0);
1499             return;
1500         }
1501         int lengthPos = parcel.dataPosition();
1502         parcel.writeInt(-1); // dummy, will hold length
1503         parcel.writeInt(BUNDLE_MAGIC);
1504 
1505         int startPos = parcel.dataPosition();
1506         parcel.writeArrayMapInternal(map);
1507         int endPos = parcel.dataPosition();
1508 
1509         // Backpatch length
1510         parcel.setDataPosition(lengthPos);
1511         int length = endPos - startPos;
1512         parcel.writeInt(length);
1513         parcel.setDataPosition(endPos);
1514     }
1515 
1516     /**
1517      * Reads the Parcel contents into this Bundle, typically in order for
1518      * it to be passed through an IBinder connection.
1519      * @param parcel The parcel to overwrite this bundle from.
1520      */
readFromParcelInner(Parcel parcel)1521     void readFromParcelInner(Parcel parcel) {
1522         // Keep implementation in sync with readFromParcel() in
1523         // frameworks/native/libs/binder/PersistableBundle.cpp.
1524         int length = parcel.readInt();
1525         readFromParcelInner(parcel, length);
1526     }
1527 
readFromParcelInner(Parcel parcel, int length)1528     private void readFromParcelInner(Parcel parcel, int length) {
1529         if (length < 0) {
1530             throw new RuntimeException("Bad length in parcel: " + length);
1531 
1532         } else if (length == 0) {
1533             // Empty Bundle or end of data.
1534             mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
1535             return;
1536         }
1537 
1538         final int magic = parcel.readInt();
1539         if (magic != BUNDLE_MAGIC) {
1540             throw new IllegalStateException("Bad magic number for Bundle: 0x"
1541                     + Integer.toHexString(magic));
1542         }
1543 
1544         // Advance within this Parcel
1545         int offset = parcel.dataPosition();
1546         parcel.setDataPosition(MathUtils.addOrThrow(offset, length));
1547 
1548         Parcel p = Parcel.obtain();
1549         p.setDataPosition(0);
1550         p.appendFrom(parcel, offset, length);
1551         p.adoptClassCookies(parcel);
1552         if (DEBUG) Log.d(TAG, "Retrieving "  + Integer.toHexString(System.identityHashCode(this))
1553                 + ": " + length + " bundle bytes starting at " + offset);
1554         p.setDataPosition(0);
1555 
1556         mParcelledData = p;
1557     }
1558 }
1559