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