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