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