Bundle.java revision 5164246d7e47b9c995ca1e1587f3056eb777f60b
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 /** 1033 * Returns the value associated with the given key, or null if 1034 * no mapping of the desired type exists for the given key or a null 1035 * value is explicitly associated with the key. 1036 * 1037 * @param key a String, or null 1038 * @return a String value, or null 1039 */ 1040 public String getString(String key) { 1041 unparcel(); 1042 Object o = mMap.get(key); 1043 if (o == null) { 1044 return null; 1045 } 1046 try { 1047 return (String) o; 1048 } catch (ClassCastException e) { 1049 typeWarning(key, o, "String", e); 1050 return null; 1051 } 1052 } 1053 1054 /** 1055 * Returns the value associated with the given key, or null if 1056 * no mapping of the desired type exists for the given key or a null 1057 * value is explicitly associated with the key. 1058 * 1059 * @param key a String, or null 1060 * @return a CharSequence value, or null 1061 */ 1062 public CharSequence getCharSequence(String key) { 1063 unparcel(); 1064 Object o = mMap.get(key); 1065 if (o == null) { 1066 return null; 1067 } 1068 try { 1069 return (CharSequence) o; 1070 } catch (ClassCastException e) { 1071 typeWarning(key, o, "CharSequence", e); 1072 return null; 1073 } 1074 } 1075 1076 /** 1077 * Returns the value associated with the given key, or null if 1078 * no mapping of the desired type exists for the given key or a null 1079 * value is explicitly associated with the key. 1080 * 1081 * @param key a String, or null 1082 * @return a Bundle value, or null 1083 */ 1084 public Bundle getBundle(String key) { 1085 unparcel(); 1086 Object o = mMap.get(key); 1087 if (o == null) { 1088 return null; 1089 } 1090 try { 1091 return (Bundle) o; 1092 } catch (ClassCastException e) { 1093 typeWarning(key, o, "Bundle", e); 1094 return null; 1095 } 1096 } 1097 1098 /** 1099 * Returns the value associated with the given key, or null if 1100 * no mapping of the desired type exists for the given key or a null 1101 * value is explicitly associated with the key. 1102 * 1103 * @param key a String, or null 1104 * @return a Parcelable value, or null 1105 */ 1106 public <T extends Parcelable> T getParcelable(String key) { 1107 unparcel(); 1108 Object o = mMap.get(key); 1109 if (o == null) { 1110 return null; 1111 } 1112 try { 1113 return (T) o; 1114 } catch (ClassCastException e) { 1115 typeWarning(key, o, "Parcelable", e); 1116 return null; 1117 } 1118 } 1119 1120 /** 1121 * Returns the value associated with the given key, or null if 1122 * no mapping of the desired type exists for the given key or a null 1123 * value is explicitly associated with the key. 1124 * 1125 * @param key a String, or null 1126 * @return a Parcelable[] value, or null 1127 */ 1128 public Parcelable[] getParcelableArray(String key) { 1129 unparcel(); 1130 Object o = mMap.get(key); 1131 if (o == null) { 1132 return null; 1133 } 1134 try { 1135 return (Parcelable[]) o; 1136 } catch (ClassCastException e) { 1137 typeWarning(key, o, "Parcelable[]", e); 1138 return null; 1139 } 1140 } 1141 1142 /** 1143 * Returns the value associated with the given key, or null if 1144 * no mapping of the desired type exists for the given key or a null 1145 * value is explicitly associated with the key. 1146 * 1147 * @param key a String, or null 1148 * @return an ArrayList<T> value, or null 1149 */ 1150 public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String key) { 1151 unparcel(); 1152 Object o = mMap.get(key); 1153 if (o == null) { 1154 return null; 1155 } 1156 try { 1157 return (ArrayList<T>) o; 1158 } catch (ClassCastException e) { 1159 typeWarning(key, o, "ArrayList", e); 1160 return null; 1161 } 1162 } 1163 1164 /** 1165 * Returns the value associated with the given key, or null if 1166 * no mapping of the desired type exists for the given key or a null 1167 * value is explicitly associated with the key. 1168 * 1169 * @param key a String, or null 1170 * 1171 * @return a SparseArray of T values, or null 1172 */ 1173 public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(String key) { 1174 unparcel(); 1175 Object o = mMap.get(key); 1176 if (o == null) { 1177 return null; 1178 } 1179 try { 1180 return (SparseArray<T>) o; 1181 } catch (ClassCastException e) { 1182 typeWarning(key, o, "SparseArray", e); 1183 return null; 1184 } 1185 } 1186 1187 /** 1188 * Returns the value associated with the given key, or null if 1189 * no mapping of the desired type exists for the given key or a null 1190 * value is explicitly associated with the key. 1191 * 1192 * @param key a String, or null 1193 * @return a Serializable value, or null 1194 */ 1195 public Serializable getSerializable(String key) { 1196 unparcel(); 1197 Object o = mMap.get(key); 1198 if (o == null) { 1199 return null; 1200 } 1201 try { 1202 return (Serializable) o; 1203 } catch (ClassCastException e) { 1204 typeWarning(key, o, "Serializable", e); 1205 return null; 1206 } 1207 } 1208 1209 /** 1210 * Returns the value associated with the given key, or null if 1211 * no mapping of the desired type exists for the given key or a null 1212 * value is explicitly associated with the key. 1213 * 1214 * @param key a String, or null 1215 * @return an ArrayList<String> value, or null 1216 */ 1217 public ArrayList<Integer> getIntegerArrayList(String key) { 1218 unparcel(); 1219 Object o = mMap.get(key); 1220 if (o == null) { 1221 return null; 1222 } 1223 try { 1224 return (ArrayList<Integer>) o; 1225 } catch (ClassCastException e) { 1226 typeWarning(key, o, "ArrayList<Integer>", e); 1227 return null; 1228 } 1229 } 1230 1231 /** 1232 * Returns the value associated with the given key, or null if 1233 * no mapping of the desired type exists for the given key or a null 1234 * value is explicitly associated with the key. 1235 * 1236 * @param key a String, or null 1237 * @return an ArrayList<String> value, or null 1238 */ 1239 public ArrayList<String> getStringArrayList(String key) { 1240 unparcel(); 1241 Object o = mMap.get(key); 1242 if (o == null) { 1243 return null; 1244 } 1245 try { 1246 return (ArrayList<String>) o; 1247 } catch (ClassCastException e) { 1248 typeWarning(key, o, "ArrayList<String>", e); 1249 return null; 1250 } 1251 } 1252 1253 /** 1254 * Returns the value associated with the given key, or null if 1255 * no mapping of the desired type exists for the given key or a null 1256 * value is explicitly associated with the key. 1257 * 1258 * @param key a String, or null 1259 * @return an ArrayList<CharSequence> value, or null 1260 */ 1261 public ArrayList<CharSequence> getCharSequenceArrayList(String key) { 1262 unparcel(); 1263 Object o = mMap.get(key); 1264 if (o == null) { 1265 return null; 1266 } 1267 try { 1268 return (ArrayList<CharSequence>) o; 1269 } catch (ClassCastException e) { 1270 typeWarning(key, o, "ArrayList<CharSequence>", e); 1271 return null; 1272 } 1273 } 1274 1275 /** 1276 * Returns the value associated with the given key, or null if 1277 * no mapping of the desired type exists for the given key or a null 1278 * value is explicitly associated with the key. 1279 * 1280 * @param key a String, or null 1281 * @return a boolean[] value, or null 1282 */ 1283 public boolean[] getBooleanArray(String key) { 1284 unparcel(); 1285 Object o = mMap.get(key); 1286 if (o == null) { 1287 return null; 1288 } 1289 try { 1290 return (boolean[]) o; 1291 } catch (ClassCastException e) { 1292 typeWarning(key, o, "byte[]", e); 1293 return null; 1294 } 1295 } 1296 1297 /** 1298 * Returns the value associated with the given key, or null if 1299 * no mapping of the desired type exists for the given key or a null 1300 * value is explicitly associated with the key. 1301 * 1302 * @param key a String, or null 1303 * @return a byte[] value, or null 1304 */ 1305 public byte[] getByteArray(String key) { 1306 unparcel(); 1307 Object o = mMap.get(key); 1308 if (o == null) { 1309 return null; 1310 } 1311 try { 1312 return (byte[]) o; 1313 } catch (ClassCastException e) { 1314 typeWarning(key, o, "byte[]", e); 1315 return null; 1316 } 1317 } 1318 1319 /** 1320 * Returns the value associated with the given key, or null if 1321 * no mapping of the desired type exists for the given key or a null 1322 * value is explicitly associated with the key. 1323 * 1324 * @param key a String, or null 1325 * @return a short[] value, or null 1326 */ 1327 public short[] getShortArray(String key) { 1328 unparcel(); 1329 Object o = mMap.get(key); 1330 if (o == null) { 1331 return null; 1332 } 1333 try { 1334 return (short[]) o; 1335 } catch (ClassCastException e) { 1336 typeWarning(key, o, "short[]", e); 1337 return null; 1338 } 1339 } 1340 1341 /** 1342 * Returns the value associated with the given key, or null if 1343 * no mapping of the desired type exists for the given key or a null 1344 * value is explicitly associated with the key. 1345 * 1346 * @param key a String, or null 1347 * @return a char[] value, or null 1348 */ 1349 public char[] getCharArray(String key) { 1350 unparcel(); 1351 Object o = mMap.get(key); 1352 if (o == null) { 1353 return null; 1354 } 1355 try { 1356 return (char[]) o; 1357 } catch (ClassCastException e) { 1358 typeWarning(key, o, "char[]", e); 1359 return null; 1360 } 1361 } 1362 1363 /** 1364 * Returns the value associated with the given key, or null if 1365 * no mapping of the desired type exists for the given key or a null 1366 * value is explicitly associated with the key. 1367 * 1368 * @param key a String, or null 1369 * @return an int[] value, or null 1370 */ 1371 public int[] getIntArray(String key) { 1372 unparcel(); 1373 Object o = mMap.get(key); 1374 if (o == null) { 1375 return null; 1376 } 1377 try { 1378 return (int[]) o; 1379 } catch (ClassCastException e) { 1380 typeWarning(key, o, "int[]", e); 1381 return null; 1382 } 1383 } 1384 1385 /** 1386 * Returns the value associated with the given key, or null if 1387 * no mapping of the desired type exists for the given key or a null 1388 * value is explicitly associated with the key. 1389 * 1390 * @param key a String, or null 1391 * @return a long[] value, or null 1392 */ 1393 public long[] getLongArray(String key) { 1394 unparcel(); 1395 Object o = mMap.get(key); 1396 if (o == null) { 1397 return null; 1398 } 1399 try { 1400 return (long[]) o; 1401 } catch (ClassCastException e) { 1402 typeWarning(key, o, "long[]", e); 1403 return null; 1404 } 1405 } 1406 1407 /** 1408 * Returns the value associated with the given key, or null if 1409 * no mapping of the desired type exists for the given key or a null 1410 * value is explicitly associated with the key. 1411 * 1412 * @param key a String, or null 1413 * @return a float[] value, or null 1414 */ 1415 public float[] getFloatArray(String key) { 1416 unparcel(); 1417 Object o = mMap.get(key); 1418 if (o == null) { 1419 return null; 1420 } 1421 try { 1422 return (float[]) o; 1423 } catch (ClassCastException e) { 1424 typeWarning(key, o, "float[]", e); 1425 return null; 1426 } 1427 } 1428 1429 /** 1430 * Returns the value associated with the given key, or null if 1431 * no mapping of the desired type exists for the given key or a null 1432 * value is explicitly associated with the key. 1433 * 1434 * @param key a String, or null 1435 * @return a double[] value, or null 1436 */ 1437 public double[] getDoubleArray(String key) { 1438 unparcel(); 1439 Object o = mMap.get(key); 1440 if (o == null) { 1441 return null; 1442 } 1443 try { 1444 return (double[]) o; 1445 } catch (ClassCastException e) { 1446 typeWarning(key, o, "double[]", e); 1447 return null; 1448 } 1449 } 1450 1451 /** 1452 * Returns the value associated with the given key, or null if 1453 * no mapping of the desired type exists for the given key or a null 1454 * value is explicitly associated with the key. 1455 * 1456 * @param key a String, or null 1457 * @return a String[] value, or null 1458 */ 1459 public String[] getStringArray(String key) { 1460 unparcel(); 1461 Object o = mMap.get(key); 1462 if (o == null) { 1463 return null; 1464 } 1465 try { 1466 return (String[]) o; 1467 } catch (ClassCastException e) { 1468 typeWarning(key, o, "String[]", e); 1469 return null; 1470 } 1471 } 1472 1473 /** 1474 * Returns the value associated with the given key, or null if 1475 * no mapping of the desired type exists for the given key or a null 1476 * value is explicitly associated with the key. 1477 * 1478 * @param key a String, or null 1479 * @return a CharSequence[] value, or null 1480 */ 1481 public CharSequence[] getCharSequenceArray(String key) { 1482 unparcel(); 1483 Object o = mMap.get(key); 1484 if (o == null) { 1485 return null; 1486 } 1487 try { 1488 return (CharSequence[]) o; 1489 } catch (ClassCastException e) { 1490 typeWarning(key, o, "CharSequence[]", e); 1491 return null; 1492 } 1493 } 1494 1495 /** 1496 * Returns the value associated with the given key, or null if 1497 * no mapping of the desired type exists for the given key or a null 1498 * value is explicitly associated with the key. 1499 * 1500 * @param key a String, or null 1501 * @return an IBinder value, or null 1502 * 1503 * @deprecated 1504 * @hide 1505 */ 1506 @Deprecated 1507 public IBinder getIBinder(String key) { 1508 unparcel(); 1509 Object o = mMap.get(key); 1510 if (o == null) { 1511 return null; 1512 } 1513 try { 1514 return (IBinder) o; 1515 } catch (ClassCastException e) { 1516 typeWarning(key, o, "IBinder", e); 1517 return null; 1518 } 1519 } 1520 1521 public static final Parcelable.Creator<Bundle> CREATOR = 1522 new Parcelable.Creator<Bundle>() { 1523 public Bundle createFromParcel(Parcel in) { 1524 return in.readBundle(); 1525 } 1526 1527 public Bundle[] newArray(int size) { 1528 return new Bundle[size]; 1529 } 1530 }; 1531 1532 /** 1533 * Report the nature of this Parcelable's contents 1534 */ 1535 public int describeContents() { 1536 int mask = 0; 1537 if (hasFileDescriptors()) { 1538 mask |= Parcelable.CONTENTS_FILE_DESCRIPTOR; 1539 } 1540 return mask; 1541 } 1542 1543 /** 1544 * Writes the Bundle contents to a Parcel, typically in order for 1545 * it to be passed through an IBinder connection. 1546 * @param parcel The parcel to copy this bundle to. 1547 */ 1548 public void writeToParcel(Parcel parcel, int flags) { 1549 if (mParcelledData != null) { 1550 int length = mParcelledData.dataSize(); 1551 parcel.writeInt(length); 1552 parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' 1553 parcel.appendFrom(mParcelledData, 0, length); 1554 } else { 1555 parcel.writeInt(-1); // dummy, will hold length 1556 parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' 1557 1558 int oldPos = parcel.dataPosition(); 1559 parcel.writeMapInternal(mMap); 1560 int newPos = parcel.dataPosition(); 1561 1562 // Backpatch length 1563 parcel.setDataPosition(oldPos - 8); 1564 int length = newPos - oldPos; 1565 parcel.writeInt(length); 1566 parcel.setDataPosition(newPos); 1567 } 1568 } 1569 1570 /** 1571 * Reads the Parcel contents into this Bundle, typically in order for 1572 * it to be passed through an IBinder connection. 1573 * @param parcel The parcel to overwrite this bundle from. 1574 */ 1575 public void readFromParcel(Parcel parcel) { 1576 int length = parcel.readInt(); 1577 if (length < 0) { 1578 throw new RuntimeException("Bad length in parcel: " + length); 1579 } 1580 readFromParcelInner(parcel, length); 1581 } 1582 1583 void readFromParcelInner(Parcel parcel, int length) { 1584 int magic = parcel.readInt(); 1585 if (magic != 0x4C444E42) { 1586 //noinspection ThrowableInstanceNeverThrown 1587 String st = Log.getStackTraceString(new RuntimeException()); 1588 Log.e("Bundle", "readBundle: bad magic number"); 1589 Log.e("Bundle", "readBundle: trace = " + st); 1590 } 1591 1592 // Advance within this Parcel 1593 int offset = parcel.dataPosition(); 1594 parcel.setDataPosition(offset + length); 1595 1596 Parcel p = Parcel.obtain(); 1597 p.setDataPosition(0); 1598 p.appendFrom(parcel, offset, length); 1599 p.setDataPosition(0); 1600 1601 mParcelledData = p; 1602 mHasFds = p.hasFileDescriptors(); 1603 mFdsKnown = true; 1604 } 1605 1606 @Override 1607 public synchronized String toString() { 1608 if (mParcelledData != null) { 1609 return "Bundle[mParcelledData.dataSize=" + 1610 mParcelledData.dataSize() + "]"; 1611 } 1612 return "Bundle[" + mMap.toString() + "]"; 1613 } 1614} 1615