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