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