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