Bundle.java revision 08bbffb049c135c5dfd40d261118c90d1a6dc111
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 * 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 */ 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 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 */ 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 */ 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 */ 187 public boolean isEmpty() { 188 unparcel(); 189 return mMap.isEmpty(); 190 } 191 192 /** 193 * Removes all elements from the mapping of this Bundle. 194 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 522 public void putStringArrayList(String key, ArrayList<String> value) { 523 unparcel(); 524 mMap.put(key, value); 525 } 526 527 /** 528 * Inserts an ArrayList<CharSequence> 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 an ArrayList<CharSequence> object, or null 533 */ 534 public void putCharSequenceArrayList(String key, ArrayList<CharSequence> value) { 535 unparcel(); 536 mMap.put(key, value); 537 } 538 539 /** 540 * Inserts a Serializable 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 Serializable object, or null 545 */ 546 public void putSerializable(String key, Serializable value) { 547 unparcel(); 548 mMap.put(key, value); 549 } 550 551 /** 552 * Inserts a boolean 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 boolean array object, or null 557 */ 558 public void putBooleanArray(String key, boolean[] value) { 559 unparcel(); 560 mMap.put(key, value); 561 } 562 563 /** 564 * Inserts a byte 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 byte array object, or null 569 */ 570 public void putByteArray(String key, byte[] value) { 571 unparcel(); 572 mMap.put(key, value); 573 } 574 575 /** 576 * Inserts a short 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 short array object, or null 581 */ 582 public void putShortArray(String key, short[] value) { 583 unparcel(); 584 mMap.put(key, value); 585 } 586 587 /** 588 * Inserts a char 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 a char array object, or null 593 */ 594 public void putCharArray(String key, char[] value) { 595 unparcel(); 596 mMap.put(key, value); 597 } 598 599 /** 600 * Inserts an int 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 an int array object, or null 605 */ 606 public void putIntArray(String key, int[] value) { 607 unparcel(); 608 mMap.put(key, value); 609 } 610 611 /** 612 * Inserts a long 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 long array object, or null 617 */ 618 public void putLongArray(String key, long[] value) { 619 unparcel(); 620 mMap.put(key, value); 621 } 622 623 /** 624 * Inserts a float 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 float array object, or null 629 */ 630 public void putFloatArray(String key, float[] value) { 631 unparcel(); 632 mMap.put(key, value); 633 } 634 635 /** 636 * Inserts a double 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 double array object, or null 641 */ 642 public void putDoubleArray(String key, double[] value) { 643 unparcel(); 644 mMap.put(key, value); 645 } 646 647 /** 648 * Inserts a String array 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 String array object, or null 653 */ 654 public void putStringArray(String key, String[] value) { 655 unparcel(); 656 mMap.put(key, value); 657 } 658 659 /** 660 * Inserts a CharSequence array 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 a CharSequence array object, or null 665 */ 666 public void putCharSequenceArray(String key, CharSequence[] value) { 667 unparcel(); 668 mMap.put(key, value); 669 } 670 671 /** 672 * Inserts a Bundle value into the mapping of this Bundle, replacing 673 * any existing value for the given key. Either key or value may be null. 674 * 675 * @param key a String, or null 676 * @param value a Bundle object, or null 677 */ 678 public void putBundle(String key, Bundle value) { 679 unparcel(); 680 mMap.put(key, value); 681 } 682 683 /** 684 * Inserts an IBinder value into the mapping of this Bundle, replacing 685 * any existing value for the given key. Either key or value may be null. 686 * 687 * @param key a String, or null 688 * @param value an IBinder object, or null 689 * 690 * @deprecated 691 * @hide 692 */ 693 @Deprecated 694 public void putIBinder(String key, IBinder value) { 695 unparcel(); 696 mMap.put(key, value); 697 } 698 699 /** 700 * Returns the value associated with the given key, or false if 701 * no mapping of the desired type exists for the given key. 702 * 703 * @param key a String 704 * @return a boolean value 705 */ 706 public boolean getBoolean(String key) { 707 unparcel(); 708 return getBoolean(key, false); 709 } 710 711 // Log a message if the value was non-null but not of the expected type 712 private void typeWarning(String key, Object value, String className, 713 Object defaultValue, ClassCastException e) { 714 StringBuilder sb = new StringBuilder(); 715 sb.append("Key "); 716 sb.append(key); 717 sb.append(" expected "); 718 sb.append(className); 719 sb.append(" but value was a "); 720 sb.append(value.getClass().getName()); 721 sb.append(". The default value "); 722 sb.append(defaultValue); 723 sb.append(" was returned."); 724 Log.w(LOG_TAG, sb.toString()); 725 Log.w(LOG_TAG, "Attempt to cast generated internal exception:", e); 726 } 727 728 private void typeWarning(String key, Object value, String className, 729 ClassCastException e) { 730 typeWarning(key, value, className, "<null>", e); 731 } 732 733 /** 734 * Returns the value associated with the given key, or defaultValue if 735 * no mapping of the desired type exists for the given key. 736 * 737 * @param key a String 738 * @return a boolean value 739 */ 740 public boolean getBoolean(String key, boolean defaultValue) { 741 unparcel(); 742 Object o = mMap.get(key); 743 if (o == null) { 744 return defaultValue; 745 } 746 try { 747 return (Boolean) o; 748 } catch (ClassCastException e) { 749 typeWarning(key, o, "Boolean", defaultValue, e); 750 return defaultValue; 751 } 752 } 753 754 /** 755 * Returns the value associated with the given key, or (byte) 0 if 756 * no mapping of the desired type exists for the given key. 757 * 758 * @param key a String 759 * @return a byte value 760 */ 761 public byte getByte(String key) { 762 unparcel(); 763 return getByte(key, (byte) 0); 764 } 765 766 /** 767 * Returns the value associated with the given key, or defaultValue if 768 * no mapping of the desired type exists for the given key. 769 * 770 * @param key a String 771 * @return a byte value 772 */ 773 public Byte getByte(String key, byte defaultValue) { 774 unparcel(); 775 Object o = mMap.get(key); 776 if (o == null) { 777 return defaultValue; 778 } 779 try { 780 return (Byte) o; 781 } catch (ClassCastException e) { 782 typeWarning(key, o, "Byte", defaultValue, e); 783 return defaultValue; 784 } 785 } 786 787 /** 788 * Returns the value associated with the given key, or false if 789 * no mapping of the desired type exists for the given key. 790 * 791 * @param key a String 792 * @return a char value 793 */ 794 public char getChar(String key) { 795 unparcel(); 796 return getChar(key, (char) 0); 797 } 798 799 /** 800 * Returns the value associated with the given key, or (char) 0 if 801 * no mapping of the desired type exists for the given key. 802 * 803 * @param key a String 804 * @return a char value 805 */ 806 public char getChar(String key, char defaultValue) { 807 unparcel(); 808 Object o = mMap.get(key); 809 if (o == null) { 810 return defaultValue; 811 } 812 try { 813 return (Character) o; 814 } catch (ClassCastException e) { 815 typeWarning(key, o, "Character", defaultValue, e); 816 return defaultValue; 817 } 818 } 819 820 /** 821 * Returns the value associated with the given key, or (short) 0 if 822 * no mapping of the desired type exists for the given key. 823 * 824 * @param key a String 825 * @return a short value 826 */ 827 public short getShort(String key) { 828 unparcel(); 829 return getShort(key, (short) 0); 830 } 831 832 /** 833 * Returns the value associated with the given key, or defaultValue if 834 * no mapping of the desired type exists for the given key. 835 * 836 * @param key a String 837 * @return a short value 838 */ 839 public short getShort(String key, short defaultValue) { 840 unparcel(); 841 Object o = mMap.get(key); 842 if (o == null) { 843 return defaultValue; 844 } 845 try { 846 return (Short) o; 847 } catch (ClassCastException e) { 848 typeWarning(key, o, "Short", defaultValue, e); 849 return defaultValue; 850 } 851 } 852 853 /** 854 * Returns the value associated with the given key, or 0 if 855 * no mapping of the desired type exists for the given key. 856 * 857 * @param key a String 858 * @return an int value 859 */ 860 public int getInt(String key) { 861 unparcel(); 862 return getInt(key, 0); 863 } 864 865 /** 866 * Returns the value associated with the given key, or defaultValue if 867 * no mapping of the desired type exists for the given key. 868 * 869 * @param key a String 870 * @return an int value 871 */ 872 public int getInt(String key, int defaultValue) { 873 unparcel(); 874 Object o = mMap.get(key); 875 if (o == null) { 876 return defaultValue; 877 } 878 try { 879 return (Integer) o; 880 } catch (ClassCastException e) { 881 typeWarning(key, o, "Integer", defaultValue, e); 882 return defaultValue; 883 } 884 } 885 886 /** 887 * Returns the value associated with the given key, or 0L if 888 * no mapping of the desired type exists for the given key. 889 * 890 * @param key a String 891 * @return a long value 892 */ 893 public long getLong(String key) { 894 unparcel(); 895 return getLong(key, 0L); 896 } 897 898 /** 899 * Returns the value associated with the given key, or defaultValue if 900 * no mapping of the desired type exists for the given key. 901 * 902 * @param key a String 903 * @return a long value 904 */ 905 public long getLong(String key, long defaultValue) { 906 unparcel(); 907 Object o = mMap.get(key); 908 if (o == null) { 909 return defaultValue; 910 } 911 try { 912 return (Long) o; 913 } catch (ClassCastException e) { 914 typeWarning(key, o, "Long", defaultValue, e); 915 return defaultValue; 916 } 917 } 918 919 /** 920 * Returns the value associated with the given key, or 0.0f if 921 * no mapping of the desired type exists for the given key. 922 * 923 * @param key a String 924 * @return a float value 925 */ 926 public float getFloat(String key) { 927 unparcel(); 928 return getFloat(key, 0.0f); 929 } 930 931 /** 932 * Returns the value associated with the given key, or defaultValue if 933 * no mapping of the desired type exists for the given key. 934 * 935 * @param key a String 936 * @return a float value 937 */ 938 public float getFloat(String key, float defaultValue) { 939 unparcel(); 940 Object o = mMap.get(key); 941 if (o == null) { 942 return defaultValue; 943 } 944 try { 945 return (Float) o; 946 } catch (ClassCastException e) { 947 typeWarning(key, o, "Float", defaultValue, e); 948 return defaultValue; 949 } 950 } 951 952 /** 953 * Returns the value associated with the given key, or 0.0 if 954 * no mapping of the desired type exists for the given key. 955 * 956 * @param key a String 957 * @return a double value 958 */ 959 public double getDouble(String key) { 960 unparcel(); 961 return getDouble(key, 0.0); 962 } 963 964 /** 965 * Returns the value associated with the given key, or defaultValue if 966 * no mapping of the desired type exists for the given key. 967 * 968 * @param key a String 969 * @return a double value 970 */ 971 public double getDouble(String key, double defaultValue) { 972 unparcel(); 973 Object o = mMap.get(key); 974 if (o == null) { 975 return defaultValue; 976 } 977 try { 978 return (Double) o; 979 } catch (ClassCastException e) { 980 typeWarning(key, o, "Double", defaultValue, e); 981 return defaultValue; 982 } 983 } 984 985 986 /** 987 * Returns the value associated with the given key, or null if 988 * no mapping of the desired type exists for the given key or a null 989 * value is explicitly associated with the key. 990 * 991 * @param key a String, or null 992 * @return a String value, or null 993 */ 994 public String getString(String key) { 995 unparcel(); 996 Object o = mMap.get(key); 997 if (o == null) { 998 return null; 999 } 1000 try { 1001 return (String) o; 1002 } catch (ClassCastException e) { 1003 typeWarning(key, o, "String", e); 1004 return null; 1005 } 1006 } 1007 1008 /** 1009 * Returns the value associated with the given key, or null if 1010 * no mapping of the desired type exists for the given key or a null 1011 * value is explicitly associated with the key. 1012 * 1013 * @param key a String, or null 1014 * @return a CharSequence value, or null 1015 */ 1016 public CharSequence getCharSequence(String key) { 1017 unparcel(); 1018 Object o = mMap.get(key); 1019 if (o == null) { 1020 return null; 1021 } 1022 try { 1023 return (CharSequence) o; 1024 } catch (ClassCastException e) { 1025 typeWarning(key, o, "CharSequence", e); 1026 return null; 1027 } 1028 } 1029 1030 /** 1031 * Returns the value associated with the given key, or null if 1032 * no mapping of the desired type exists for the given key or a null 1033 * value is explicitly associated with the key. 1034 * 1035 * @param key a String, or null 1036 * @return a Bundle value, or null 1037 */ 1038 public Bundle getBundle(String key) { 1039 unparcel(); 1040 Object o = mMap.get(key); 1041 if (o == null) { 1042 return null; 1043 } 1044 try { 1045 return (Bundle) o; 1046 } catch (ClassCastException e) { 1047 typeWarning(key, o, "Bundle", e); 1048 return null; 1049 } 1050 } 1051 1052 /** 1053 * Returns the value associated with the given key, or null if 1054 * no mapping of the desired type exists for the given key or a null 1055 * value is explicitly associated with the key. 1056 * 1057 * @param key a String, or null 1058 * @return a Parcelable value, or null 1059 */ 1060 public <T extends Parcelable> T getParcelable(String key) { 1061 unparcel(); 1062 Object o = mMap.get(key); 1063 if (o == null) { 1064 return null; 1065 } 1066 try { 1067 return (T) o; 1068 } catch (ClassCastException e) { 1069 typeWarning(key, o, "Parcelable", e); 1070 return null; 1071 } 1072 } 1073 1074 /** 1075 * Returns the value associated with the given key, or null if 1076 * no mapping of the desired type exists for the given key or a null 1077 * value is explicitly associated with the key. 1078 * 1079 * @param key a String, or null 1080 * @return a Parcelable[] value, or null 1081 */ 1082 public Parcelable[] getParcelableArray(String key) { 1083 unparcel(); 1084 Object o = mMap.get(key); 1085 if (o == null) { 1086 return null; 1087 } 1088 try { 1089 return (Parcelable[]) o; 1090 } catch (ClassCastException e) { 1091 typeWarning(key, o, "Parcelable[]", e); 1092 return null; 1093 } 1094 } 1095 1096 /** 1097 * Returns the value associated with the given key, or null if 1098 * no mapping of the desired type exists for the given key or a null 1099 * value is explicitly associated with the key. 1100 * 1101 * @param key a String, or null 1102 * @return an ArrayList<T> value, or null 1103 */ 1104 public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String key) { 1105 unparcel(); 1106 Object o = mMap.get(key); 1107 if (o == null) { 1108 return null; 1109 } 1110 try { 1111 return (ArrayList<T>) o; 1112 } catch (ClassCastException e) { 1113 typeWarning(key, o, "ArrayList", e); 1114 return null; 1115 } 1116 } 1117 1118 /** 1119 * Returns the value associated with the given key, or null if 1120 * no mapping of the desired type exists for the given key or a null 1121 * value is explicitly associated with the key. 1122 * 1123 * @param key a String, or null 1124 * 1125 * @return a SparseArray of T values, or null 1126 */ 1127 public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(String key) { 1128 unparcel(); 1129 Object o = mMap.get(key); 1130 if (o == null) { 1131 return null; 1132 } 1133 try { 1134 return (SparseArray<T>) o; 1135 } catch (ClassCastException e) { 1136 typeWarning(key, o, "SparseArray", 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 Serializable value, or null 1148 */ 1149 public Serializable getSerializable(String key) { 1150 unparcel(); 1151 Object o = mMap.get(key); 1152 if (o == null) { 1153 return null; 1154 } 1155 try { 1156 return (Serializable) o; 1157 } catch (ClassCastException e) { 1158 typeWarning(key, o, "Serializable", 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 an ArrayList<String> value, or null 1170 */ 1171 public ArrayList<Integer> getIntegerArrayList(String key) { 1172 unparcel(); 1173 Object o = mMap.get(key); 1174 if (o == null) { 1175 return null; 1176 } 1177 try { 1178 return (ArrayList<Integer>) o; 1179 } catch (ClassCastException e) { 1180 typeWarning(key, o, "ArrayList<Integer>", 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<String> value, or null 1192 */ 1193 public ArrayList<String> getStringArrayList(String key) { 1194 unparcel(); 1195 Object o = mMap.get(key); 1196 if (o == null) { 1197 return null; 1198 } 1199 try { 1200 return (ArrayList<String>) o; 1201 } catch (ClassCastException e) { 1202 typeWarning(key, o, "ArrayList<String>", 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 * @return an ArrayList<CharSequence> value, or null 1214 */ 1215 public ArrayList<CharSequence> getCharSequenceArrayList(String key) { 1216 unparcel(); 1217 Object o = mMap.get(key); 1218 if (o == null) { 1219 return null; 1220 } 1221 try { 1222 return (ArrayList<CharSequence>) o; 1223 } catch (ClassCastException e) { 1224 typeWarning(key, o, "ArrayList<CharSequence>", e); 1225 return null; 1226 } 1227 } 1228 1229 /** 1230 * Returns the value associated with the given key, or null if 1231 * no mapping of the desired type exists for the given key or a null 1232 * value is explicitly associated with the key. 1233 * 1234 * @param key a String, or null 1235 * @return a boolean[] value, or null 1236 */ 1237 public boolean[] getBooleanArray(String key) { 1238 unparcel(); 1239 Object o = mMap.get(key); 1240 if (o == null) { 1241 return null; 1242 } 1243 try { 1244 return (boolean[]) o; 1245 } catch (ClassCastException e) { 1246 typeWarning(key, o, "byte[]", e); 1247 return null; 1248 } 1249 } 1250 1251 /** 1252 * Returns the value associated with the given key, or null if 1253 * no mapping of the desired type exists for the given key or a null 1254 * value is explicitly associated with the key. 1255 * 1256 * @param key a String, or null 1257 * @return a byte[] value, or null 1258 */ 1259 public byte[] getByteArray(String key) { 1260 unparcel(); 1261 Object o = mMap.get(key); 1262 if (o == null) { 1263 return null; 1264 } 1265 try { 1266 return (byte[]) o; 1267 } catch (ClassCastException e) { 1268 typeWarning(key, o, "byte[]", e); 1269 return null; 1270 } 1271 } 1272 1273 /** 1274 * Returns the value associated with the given key, or null if 1275 * no mapping of the desired type exists for the given key or a null 1276 * value is explicitly associated with the key. 1277 * 1278 * @param key a String, or null 1279 * @return a short[] value, or null 1280 */ 1281 public short[] getShortArray(String key) { 1282 unparcel(); 1283 Object o = mMap.get(key); 1284 if (o == null) { 1285 return null; 1286 } 1287 try { 1288 return (short[]) o; 1289 } catch (ClassCastException e) { 1290 typeWarning(key, o, "short[]", e); 1291 return null; 1292 } 1293 } 1294 1295 /** 1296 * Returns the value associated with the given key, or null if 1297 * no mapping of the desired type exists for the given key or a null 1298 * value is explicitly associated with the key. 1299 * 1300 * @param key a String, or null 1301 * @return a char[] value, or null 1302 */ 1303 public char[] getCharArray(String key) { 1304 unparcel(); 1305 Object o = mMap.get(key); 1306 if (o == null) { 1307 return null; 1308 } 1309 try { 1310 return (char[]) o; 1311 } catch (ClassCastException e) { 1312 typeWarning(key, o, "char[]", e); 1313 return null; 1314 } 1315 } 1316 1317 /** 1318 * Returns the value associated with the given key, or null if 1319 * no mapping of the desired type exists for the given key or a null 1320 * value is explicitly associated with the key. 1321 * 1322 * @param key a String, or null 1323 * @return an int[] value, or null 1324 */ 1325 public int[] getIntArray(String key) { 1326 unparcel(); 1327 Object o = mMap.get(key); 1328 if (o == null) { 1329 return null; 1330 } 1331 try { 1332 return (int[]) o; 1333 } catch (ClassCastException e) { 1334 typeWarning(key, o, "int[]", e); 1335 return null; 1336 } 1337 } 1338 1339 /** 1340 * Returns the value associated with the given key, or null if 1341 * no mapping of the desired type exists for the given key or a null 1342 * value is explicitly associated with the key. 1343 * 1344 * @param key a String, or null 1345 * @return a long[] value, or null 1346 */ 1347 public long[] getLongArray(String key) { 1348 unparcel(); 1349 Object o = mMap.get(key); 1350 if (o == null) { 1351 return null; 1352 } 1353 try { 1354 return (long[]) o; 1355 } catch (ClassCastException e) { 1356 typeWarning(key, o, "long[]", e); 1357 return null; 1358 } 1359 } 1360 1361 /** 1362 * Returns the value associated with the given key, or null if 1363 * no mapping of the desired type exists for the given key or a null 1364 * value is explicitly associated with the key. 1365 * 1366 * @param key a String, or null 1367 * @return a float[] value, or null 1368 */ 1369 public float[] getFloatArray(String key) { 1370 unparcel(); 1371 Object o = mMap.get(key); 1372 if (o == null) { 1373 return null; 1374 } 1375 try { 1376 return (float[]) o; 1377 } catch (ClassCastException e) { 1378 typeWarning(key, o, "float[]", e); 1379 return null; 1380 } 1381 } 1382 1383 /** 1384 * Returns the value associated with the given key, or null if 1385 * no mapping of the desired type exists for the given key or a null 1386 * value is explicitly associated with the key. 1387 * 1388 * @param key a String, or null 1389 * @return a double[] value, or null 1390 */ 1391 public double[] getDoubleArray(String key) { 1392 unparcel(); 1393 Object o = mMap.get(key); 1394 if (o == null) { 1395 return null; 1396 } 1397 try { 1398 return (double[]) o; 1399 } catch (ClassCastException e) { 1400 typeWarning(key, o, "double[]", e); 1401 return null; 1402 } 1403 } 1404 1405 /** 1406 * Returns the value associated with the given key, or null if 1407 * no mapping of the desired type exists for the given key or a null 1408 * value is explicitly associated with the key. 1409 * 1410 * @param key a String, or null 1411 * @return a String[] value, or null 1412 */ 1413 public String[] getStringArray(String key) { 1414 unparcel(); 1415 Object o = mMap.get(key); 1416 if (o == null) { 1417 return null; 1418 } 1419 try { 1420 return (String[]) o; 1421 } catch (ClassCastException e) { 1422 typeWarning(key, o, "String[]", e); 1423 return null; 1424 } 1425 } 1426 1427 /** 1428 * Returns the value associated with the given key, or null if 1429 * no mapping of the desired type exists for the given key or a null 1430 * value is explicitly associated with the key. 1431 * 1432 * @param key a String, or null 1433 * @return a CharSequence[] value, or null 1434 */ 1435 public CharSequence[] getCharSequenceArray(String key) { 1436 unparcel(); 1437 Object o = mMap.get(key); 1438 if (o == null) { 1439 return null; 1440 } 1441 try { 1442 return (CharSequence[]) o; 1443 } catch (ClassCastException e) { 1444 typeWarning(key, o, "CharSequence[]", e); 1445 return null; 1446 } 1447 } 1448 1449 /** 1450 * Returns the value associated with the given key, or null if 1451 * no mapping of the desired type exists for the given key or a null 1452 * value is explicitly associated with the key. 1453 * 1454 * @param key a String, or null 1455 * @return an IBinder value, or null 1456 * 1457 * @deprecated 1458 * @hide 1459 */ 1460 @Deprecated 1461 public IBinder getIBinder(String key) { 1462 unparcel(); 1463 Object o = mMap.get(key); 1464 if (o == null) { 1465 return null; 1466 } 1467 try { 1468 return (IBinder) o; 1469 } catch (ClassCastException e) { 1470 typeWarning(key, o, "IBinder", e); 1471 return null; 1472 } 1473 } 1474 1475 public static final Parcelable.Creator<Bundle> CREATOR = 1476 new Parcelable.Creator<Bundle>() { 1477 public Bundle createFromParcel(Parcel in) { 1478 return in.readBundle(); 1479 } 1480 1481 public Bundle[] newArray(int size) { 1482 return new Bundle[size]; 1483 } 1484 }; 1485 1486 /** 1487 * Report the nature of this Parcelable's contents 1488 */ 1489 public int describeContents() { 1490 int mask = 0; 1491 if (hasFileDescriptors()) { 1492 mask |= Parcelable.CONTENTS_FILE_DESCRIPTOR; 1493 } 1494 return mask; 1495 } 1496 1497 /** 1498 * Writes the Bundle contents to a Parcel, typically in order for 1499 * it to be passed through an IBinder connection. 1500 * @param parcel The parcel to copy this bundle to. 1501 */ 1502 public void writeToParcel(Parcel parcel, int flags) { 1503 if (mParcelledData != null) { 1504 int length = mParcelledData.dataSize(); 1505 parcel.writeInt(length); 1506 parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' 1507 parcel.appendFrom(mParcelledData, 0, length); 1508 } else { 1509 parcel.writeInt(-1); // dummy, will hold length 1510 parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' 1511 1512 int oldPos = parcel.dataPosition(); 1513 parcel.writeMapInternal(mMap); 1514 int newPos = parcel.dataPosition(); 1515 1516 // Backpatch length 1517 parcel.setDataPosition(oldPos - 8); 1518 int length = newPos - oldPos; 1519 parcel.writeInt(length); 1520 parcel.setDataPosition(newPos); 1521 } 1522 } 1523 1524 /** 1525 * Reads the Parcel contents into this Bundle, typically in order for 1526 * it to be passed through an IBinder connection. 1527 * @param parcel The parcel to overwrite this bundle from. 1528 */ 1529 public void readFromParcel(Parcel parcel) { 1530 int length = parcel.readInt(); 1531 if (length < 0) { 1532 throw new RuntimeException("Bad length in parcel: " + length); 1533 } 1534 readFromParcelInner(parcel, length); 1535 } 1536 1537 void readFromParcelInner(Parcel parcel, int length) { 1538 int magic = parcel.readInt(); 1539 if (magic != 0x4C444E42) { 1540 //noinspection ThrowableInstanceNeverThrown 1541 String st = Log.getStackTraceString(new RuntimeException()); 1542 Log.e("Bundle", "readBundle: bad magic number"); 1543 Log.e("Bundle", "readBundle: trace = " + st); 1544 } 1545 1546 // Advance within this Parcel 1547 int offset = parcel.dataPosition(); 1548 parcel.setDataPosition(offset + length); 1549 1550 Parcel p = Parcel.obtain(); 1551 p.setDataPosition(0); 1552 p.appendFrom(parcel, offset, length); 1553 p.setDataPosition(0); 1554 1555 mParcelledData = p; 1556 mHasFds = p.hasFileDescriptors(); 1557 mFdsKnown = true; 1558 } 1559 1560 @Override 1561 public synchronized String toString() { 1562 if (mParcelledData != null) { 1563 return "Bundle[mParcelledData.dataSize=" + 1564 mParcelledData.dataSize() + "]"; 1565 } 1566 return "Bundle[" + mMap.toString() + "]"; 1567 } 1568} 1569