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