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