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