1 /* 2 * Copyright (C) 2014 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.annotation.Nullable; 20 import android.util.ArrayMap; 21 import android.util.Log; 22 import android.util.MathUtils; 23 import android.util.Slog; 24 25 import java.io.Serializable; 26 import java.util.ArrayList; 27 import java.util.Set; 28 29 /** 30 * A mapping from String keys to values of various types. In most cases, you 31 * should work directly with either the {@link Bundle} or 32 * {@link PersistableBundle} subclass. 33 */ 34 public class BaseBundle { 35 private static final String TAG = "Bundle"; 36 static final boolean DEBUG = false; 37 38 // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp. 39 static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L' 40 41 /** 42 * Flag indicating that this Bundle is okay to "defuse." That is, it's okay 43 * for system processes to ignore any {@link BadParcelableException} 44 * encountered when unparceling it, leaving an empty bundle in its place. 45 * <p> 46 * This should <em>only</em> be set when the Bundle reaches its final 47 * destination, otherwise a system process may clobber contents that were 48 * destined for an app that could have unparceled them. 49 */ 50 static final int FLAG_DEFUSABLE = 1 << 0; 51 52 private static final boolean LOG_DEFUSABLE = false; 53 54 private static volatile boolean sShouldDefuse = false; 55 56 /** 57 * Set global variable indicating that any Bundles parsed in this process 58 * should be "defused." That is, any {@link BadParcelableException} 59 * encountered will be suppressed and logged, leaving an empty Bundle 60 * instead of crashing. 61 * 62 * @hide 63 */ setShouldDefuse(boolean shouldDefuse)64 public static void setShouldDefuse(boolean shouldDefuse) { 65 sShouldDefuse = shouldDefuse; 66 } 67 68 // A parcel cannot be obtained during compile-time initialization. Put the 69 // empty parcel into an inner class that can be initialized separately. This 70 // allows to initialize BaseBundle, and classes depending on it. 71 /** {@hide} */ 72 static final class NoImagePreloadHolder { 73 public static final Parcel EMPTY_PARCEL = Parcel.obtain(); 74 } 75 76 // Invariant - exactly one of mMap / mParcelledData will be null 77 // (except inside a call to unparcel) 78 79 ArrayMap<String, Object> mMap = null; 80 81 /* 82 * If mParcelledData is non-null, then mMap will be null and the 83 * data are stored as a Parcel containing a Bundle. When the data 84 * are unparcelled, mParcelledData willbe set to null. 85 */ 86 Parcel mParcelledData = null; 87 88 /** 89 * The ClassLoader used when unparcelling data from mParcelledData. 90 */ 91 private ClassLoader mClassLoader; 92 93 /** {@hide} */ 94 int mFlags; 95 96 /** 97 * Constructs a new, empty Bundle that uses a specific ClassLoader for 98 * instantiating Parcelable and Serializable objects. 99 * 100 * @param loader An explicit ClassLoader to use when instantiating objects 101 * inside of the Bundle. 102 * @param capacity Initial size of the ArrayMap. 103 */ BaseBundle(@ullable ClassLoader loader, int capacity)104 BaseBundle(@Nullable ClassLoader loader, int capacity) { 105 mMap = capacity > 0 ? 106 new ArrayMap<String, Object>(capacity) : new ArrayMap<String, Object>(); 107 mClassLoader = loader == null ? getClass().getClassLoader() : loader; 108 } 109 110 /** 111 * Constructs a new, empty Bundle. 112 */ BaseBundle()113 BaseBundle() { 114 this((ClassLoader) null, 0); 115 } 116 117 /** 118 * Constructs a Bundle whose data is stored as a Parcel. The data 119 * will be unparcelled on first contact, using the assigned ClassLoader. 120 * 121 * @param parcelledData a Parcel containing a Bundle 122 */ BaseBundle(Parcel parcelledData)123 BaseBundle(Parcel parcelledData) { 124 readFromParcelInner(parcelledData); 125 } 126 BaseBundle(Parcel parcelledData, int length)127 BaseBundle(Parcel parcelledData, int length) { 128 readFromParcelInner(parcelledData, length); 129 } 130 131 /** 132 * Constructs a new, empty Bundle that uses a specific ClassLoader for 133 * instantiating Parcelable and Serializable objects. 134 * 135 * @param loader An explicit ClassLoader to use when instantiating objects 136 * inside of the Bundle. 137 */ BaseBundle(ClassLoader loader)138 BaseBundle(ClassLoader loader) { 139 this(loader, 0); 140 } 141 142 /** 143 * Constructs a new, empty Bundle sized to hold the given number of 144 * elements. The Bundle will grow as needed. 145 * 146 * @param capacity the initial capacity of the Bundle 147 */ BaseBundle(int capacity)148 BaseBundle(int capacity) { 149 this((ClassLoader) null, capacity); 150 } 151 152 /** 153 * Constructs a Bundle containing a copy of the mappings from the given 154 * Bundle. 155 * 156 * @param b a Bundle to be copied. 157 */ BaseBundle(BaseBundle b)158 BaseBundle(BaseBundle b) { 159 copyInternal(b, false); 160 } 161 162 /** 163 * Special constructor that does not initialize the bundle. 164 */ BaseBundle(boolean doInit)165 BaseBundle(boolean doInit) { 166 } 167 168 /** 169 * TODO: optimize this later (getting just the value part of a Bundle 170 * with a single pair) once Bundle.forPair() above is implemented 171 * with a special single-value Map implementation/serialization. 172 * 173 * Note: value in single-pair Bundle may be null. 174 * 175 * @hide 176 */ getPairValue()177 public String getPairValue() { 178 unparcel(); 179 int size = mMap.size(); 180 if (size > 1) { 181 Log.w(TAG, "getPairValue() used on Bundle with multiple pairs."); 182 } 183 if (size == 0) { 184 return null; 185 } 186 Object o = mMap.valueAt(0); 187 try { 188 return (String) o; 189 } catch (ClassCastException e) { 190 typeWarning("getPairValue()", o, "String", e); 191 return null; 192 } 193 } 194 195 /** 196 * Changes the ClassLoader this Bundle uses when instantiating objects. 197 * 198 * @param loader An explicit ClassLoader to use when instantiating objects 199 * inside of the Bundle. 200 */ setClassLoader(ClassLoader loader)201 void setClassLoader(ClassLoader loader) { 202 mClassLoader = loader; 203 } 204 205 /** 206 * Return the ClassLoader currently associated with this Bundle. 207 */ getClassLoader()208 ClassLoader getClassLoader() { 209 return mClassLoader; 210 } 211 212 /** 213 * If the underlying data are stored as a Parcel, unparcel them 214 * using the currently assigned class loader. 215 */ unparcel()216 /* package */ void unparcel() { 217 synchronized (this) { 218 final Parcel parcelledData = mParcelledData; 219 if (parcelledData == null) { 220 if (DEBUG) Log.d(TAG, "unparcel " 221 + Integer.toHexString(System.identityHashCode(this)) 222 + ": no parcelled data"); 223 return; 224 } 225 226 if (LOG_DEFUSABLE && sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) { 227 Slog.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may " 228 + "clobber all data inside!", new Throwable()); 229 } 230 231 if (isEmptyParcel()) { 232 if (DEBUG) Log.d(TAG, "unparcel " 233 + Integer.toHexString(System.identityHashCode(this)) + ": empty"); 234 if (mMap == null) { 235 mMap = new ArrayMap<>(1); 236 } else { 237 mMap.erase(); 238 } 239 mParcelledData = null; 240 return; 241 } 242 243 int N = parcelledData.readInt(); 244 if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this)) 245 + ": reading " + N + " maps"); 246 if (N < 0) { 247 return; 248 } 249 ArrayMap<String, Object> map = mMap; 250 if (map == null) { 251 map = new ArrayMap<>(N); 252 } else { 253 map.erase(); 254 map.ensureCapacity(N); 255 } 256 try { 257 parcelledData.readArrayMapInternal(map, N, mClassLoader); 258 } catch (BadParcelableException e) { 259 if (sShouldDefuse) { 260 Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e); 261 map.erase(); 262 } else { 263 throw e; 264 } 265 } finally { 266 mMap = map; 267 parcelledData.recycle(); 268 mParcelledData = null; 269 } 270 if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this)) 271 + " final map: " + mMap); 272 } 273 } 274 275 /** 276 * @hide 277 */ isParcelled()278 public boolean isParcelled() { 279 return mParcelledData != null; 280 } 281 282 /** 283 * @hide 284 */ isEmptyParcel()285 public boolean isEmptyParcel() { 286 return mParcelledData == NoImagePreloadHolder.EMPTY_PARCEL; 287 } 288 289 /** @hide */ getMap()290 ArrayMap<String, Object> getMap() { 291 unparcel(); 292 return mMap; 293 } 294 295 /** 296 * Returns the number of mappings contained in this Bundle. 297 * 298 * @return the number of mappings as an int. 299 */ size()300 public int size() { 301 unparcel(); 302 return mMap.size(); 303 } 304 305 /** 306 * Returns true if the mapping of this Bundle is empty, false otherwise. 307 */ isEmpty()308 public boolean isEmpty() { 309 unparcel(); 310 return mMap.isEmpty(); 311 } 312 313 /** 314 * @hide this should probably be the implementation of isEmpty(). To do that we 315 * need to ensure we always use the special empty parcel form when the bundle is 316 * empty. (This may already be the case, but to be safe we'll do this later when 317 * we aren't trying to stabilize.) 318 */ maybeIsEmpty()319 public boolean maybeIsEmpty() { 320 if (isParcelled()) { 321 return isEmptyParcel(); 322 } else { 323 return isEmpty(); 324 } 325 } 326 327 /** 328 * @hide This kind-of does an equality comparison. Kind-of. 329 */ kindofEquals(BaseBundle other)330 public boolean kindofEquals(BaseBundle other) { 331 if (other == null) { 332 return false; 333 } 334 if (isParcelled() != other.isParcelled()) { 335 // Big kind-of here! 336 return false; 337 } else if (isParcelled()) { 338 return mParcelledData.compareData(other.mParcelledData) == 0; 339 } else { 340 return mMap.equals(other.mMap); 341 } 342 } 343 344 /** 345 * Removes all elements from the mapping of this Bundle. 346 */ clear()347 public void clear() { 348 unparcel(); 349 mMap.clear(); 350 } 351 copyInternal(BaseBundle from, boolean deep)352 void copyInternal(BaseBundle from, boolean deep) { 353 synchronized (from) { 354 if (from.mParcelledData != null) { 355 if (from.isEmptyParcel()) { 356 mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL; 357 } else { 358 mParcelledData = Parcel.obtain(); 359 mParcelledData.appendFrom(from.mParcelledData, 0, 360 from.mParcelledData.dataSize()); 361 mParcelledData.setDataPosition(0); 362 } 363 } else { 364 mParcelledData = null; 365 } 366 367 if (from.mMap != null) { 368 if (!deep) { 369 mMap = new ArrayMap<>(from.mMap); 370 } else { 371 final ArrayMap<String, Object> fromMap = from.mMap; 372 final int N = fromMap.size(); 373 mMap = new ArrayMap<>(N); 374 for (int i = 0; i < N; i++) { 375 mMap.append(fromMap.keyAt(i), deepCopyValue(fromMap.valueAt(i))); 376 } 377 } 378 } else { 379 mMap = null; 380 } 381 382 mClassLoader = from.mClassLoader; 383 } 384 } 385 deepCopyValue(Object value)386 Object deepCopyValue(Object value) { 387 if (value == null) { 388 return null; 389 } 390 if (value instanceof Bundle) { 391 return ((Bundle)value).deepCopy(); 392 } else if (value instanceof PersistableBundle) { 393 return ((PersistableBundle)value).deepCopy(); 394 } else if (value instanceof ArrayList) { 395 return deepcopyArrayList((ArrayList) value); 396 } else if (value.getClass().isArray()) { 397 if (value instanceof int[]) { 398 return ((int[])value).clone(); 399 } else if (value instanceof long[]) { 400 return ((long[])value).clone(); 401 } else if (value instanceof float[]) { 402 return ((float[])value).clone(); 403 } else if (value instanceof double[]) { 404 return ((double[])value).clone(); 405 } else if (value instanceof Object[]) { 406 return ((Object[])value).clone(); 407 } else if (value instanceof byte[]) { 408 return ((byte[])value).clone(); 409 } else if (value instanceof short[]) { 410 return ((short[])value).clone(); 411 } else if (value instanceof char[]) { 412 return ((char[]) value).clone(); 413 } 414 } 415 return value; 416 } 417 deepcopyArrayList(ArrayList from)418 ArrayList deepcopyArrayList(ArrayList from) { 419 final int N = from.size(); 420 ArrayList out = new ArrayList(N); 421 for (int i=0; i<N; i++) { 422 out.add(deepCopyValue(from.get(i))); 423 } 424 return out; 425 } 426 427 /** 428 * Returns true if the given key is contained in the mapping 429 * of this Bundle. 430 * 431 * @param key a String key 432 * @return true if the key is part of the mapping, false otherwise 433 */ containsKey(String key)434 public boolean containsKey(String key) { 435 unparcel(); 436 return mMap.containsKey(key); 437 } 438 439 /** 440 * Returns the entry with the given key as an object. 441 * 442 * @param key a String key 443 * @return an Object, or null 444 */ 445 @Nullable get(String key)446 public Object get(String key) { 447 unparcel(); 448 return mMap.get(key); 449 } 450 451 /** 452 * Removes any entry with the given key from the mapping of this Bundle. 453 * 454 * @param key a String key 455 */ remove(String key)456 public void remove(String key) { 457 unparcel(); 458 mMap.remove(key); 459 } 460 461 /** 462 * Inserts all mappings from the given PersistableBundle into this BaseBundle. 463 * 464 * @param bundle a PersistableBundle 465 */ putAll(PersistableBundle bundle)466 public void putAll(PersistableBundle bundle) { 467 unparcel(); 468 bundle.unparcel(); 469 mMap.putAll(bundle.mMap); 470 } 471 472 /** 473 * Inserts all mappings from the given Map into this BaseBundle. 474 * 475 * @param map a Map 476 */ putAll(ArrayMap map)477 void putAll(ArrayMap map) { 478 unparcel(); 479 mMap.putAll(map); 480 } 481 482 /** 483 * Returns a Set containing the Strings used as keys in this Bundle. 484 * 485 * @return a Set of String keys 486 */ keySet()487 public Set<String> keySet() { 488 unparcel(); 489 return mMap.keySet(); 490 } 491 492 /** 493 * Inserts a Boolean 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 boolean 498 */ putBoolean(@ullable String key, boolean value)499 public void putBoolean(@Nullable String key, boolean value) { 500 unparcel(); 501 mMap.put(key, value); 502 } 503 504 /** 505 * Inserts a byte value into the mapping of this Bundle, replacing 506 * any existing value for the given key. 507 * 508 * @param key a String, or null 509 * @param value a byte 510 */ putByte(@ullable String key, byte value)511 void putByte(@Nullable String key, byte value) { 512 unparcel(); 513 mMap.put(key, value); 514 } 515 516 /** 517 * Inserts a char value into the mapping of this Bundle, replacing 518 * any existing value for the given key. 519 * 520 * @param key a String, or null 521 * @param value a char 522 */ putChar(@ullable String key, char value)523 void putChar(@Nullable String key, char value) { 524 unparcel(); 525 mMap.put(key, value); 526 } 527 528 /** 529 * Inserts a short value into the mapping of this Bundle, replacing 530 * any existing value for the given key. 531 * 532 * @param key a String, or null 533 * @param value a short 534 */ putShort(@ullable String key, short value)535 void putShort(@Nullable String key, short value) { 536 unparcel(); 537 mMap.put(key, value); 538 } 539 540 /** 541 * Inserts an int value into the mapping of this Bundle, replacing 542 * any existing value for the given key. 543 * 544 * @param key a String, or null 545 * @param value an int 546 */ putInt(@ullable String key, int value)547 public void putInt(@Nullable String key, int value) { 548 unparcel(); 549 mMap.put(key, value); 550 } 551 552 /** 553 * Inserts a long value into the mapping of this Bundle, replacing 554 * any existing value for the given key. 555 * 556 * @param key a String, or null 557 * @param value a long 558 */ putLong(@ullable String key, long value)559 public void putLong(@Nullable String key, long value) { 560 unparcel(); 561 mMap.put(key, value); 562 } 563 564 /** 565 * Inserts a float value into the mapping of this Bundle, replacing 566 * any existing value for the given key. 567 * 568 * @param key a String, or null 569 * @param value a float 570 */ putFloat(@ullable String key, float value)571 void putFloat(@Nullable String key, float value) { 572 unparcel(); 573 mMap.put(key, value); 574 } 575 576 /** 577 * Inserts a double value into the mapping of this Bundle, replacing 578 * any existing value for the given key. 579 * 580 * @param key a String, or null 581 * @param value a double 582 */ putDouble(@ullable String key, double value)583 public void putDouble(@Nullable String key, double value) { 584 unparcel(); 585 mMap.put(key, value); 586 } 587 588 /** 589 * Inserts a String 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 a String, or null 594 */ putString(@ullable String key, @Nullable String value)595 public void putString(@Nullable String key, @Nullable String value) { 596 unparcel(); 597 mMap.put(key, value); 598 } 599 600 /** 601 * Inserts a CharSequence 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 CharSequence, or null 606 */ putCharSequence(@ullable String key, @Nullable CharSequence value)607 void putCharSequence(@Nullable String key, @Nullable CharSequence value) { 608 unparcel(); 609 mMap.put(key, value); 610 } 611 612 /** 613 * Inserts an ArrayList<Integer> 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 an ArrayList<Integer> object, or null 618 */ putIntegerArrayList(@ullable String key, @Nullable ArrayList<Integer> value)619 void putIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) { 620 unparcel(); 621 mMap.put(key, value); 622 } 623 624 /** 625 * Inserts an ArrayList<String> 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 an ArrayList<String> object, or null 630 */ putStringArrayList(@ullable String key, @Nullable ArrayList<String> value)631 void putStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) { 632 unparcel(); 633 mMap.put(key, value); 634 } 635 636 /** 637 * Inserts an ArrayList<CharSequence> 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 an ArrayList<CharSequence> object, or null 642 */ putCharSequenceArrayList(@ullable String key, @Nullable ArrayList<CharSequence> value)643 void putCharSequenceArrayList(@Nullable String key, @Nullable ArrayList<CharSequence> value) { 644 unparcel(); 645 mMap.put(key, value); 646 } 647 648 /** 649 * Inserts a Serializable 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 Serializable object, or null 654 */ putSerializable(@ullable String key, @Nullable Serializable value)655 void putSerializable(@Nullable String key, @Nullable Serializable value) { 656 unparcel(); 657 mMap.put(key, value); 658 } 659 660 /** 661 * Inserts a boolean 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 a boolean array object, or null 666 */ putBooleanArray(@ullable String key, @Nullable boolean[] value)667 public void putBooleanArray(@Nullable String key, @Nullable boolean[] value) { 668 unparcel(); 669 mMap.put(key, value); 670 } 671 672 /** 673 * Inserts a byte 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 byte array object, or null 678 */ putByteArray(@ullable String key, @Nullable byte[] value)679 void putByteArray(@Nullable String key, @Nullable byte[] value) { 680 unparcel(); 681 mMap.put(key, value); 682 } 683 684 /** 685 * Inserts a short 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 short array object, or null 690 */ putShortArray(@ullable String key, @Nullable short[] value)691 void putShortArray(@Nullable String key, @Nullable short[] value) { 692 unparcel(); 693 mMap.put(key, value); 694 } 695 696 /** 697 * Inserts a char 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 char array object, or null 702 */ putCharArray(@ullable String key, @Nullable char[] value)703 void putCharArray(@Nullable String key, @Nullable char[] value) { 704 unparcel(); 705 mMap.put(key, value); 706 } 707 708 /** 709 * Inserts an int 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 an int array object, or null 714 */ putIntArray(@ullable String key, @Nullable int[] value)715 public void putIntArray(@Nullable String key, @Nullable int[] value) { 716 unparcel(); 717 mMap.put(key, value); 718 } 719 720 /** 721 * Inserts a long 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 long array object, or null 726 */ putLongArray(@ullable String key, @Nullable long[] value)727 public void putLongArray(@Nullable String key, @Nullable long[] value) { 728 unparcel(); 729 mMap.put(key, value); 730 } 731 732 /** 733 * Inserts a float array 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 float array object, or null 738 */ putFloatArray(@ullable String key, @Nullable float[] value)739 void putFloatArray(@Nullable String key, @Nullable float[] value) { 740 unparcel(); 741 mMap.put(key, value); 742 } 743 744 /** 745 * Inserts a double array 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 * @param key a String, or null 749 * @param value a double array object, or null 750 */ putDoubleArray(@ullable String key, @Nullable double[] value)751 public void putDoubleArray(@Nullable String key, @Nullable double[] value) { 752 unparcel(); 753 mMap.put(key, value); 754 } 755 756 /** 757 * Inserts a String array value into the mapping of this Bundle, replacing 758 * any existing value for the given key. Either key or value may be null. 759 * 760 * @param key a String, or null 761 * @param value a String array object, or null 762 */ putStringArray(@ullable String key, @Nullable String[] value)763 public void putStringArray(@Nullable String key, @Nullable String[] value) { 764 unparcel(); 765 mMap.put(key, value); 766 } 767 768 /** 769 * Inserts a CharSequence array value into the mapping of this Bundle, replacing 770 * any existing value for the given key. Either key or value may be null. 771 * 772 * @param key a String, or null 773 * @param value a CharSequence array object, or null 774 */ putCharSequenceArray(@ullable String key, @Nullable CharSequence[] value)775 void putCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) { 776 unparcel(); 777 mMap.put(key, value); 778 } 779 780 /** 781 * Returns the value associated with the given key, or false if 782 * no mapping of the desired type exists for the given key. 783 * 784 * @param key a String 785 * @return a boolean value 786 */ getBoolean(String key)787 public boolean getBoolean(String key) { 788 unparcel(); 789 if (DEBUG) Log.d(TAG, "Getting boolean in " 790 + Integer.toHexString(System.identityHashCode(this))); 791 return getBoolean(key, false); 792 } 793 794 // 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)795 void typeWarning(String key, Object value, String className, 796 Object defaultValue, ClassCastException e) { 797 StringBuilder sb = new StringBuilder(); 798 sb.append("Key "); 799 sb.append(key); 800 sb.append(" expected "); 801 sb.append(className); 802 sb.append(" but value was a "); 803 sb.append(value.getClass().getName()); 804 sb.append(". The default value "); 805 sb.append(defaultValue); 806 sb.append(" was returned."); 807 Log.w(TAG, sb.toString()); 808 Log.w(TAG, "Attempt to cast generated internal exception:", e); 809 } 810 typeWarning(String key, Object value, String className, ClassCastException e)811 void typeWarning(String key, Object value, String className, 812 ClassCastException e) { 813 typeWarning(key, value, className, "<null>", e); 814 } 815 816 /** 817 * Returns the value associated with the given key, or defaultValue if 818 * no mapping of the desired type exists for the given key. 819 * 820 * @param key a String 821 * @param defaultValue Value to return if key does not exist 822 * @return a boolean value 823 */ getBoolean(String key, boolean defaultValue)824 public boolean getBoolean(String key, boolean defaultValue) { 825 unparcel(); 826 Object o = mMap.get(key); 827 if (o == null) { 828 return defaultValue; 829 } 830 try { 831 return (Boolean) o; 832 } catch (ClassCastException e) { 833 typeWarning(key, o, "Boolean", defaultValue, e); 834 return defaultValue; 835 } 836 } 837 838 /** 839 * Returns the value associated with the given key, or (byte) 0 if 840 * no mapping of the desired type exists for the given key. 841 * 842 * @param key a String 843 * @return a byte value 844 */ getByte(String key)845 byte getByte(String key) { 846 unparcel(); 847 return getByte(key, (byte) 0); 848 } 849 850 /** 851 * Returns the value associated with the given key, or defaultValue if 852 * no mapping of the desired type exists for the given key. 853 * 854 * @param key a String 855 * @param defaultValue Value to return if key does not exist 856 * @return a byte value 857 */ getByte(String key, byte defaultValue)858 Byte getByte(String key, byte defaultValue) { 859 unparcel(); 860 Object o = mMap.get(key); 861 if (o == null) { 862 return defaultValue; 863 } 864 try { 865 return (Byte) o; 866 } catch (ClassCastException e) { 867 typeWarning(key, o, "Byte", defaultValue, e); 868 return defaultValue; 869 } 870 } 871 872 /** 873 * Returns the value associated with the given key, or (char) 0 if 874 * no mapping of the desired type exists for the given key. 875 * 876 * @param key a String 877 * @return a char value 878 */ getChar(String key)879 char getChar(String key) { 880 unparcel(); 881 return getChar(key, (char) 0); 882 } 883 884 /** 885 * Returns the value associated with the given key, or defaultValue if 886 * no mapping of the desired type exists for the given key. 887 * 888 * @param key a String 889 * @param defaultValue Value to return if key does not exist 890 * @return a char value 891 */ getChar(String key, char defaultValue)892 char getChar(String key, char defaultValue) { 893 unparcel(); 894 Object o = mMap.get(key); 895 if (o == null) { 896 return defaultValue; 897 } 898 try { 899 return (Character) o; 900 } catch (ClassCastException e) { 901 typeWarning(key, o, "Character", defaultValue, e); 902 return defaultValue; 903 } 904 } 905 906 /** 907 * Returns the value associated with the given key, or (short) 0 if 908 * no mapping of the desired type exists for the given key. 909 * 910 * @param key a String 911 * @return a short value 912 */ getShort(String key)913 short getShort(String key) { 914 unparcel(); 915 return getShort(key, (short) 0); 916 } 917 918 /** 919 * Returns the value associated with the given key, or defaultValue if 920 * no mapping of the desired type exists for the given key. 921 * 922 * @param key a String 923 * @param defaultValue Value to return if key does not exist 924 * @return a short value 925 */ getShort(String key, short defaultValue)926 short getShort(String key, short defaultValue) { 927 unparcel(); 928 Object o = mMap.get(key); 929 if (o == null) { 930 return defaultValue; 931 } 932 try { 933 return (Short) o; 934 } catch (ClassCastException e) { 935 typeWarning(key, o, "Short", defaultValue, e); 936 return defaultValue; 937 } 938 } 939 940 /** 941 * Returns the value associated with the given key, or 0 if 942 * no mapping of the desired type exists for the given key. 943 * 944 * @param key a String 945 * @return an int value 946 */ getInt(String key)947 public int getInt(String key) { 948 unparcel(); 949 return getInt(key, 0); 950 } 951 952 /** 953 * Returns the value associated with the given key, or defaultValue if 954 * no mapping of the desired type exists for the given key. 955 * 956 * @param key a String 957 * @param defaultValue Value to return if key does not exist 958 * @return an int value 959 */ getInt(String key, int defaultValue)960 public int getInt(String key, int defaultValue) { 961 unparcel(); 962 Object o = mMap.get(key); 963 if (o == null) { 964 return defaultValue; 965 } 966 try { 967 return (Integer) o; 968 } catch (ClassCastException e) { 969 typeWarning(key, o, "Integer", defaultValue, e); 970 return defaultValue; 971 } 972 } 973 974 /** 975 * Returns the value associated with the given key, or 0L if 976 * no mapping of the desired type exists for the given key. 977 * 978 * @param key a String 979 * @return a long value 980 */ getLong(String key)981 public long getLong(String key) { 982 unparcel(); 983 return getLong(key, 0L); 984 } 985 986 /** 987 * Returns the value associated with the given key, or defaultValue if 988 * no mapping of the desired type exists for the given key. 989 * 990 * @param key a String 991 * @param defaultValue Value to return if key does not exist 992 * @return a long value 993 */ getLong(String key, long defaultValue)994 public long getLong(String key, long defaultValue) { 995 unparcel(); 996 Object o = mMap.get(key); 997 if (o == null) { 998 return defaultValue; 999 } 1000 try { 1001 return (Long) o; 1002 } catch (ClassCastException e) { 1003 typeWarning(key, o, "Long", defaultValue, e); 1004 return defaultValue; 1005 } 1006 } 1007 1008 /** 1009 * Returns the value associated with the given key, or 0.0f if 1010 * no mapping of the desired type exists for the given key. 1011 * 1012 * @param key a String 1013 * @return a float value 1014 */ getFloat(String key)1015 float getFloat(String key) { 1016 unparcel(); 1017 return getFloat(key, 0.0f); 1018 } 1019 1020 /** 1021 * Returns the value associated with the given key, or defaultValue if 1022 * no mapping of the desired type exists for the given key. 1023 * 1024 * @param key a String 1025 * @param defaultValue Value to return if key does not exist 1026 * @return a float value 1027 */ getFloat(String key, float defaultValue)1028 float getFloat(String key, float defaultValue) { 1029 unparcel(); 1030 Object o = mMap.get(key); 1031 if (o == null) { 1032 return defaultValue; 1033 } 1034 try { 1035 return (Float) o; 1036 } catch (ClassCastException e) { 1037 typeWarning(key, o, "Float", defaultValue, e); 1038 return defaultValue; 1039 } 1040 } 1041 1042 /** 1043 * Returns the value associated with the given key, or 0.0 if 1044 * no mapping of the desired type exists for the given key. 1045 * 1046 * @param key a String 1047 * @return a double value 1048 */ getDouble(String key)1049 public double getDouble(String key) { 1050 unparcel(); 1051 return getDouble(key, 0.0); 1052 } 1053 1054 /** 1055 * Returns the value associated with the given key, or defaultValue if 1056 * no mapping of the desired type exists for the given key. 1057 * 1058 * @param key a String 1059 * @param defaultValue Value to return if key does not exist 1060 * @return a double value 1061 */ getDouble(String key, double defaultValue)1062 public double getDouble(String key, double defaultValue) { 1063 unparcel(); 1064 Object o = mMap.get(key); 1065 if (o == null) { 1066 return defaultValue; 1067 } 1068 try { 1069 return (Double) o; 1070 } catch (ClassCastException e) { 1071 typeWarning(key, o, "Double", defaultValue, e); 1072 return defaultValue; 1073 } 1074 } 1075 1076 /** 1077 * Returns the value associated with the given key, or null if 1078 * no mapping of the desired type exists for the given key or a null 1079 * value is explicitly associated with the key. 1080 * 1081 * @param key a String, or null 1082 * @return a String value, or null 1083 */ 1084 @Nullable getString(@ullable String key)1085 public String getString(@Nullable String key) { 1086 unparcel(); 1087 final Object o = mMap.get(key); 1088 try { 1089 return (String) o; 1090 } catch (ClassCastException e) { 1091 typeWarning(key, o, "String", e); 1092 return null; 1093 } 1094 } 1095 1096 /** 1097 * Returns the value associated with the given key, or defaultValue if 1098 * no mapping of the desired type exists for the given key or if a null 1099 * value is explicitly associated with the given key. 1100 * 1101 * @param key a String, or null 1102 * @param defaultValue Value to return if key does not exist or if a null 1103 * value is associated with the given key. 1104 * @return the String value associated with the given key, or defaultValue 1105 * if no valid String object is currently mapped to that key. 1106 */ getString(@ullable String key, String defaultValue)1107 public String getString(@Nullable String key, String defaultValue) { 1108 final String s = getString(key); 1109 return (s == null) ? defaultValue : s; 1110 } 1111 1112 /** 1113 * Returns the value associated with the given key, or null if 1114 * no mapping of the desired type exists for the given key or a null 1115 * value is explicitly associated with the key. 1116 * 1117 * @param key a String, or null 1118 * @return a CharSequence value, or null 1119 */ 1120 @Nullable getCharSequence(@ullable String key)1121 CharSequence getCharSequence(@Nullable String key) { 1122 unparcel(); 1123 final Object o = mMap.get(key); 1124 try { 1125 return (CharSequence) o; 1126 } catch (ClassCastException e) { 1127 typeWarning(key, o, "CharSequence", e); 1128 return null; 1129 } 1130 } 1131 1132 /** 1133 * Returns the value associated with the given key, or defaultValue if 1134 * no mapping of the desired type exists for the given key or if a null 1135 * value is explicitly associated with the given key. 1136 * 1137 * @param key a String, or null 1138 * @param defaultValue Value to return if key does not exist or if a null 1139 * value is associated with the given key. 1140 * @return the CharSequence value associated with the given key, or defaultValue 1141 * if no valid CharSequence object is currently mapped to that key. 1142 */ getCharSequence(@ullable String key, CharSequence defaultValue)1143 CharSequence getCharSequence(@Nullable String key, CharSequence defaultValue) { 1144 final CharSequence cs = getCharSequence(key); 1145 return (cs == null) ? defaultValue : cs; 1146 } 1147 1148 /** 1149 * Returns the value associated with the given key, or null if 1150 * no mapping of the desired type exists for the given key or a null 1151 * value is explicitly associated with the key. 1152 * 1153 * @param key a String, or null 1154 * @return a Serializable value, or null 1155 */ 1156 @Nullable getSerializable(@ullable String key)1157 Serializable getSerializable(@Nullable String key) { 1158 unparcel(); 1159 Object o = mMap.get(key); 1160 if (o == null) { 1161 return null; 1162 } 1163 try { 1164 return (Serializable) o; 1165 } catch (ClassCastException e) { 1166 typeWarning(key, o, "Serializable", e); 1167 return null; 1168 } 1169 } 1170 1171 /** 1172 * Returns the value associated with the given key, or null if 1173 * no mapping of the desired type exists for the given key or a null 1174 * value is explicitly associated with the key. 1175 * 1176 * @param key a String, or null 1177 * @return an ArrayList<String> value, or null 1178 */ 1179 @Nullable getIntegerArrayList(@ullable String key)1180 ArrayList<Integer> getIntegerArrayList(@Nullable String key) { 1181 unparcel(); 1182 Object o = mMap.get(key); 1183 if (o == null) { 1184 return null; 1185 } 1186 try { 1187 return (ArrayList<Integer>) o; 1188 } catch (ClassCastException e) { 1189 typeWarning(key, o, "ArrayList<Integer>", e); 1190 return null; 1191 } 1192 } 1193 1194 /** 1195 * Returns the value associated with the given key, or null if 1196 * no mapping of the desired type exists for the given key or a null 1197 * value is explicitly associated with the key. 1198 * 1199 * @param key a String, or null 1200 * @return an ArrayList<String> value, or null 1201 */ 1202 @Nullable getStringArrayList(@ullable String key)1203 ArrayList<String> getStringArrayList(@Nullable String key) { 1204 unparcel(); 1205 Object o = mMap.get(key); 1206 if (o == null) { 1207 return null; 1208 } 1209 try { 1210 return (ArrayList<String>) o; 1211 } catch (ClassCastException e) { 1212 typeWarning(key, o, "ArrayList<String>", e); 1213 return null; 1214 } 1215 } 1216 1217 /** 1218 * Returns the value associated with the given key, or null if 1219 * no mapping of the desired type exists for the given key or a null 1220 * value is explicitly associated with the key. 1221 * 1222 * @param key a String, or null 1223 * @return an ArrayList<CharSequence> value, or null 1224 */ 1225 @Nullable getCharSequenceArrayList(@ullable String key)1226 ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) { 1227 unparcel(); 1228 Object o = mMap.get(key); 1229 if (o == null) { 1230 return null; 1231 } 1232 try { 1233 return (ArrayList<CharSequence>) o; 1234 } catch (ClassCastException e) { 1235 typeWarning(key, o, "ArrayList<CharSequence>", e); 1236 return null; 1237 } 1238 } 1239 1240 /** 1241 * Returns the value associated with the given key, or null if 1242 * no mapping of the desired type exists for the given key or a null 1243 * value is explicitly associated with the key. 1244 * 1245 * @param key a String, or null 1246 * @return a boolean[] value, or null 1247 */ 1248 @Nullable getBooleanArray(@ullable String key)1249 public boolean[] getBooleanArray(@Nullable String key) { 1250 unparcel(); 1251 Object o = mMap.get(key); 1252 if (o == null) { 1253 return null; 1254 } 1255 try { 1256 return (boolean[]) o; 1257 } catch (ClassCastException e) { 1258 typeWarning(key, o, "byte[]", e); 1259 return null; 1260 } 1261 } 1262 1263 /** 1264 * Returns the value associated with the given key, or null if 1265 * no mapping of the desired type exists for the given key or a null 1266 * value is explicitly associated with the key. 1267 * 1268 * @param key a String, or null 1269 * @return a byte[] value, or null 1270 */ 1271 @Nullable getByteArray(@ullable String key)1272 byte[] getByteArray(@Nullable String key) { 1273 unparcel(); 1274 Object o = mMap.get(key); 1275 if (o == null) { 1276 return null; 1277 } 1278 try { 1279 return (byte[]) o; 1280 } catch (ClassCastException e) { 1281 typeWarning(key, o, "byte[]", e); 1282 return null; 1283 } 1284 } 1285 1286 /** 1287 * Returns the value associated with the given key, or null if 1288 * no mapping of the desired type exists for the given key or a null 1289 * value is explicitly associated with the key. 1290 * 1291 * @param key a String, or null 1292 * @return a short[] value, or null 1293 */ 1294 @Nullable getShortArray(@ullable String key)1295 short[] getShortArray(@Nullable String key) { 1296 unparcel(); 1297 Object o = mMap.get(key); 1298 if (o == null) { 1299 return null; 1300 } 1301 try { 1302 return (short[]) o; 1303 } catch (ClassCastException e) { 1304 typeWarning(key, o, "short[]", e); 1305 return null; 1306 } 1307 } 1308 1309 /** 1310 * Returns the value associated with the given key, or null if 1311 * no mapping of the desired type exists for the given key or a null 1312 * value is explicitly associated with the key. 1313 * 1314 * @param key a String, or null 1315 * @return a char[] value, or null 1316 */ 1317 @Nullable getCharArray(@ullable String key)1318 char[] getCharArray(@Nullable String key) { 1319 unparcel(); 1320 Object o = mMap.get(key); 1321 if (o == null) { 1322 return null; 1323 } 1324 try { 1325 return (char[]) o; 1326 } catch (ClassCastException e) { 1327 typeWarning(key, o, "char[]", e); 1328 return null; 1329 } 1330 } 1331 1332 /** 1333 * Returns the value associated with the given key, or null if 1334 * no mapping of the desired type exists for the given key or a null 1335 * value is explicitly associated with the key. 1336 * 1337 * @param key a String, or null 1338 * @return an int[] value, or null 1339 */ 1340 @Nullable getIntArray(@ullable String key)1341 public int[] getIntArray(@Nullable String key) { 1342 unparcel(); 1343 Object o = mMap.get(key); 1344 if (o == null) { 1345 return null; 1346 } 1347 try { 1348 return (int[]) o; 1349 } catch (ClassCastException e) { 1350 typeWarning(key, o, "int[]", e); 1351 return null; 1352 } 1353 } 1354 1355 /** 1356 * Returns the value associated with the given key, or null if 1357 * no mapping of the desired type exists for the given key or a null 1358 * value is explicitly associated with the key. 1359 * 1360 * @param key a String, or null 1361 * @return a long[] value, or null 1362 */ 1363 @Nullable getLongArray(@ullable String key)1364 public long[] getLongArray(@Nullable String key) { 1365 unparcel(); 1366 Object o = mMap.get(key); 1367 if (o == null) { 1368 return null; 1369 } 1370 try { 1371 return (long[]) o; 1372 } catch (ClassCastException e) { 1373 typeWarning(key, o, "long[]", 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 float[] value, or null 1385 */ 1386 @Nullable getFloatArray(@ullable String key)1387 float[] getFloatArray(@Nullable String key) { 1388 unparcel(); 1389 Object o = mMap.get(key); 1390 if (o == null) { 1391 return null; 1392 } 1393 try { 1394 return (float[]) o; 1395 } catch (ClassCastException e) { 1396 typeWarning(key, o, "float[]", e); 1397 return null; 1398 } 1399 } 1400 1401 /** 1402 * Returns the value associated with the given key, or null if 1403 * no mapping of the desired type exists for the given key or a null 1404 * value is explicitly associated with the key. 1405 * 1406 * @param key a String, or null 1407 * @return a double[] value, or null 1408 */ 1409 @Nullable getDoubleArray(@ullable String key)1410 public double[] getDoubleArray(@Nullable String key) { 1411 unparcel(); 1412 Object o = mMap.get(key); 1413 if (o == null) { 1414 return null; 1415 } 1416 try { 1417 return (double[]) o; 1418 } catch (ClassCastException e) { 1419 typeWarning(key, o, "double[]", e); 1420 return null; 1421 } 1422 } 1423 1424 /** 1425 * Returns the value associated with the given key, or null if 1426 * no mapping of the desired type exists for the given key or a null 1427 * value is explicitly associated with the key. 1428 * 1429 * @param key a String, or null 1430 * @return a String[] value, or null 1431 */ 1432 @Nullable getStringArray(@ullable String key)1433 public String[] getStringArray(@Nullable String key) { 1434 unparcel(); 1435 Object o = mMap.get(key); 1436 if (o == null) { 1437 return null; 1438 } 1439 try { 1440 return (String[]) o; 1441 } catch (ClassCastException e) { 1442 typeWarning(key, o, "String[]", e); 1443 return null; 1444 } 1445 } 1446 1447 /** 1448 * Returns the value associated with the given key, or null if 1449 * no mapping of the desired type exists for the given key or a null 1450 * value is explicitly associated with the key. 1451 * 1452 * @param key a String, or null 1453 * @return a CharSequence[] value, or null 1454 */ 1455 @Nullable getCharSequenceArray(@ullable String key)1456 CharSequence[] getCharSequenceArray(@Nullable String key) { 1457 unparcel(); 1458 Object o = mMap.get(key); 1459 if (o == null) { 1460 return null; 1461 } 1462 try { 1463 return (CharSequence[]) o; 1464 } catch (ClassCastException e) { 1465 typeWarning(key, o, "CharSequence[]", e); 1466 return null; 1467 } 1468 } 1469 1470 /** 1471 * Writes the Bundle contents to a Parcel, typically in order for 1472 * it to be passed through an IBinder connection. 1473 * @param parcel The parcel to copy this bundle to. 1474 */ writeToParcelInner(Parcel parcel, int flags)1475 void writeToParcelInner(Parcel parcel, int flags) { 1476 // Keep implementation in sync with writeToParcel() in 1477 // frameworks/native/libs/binder/PersistableBundle.cpp. 1478 final ArrayMap<String, Object> map; 1479 synchronized (this) { 1480 // unparcel() can race with this method and cause the parcel to recycle 1481 // at the wrong time. So synchronize access the mParcelledData's content. 1482 if (mParcelledData != null) { 1483 if (mParcelledData == NoImagePreloadHolder.EMPTY_PARCEL) { 1484 parcel.writeInt(0); 1485 } else { 1486 int length = mParcelledData.dataSize(); 1487 parcel.writeInt(length); 1488 parcel.writeInt(BUNDLE_MAGIC); 1489 parcel.appendFrom(mParcelledData, 0, length); 1490 } 1491 return; 1492 } 1493 map = mMap; 1494 } 1495 1496 // Special case for empty bundles. 1497 if (map == null || map.size() <= 0) { 1498 parcel.writeInt(0); 1499 return; 1500 } 1501 int lengthPos = parcel.dataPosition(); 1502 parcel.writeInt(-1); // dummy, will hold length 1503 parcel.writeInt(BUNDLE_MAGIC); 1504 1505 int startPos = parcel.dataPosition(); 1506 parcel.writeArrayMapInternal(map); 1507 int endPos = parcel.dataPosition(); 1508 1509 // Backpatch length 1510 parcel.setDataPosition(lengthPos); 1511 int length = endPos - startPos; 1512 parcel.writeInt(length); 1513 parcel.setDataPosition(endPos); 1514 } 1515 1516 /** 1517 * Reads the Parcel contents into this Bundle, typically in order for 1518 * it to be passed through an IBinder connection. 1519 * @param parcel The parcel to overwrite this bundle from. 1520 */ readFromParcelInner(Parcel parcel)1521 void readFromParcelInner(Parcel parcel) { 1522 // Keep implementation in sync with readFromParcel() in 1523 // frameworks/native/libs/binder/PersistableBundle.cpp. 1524 int length = parcel.readInt(); 1525 readFromParcelInner(parcel, length); 1526 } 1527 readFromParcelInner(Parcel parcel, int length)1528 private void readFromParcelInner(Parcel parcel, int length) { 1529 if (length < 0) { 1530 throw new RuntimeException("Bad length in parcel: " + length); 1531 1532 } else if (length == 0) { 1533 // Empty Bundle or end of data. 1534 mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL; 1535 return; 1536 } 1537 1538 final int magic = parcel.readInt(); 1539 if (magic != BUNDLE_MAGIC) { 1540 throw new IllegalStateException("Bad magic number for Bundle: 0x" 1541 + Integer.toHexString(magic)); 1542 } 1543 1544 // Advance within this Parcel 1545 int offset = parcel.dataPosition(); 1546 parcel.setDataPosition(MathUtils.addOrThrow(offset, length)); 1547 1548 Parcel p = Parcel.obtain(); 1549 p.setDataPosition(0); 1550 p.appendFrom(parcel, offset, length); 1551 p.adoptClassCookies(parcel); 1552 if (DEBUG) Log.d(TAG, "Retrieving " + Integer.toHexString(System.identityHashCode(this)) 1553 + ": " + length + " bundle bytes starting at " + offset); 1554 p.setDataPosition(0); 1555 1556 mParcelledData = p; 1557 } 1558 } 1559