1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os; 18 19 import android.annotation.Nullable; 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.util.ArrayMap; 22 import android.util.Size; 23 import android.util.SizeF; 24 import android.util.SparseArray; 25 import android.util.proto.ProtoOutputStream; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 29 import java.io.Serializable; 30 import java.util.ArrayList; 31 import java.util.List; 32 33 /** 34 * A mapping from String keys to various {@link Parcelable} values. 35 * 36 * @see PersistableBundle 37 */ 38 public final class Bundle extends BaseBundle implements Cloneable, Parcelable { 39 @VisibleForTesting 40 static final int FLAG_HAS_FDS = 1 << 8; 41 42 @VisibleForTesting 43 static final int FLAG_HAS_FDS_KNOWN = 1 << 9; 44 45 @VisibleForTesting 46 static final int FLAG_ALLOW_FDS = 1 << 10; 47 48 public static final Bundle EMPTY; 49 50 /** 51 * Special extras used to denote extras have been stripped off. 52 * @hide 53 */ 54 public static final Bundle STRIPPED; 55 56 static { 57 EMPTY = new Bundle(); 58 EMPTY.mMap = ArrayMap.EMPTY; 59 60 STRIPPED = new Bundle(); 61 STRIPPED.putInt("STRIPPED", 1); 62 } 63 64 /** 65 * Constructs a new, empty Bundle. 66 */ Bundle()67 public Bundle() { 68 super(); 69 mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; 70 } 71 72 /** 73 * Constructs a Bundle whose data is stored as a Parcel. The data 74 * will be unparcelled on first contact, using the assigned ClassLoader. 75 * 76 * @param parcelledData a Parcel containing a Bundle 77 * 78 * @hide 79 */ 80 @VisibleForTesting Bundle(Parcel parcelledData)81 public Bundle(Parcel parcelledData) { 82 super(parcelledData); 83 mFlags = FLAG_ALLOW_FDS; 84 maybePrefillHasFds(); 85 } 86 87 /** 88 * Constructor from a parcel for when the length is known *and is not stored in the parcel.* 89 * The other constructor that takes a parcel assumes the length is in the parcel. 90 * 91 * @hide 92 */ 93 @VisibleForTesting Bundle(Parcel parcelledData, int length)94 public Bundle(Parcel parcelledData, int length) { 95 super(parcelledData, length); 96 mFlags = FLAG_ALLOW_FDS; 97 maybePrefillHasFds(); 98 } 99 100 /** 101 * If {@link #mParcelledData} is not null, copy the HAS FDS bit from it because it's fast. 102 * Otherwise (if {@link #mParcelledData} is already null), leave {@link #FLAG_HAS_FDS_KNOWN} 103 * unset, because scanning a map is slower. We'll do it lazily in 104 * {@link #hasFileDescriptors()}. 105 */ maybePrefillHasFds()106 private void maybePrefillHasFds() { 107 if (mParcelledData != null) { 108 if (mParcelledData.hasFileDescriptors()) { 109 mFlags |= FLAG_HAS_FDS | FLAG_HAS_FDS_KNOWN; 110 } else { 111 mFlags |= FLAG_HAS_FDS_KNOWN; 112 } 113 } 114 } 115 116 /** 117 * Constructs a new, empty Bundle that uses a specific ClassLoader for 118 * instantiating Parcelable and Serializable objects. 119 * 120 * @param loader An explicit ClassLoader to use when instantiating objects 121 * inside of the Bundle. 122 */ Bundle(ClassLoader loader)123 public Bundle(ClassLoader loader) { 124 super(loader); 125 mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; 126 } 127 128 /** 129 * Constructs a new, empty Bundle sized to hold the given number of 130 * elements. The Bundle will grow as needed. 131 * 132 * @param capacity the initial capacity of the Bundle 133 */ Bundle(int capacity)134 public Bundle(int capacity) { 135 super(capacity); 136 mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; 137 } 138 139 /** 140 * Constructs a Bundle containing a copy of the mappings from the given 141 * Bundle. Does only a shallow copy of the original Bundle -- see 142 * {@link #deepCopy()} if that is not what you want. 143 * 144 * @param b a Bundle to be copied. 145 * 146 * @see #deepCopy() 147 */ Bundle(Bundle b)148 public Bundle(Bundle b) { 149 super(b); 150 mFlags = b.mFlags; 151 } 152 153 /** 154 * Constructs a Bundle containing a copy of the mappings from the given 155 * PersistableBundle. Does only a shallow copy of the PersistableBundle -- see 156 * {@link PersistableBundle#deepCopy()} if you don't want that. 157 * 158 * @param b a PersistableBundle to be copied. 159 */ Bundle(PersistableBundle b)160 public Bundle(PersistableBundle b) { 161 super(b); 162 mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; 163 } 164 165 /** 166 * Constructs a Bundle without initializing it. 167 */ Bundle(boolean doInit)168 Bundle(boolean doInit) { 169 super(doInit); 170 } 171 172 /** 173 * Make a Bundle for a single key/value pair. 174 * 175 * @hide 176 */ 177 @UnsupportedAppUsage forPair(String key, String value)178 public static Bundle forPair(String key, String value) { 179 Bundle b = new Bundle(1); 180 b.putString(key, value); 181 return b; 182 } 183 184 /** 185 * Changes the ClassLoader this Bundle uses when instantiating objects. 186 * 187 * @param loader An explicit ClassLoader to use when instantiating objects 188 * inside of the Bundle. 189 */ 190 @Override setClassLoader(ClassLoader loader)191 public void setClassLoader(ClassLoader loader) { 192 super.setClassLoader(loader); 193 } 194 195 /** 196 * Return the ClassLoader currently associated with this Bundle. 197 */ 198 @Override getClassLoader()199 public ClassLoader getClassLoader() { 200 return super.getClassLoader(); 201 } 202 203 /** {@hide} */ setAllowFds(boolean allowFds)204 public boolean setAllowFds(boolean allowFds) { 205 final boolean orig = (mFlags & FLAG_ALLOW_FDS) != 0; 206 if (allowFds) { 207 mFlags |= FLAG_ALLOW_FDS; 208 } else { 209 mFlags &= ~FLAG_ALLOW_FDS; 210 } 211 return orig; 212 } 213 214 /** 215 * Mark if this Bundle is okay to "defuse." That is, it's okay for system 216 * processes to ignore any {@link BadParcelableException} encountered when 217 * unparceling it, leaving an empty bundle in its place. 218 * <p> 219 * This should <em>only</em> be set when the Bundle reaches its final 220 * destination, otherwise a system process may clobber contents that were 221 * destined for an app that could have unparceled them. 222 * 223 * @hide 224 */ setDefusable(boolean defusable)225 public void setDefusable(boolean defusable) { 226 if (defusable) { 227 mFlags |= FLAG_DEFUSABLE; 228 } else { 229 mFlags &= ~FLAG_DEFUSABLE; 230 } 231 } 232 233 /** {@hide} */ 234 @UnsupportedAppUsage setDefusable(Bundle bundle, boolean defusable)235 public static Bundle setDefusable(Bundle bundle, boolean defusable) { 236 if (bundle != null) { 237 bundle.setDefusable(defusable); 238 } 239 return bundle; 240 } 241 242 /** 243 * Clones the current Bundle. The internal map is cloned, but the keys and 244 * values to which it refers are copied by reference. 245 */ 246 @Override clone()247 public Object clone() { 248 return new Bundle(this); 249 } 250 251 /** 252 * Make a deep copy of the given bundle. Traverses into inner containers and copies 253 * them as well, so they are not shared across bundles. Will traverse in to 254 * {@link Bundle}, {@link PersistableBundle}, {@link ArrayList}, and all types of 255 * primitive arrays. Other types of objects (such as Parcelable or Serializable) 256 * are referenced as-is and not copied in any way. 257 */ deepCopy()258 public Bundle deepCopy() { 259 Bundle b = new Bundle(false); 260 b.copyInternal(this, true); 261 return b; 262 } 263 264 /** 265 * Removes all elements from the mapping of this Bundle. 266 */ 267 @Override clear()268 public void clear() { 269 super.clear(); 270 mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; 271 } 272 273 /** 274 * Removes any entry with the given key from the mapping of this Bundle. 275 * 276 * @param key a String key 277 */ remove(String key)278 public void remove(String key) { 279 super.remove(key); 280 if ((mFlags & FLAG_HAS_FDS) != 0) { 281 mFlags &= ~FLAG_HAS_FDS_KNOWN; 282 } 283 } 284 285 /** 286 * Inserts all mappings from the given Bundle into this Bundle. 287 * 288 * @param bundle a Bundle 289 */ putAll(Bundle bundle)290 public void putAll(Bundle bundle) { 291 unparcel(); 292 bundle.unparcel(); 293 mMap.putAll(bundle.mMap); 294 295 // FD state is now known if and only if both bundles already knew 296 if ((bundle.mFlags & FLAG_HAS_FDS) != 0) { 297 mFlags |= FLAG_HAS_FDS; 298 } 299 if ((bundle.mFlags & FLAG_HAS_FDS_KNOWN) == 0) { 300 mFlags &= ~FLAG_HAS_FDS_KNOWN; 301 } 302 } 303 304 /** 305 * Return the size of {@link #mParcelledData} in bytes if available, otherwise {@code 0}. 306 * 307 * @hide 308 */ 309 @UnsupportedAppUsage getSize()310 public int getSize() { 311 if (mParcelledData != null) { 312 return mParcelledData.dataSize(); 313 } else { 314 return 0; 315 } 316 } 317 318 /** 319 * Reports whether the bundle contains any parcelled file descriptors. 320 */ hasFileDescriptors()321 public boolean hasFileDescriptors() { 322 if ((mFlags & FLAG_HAS_FDS_KNOWN) == 0) { 323 boolean fdFound = false; // keep going until we find one or run out of data 324 325 if (mParcelledData != null) { 326 if (mParcelledData.hasFileDescriptors()) { 327 fdFound = true; 328 } 329 } else { 330 // It's been unparcelled, so we need to walk the map 331 for (int i=mMap.size()-1; i>=0; i--) { 332 Object obj = mMap.valueAt(i); 333 if (obj instanceof Parcelable) { 334 if ((((Parcelable)obj).describeContents() 335 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) { 336 fdFound = true; 337 break; 338 } 339 } else if (obj instanceof Parcelable[]) { 340 Parcelable[] array = (Parcelable[]) obj; 341 for (int n = array.length - 1; n >= 0; n--) { 342 Parcelable p = array[n]; 343 if (p != null && ((p.describeContents() 344 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) { 345 fdFound = true; 346 break; 347 } 348 } 349 } else if (obj instanceof SparseArray) { 350 SparseArray<? extends Parcelable> array = 351 (SparseArray<? extends Parcelable>) obj; 352 for (int n = array.size() - 1; n >= 0; n--) { 353 Parcelable p = array.valueAt(n); 354 if (p != null && (p.describeContents() 355 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) { 356 fdFound = true; 357 break; 358 } 359 } 360 } else if (obj instanceof ArrayList) { 361 ArrayList array = (ArrayList) obj; 362 // an ArrayList here might contain either Strings or 363 // Parcelables; only look inside for Parcelables 364 if (!array.isEmpty() && (array.get(0) instanceof Parcelable)) { 365 for (int n = array.size() - 1; n >= 0; n--) { 366 Parcelable p = (Parcelable) array.get(n); 367 if (p != null && ((p.describeContents() 368 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) { 369 fdFound = true; 370 break; 371 } 372 } 373 } 374 } 375 } 376 } 377 378 if (fdFound) { 379 mFlags |= FLAG_HAS_FDS; 380 } else { 381 mFlags &= ~FLAG_HAS_FDS; 382 } 383 mFlags |= FLAG_HAS_FDS_KNOWN; 384 } 385 return (mFlags & FLAG_HAS_FDS) != 0; 386 } 387 388 /** 389 * Filter values in Bundle to only basic types. 390 * @hide 391 */ 392 @UnsupportedAppUsage filterValues()393 public Bundle filterValues() { 394 unparcel(); 395 Bundle bundle = this; 396 if (mMap != null) { 397 ArrayMap<String, Object> map = mMap; 398 for (int i = map.size() - 1; i >= 0; i--) { 399 Object value = map.valueAt(i); 400 if (PersistableBundle.isValidType(value)) { 401 continue; 402 } 403 if (value instanceof Bundle) { 404 Bundle newBundle = ((Bundle)value).filterValues(); 405 if (newBundle != value) { 406 if (map == mMap) { 407 // The filter had to generate a new bundle, but we have not yet 408 // created a new one here. Do that now. 409 bundle = new Bundle(this); 410 // Note the ArrayMap<> constructor is guaranteed to generate 411 // a new object with items in the same order as the original. 412 map = bundle.mMap; 413 } 414 // Replace this current entry with the new child bundle. 415 map.setValueAt(i, newBundle); 416 } 417 continue; 418 } 419 if (value.getClass().getName().startsWith("android.")) { 420 continue; 421 } 422 if (map == mMap) { 423 // This is the first time we have had to remove something, that means we 424 // need to switch to a new Bundle. 425 bundle = new Bundle(this); 426 // Note the ArrayMap<> constructor is guaranteed to generate 427 // a new object with items in the same order as the original. 428 map = bundle.mMap; 429 } 430 map.removeAt(i); 431 } 432 } 433 mFlags |= FLAG_HAS_FDS_KNOWN; 434 mFlags &= ~FLAG_HAS_FDS; 435 return bundle; 436 } 437 438 /** {@hide} */ 439 @Override putObject(@ullable String key, @Nullable Object value)440 public void putObject(@Nullable String key, @Nullable Object value) { 441 if (value instanceof Byte) { 442 putByte(key, (Byte) value); 443 } else if (value instanceof Character) { 444 putChar(key, (Character) value); 445 } else if (value instanceof Short) { 446 putShort(key, (Short) value); 447 } else if (value instanceof Float) { 448 putFloat(key, (Float) value); 449 } else if (value instanceof CharSequence) { 450 putCharSequence(key, (CharSequence) value); 451 } else if (value instanceof Parcelable) { 452 putParcelable(key, (Parcelable) value); 453 } else if (value instanceof Size) { 454 putSize(key, (Size) value); 455 } else if (value instanceof SizeF) { 456 putSizeF(key, (SizeF) value); 457 } else if (value instanceof Parcelable[]) { 458 putParcelableArray(key, (Parcelable[]) value); 459 } else if (value instanceof ArrayList) { 460 putParcelableArrayList(key, (ArrayList) value); 461 } else if (value instanceof List) { 462 putParcelableList(key, (List) value); 463 } else if (value instanceof SparseArray) { 464 putSparseParcelableArray(key, (SparseArray) value); 465 } else if (value instanceof Serializable) { 466 putSerializable(key, (Serializable) value); 467 } else if (value instanceof byte[]) { 468 putByteArray(key, (byte[]) value); 469 } else if (value instanceof short[]) { 470 putShortArray(key, (short[]) value); 471 } else if (value instanceof char[]) { 472 putCharArray(key, (char[]) value); 473 } else if (value instanceof float[]) { 474 putFloatArray(key, (float[]) value); 475 } else if (value instanceof CharSequence[]) { 476 putCharSequenceArray(key, (CharSequence[]) value); 477 } else if (value instanceof Bundle) { 478 putBundle(key, (Bundle) value); 479 } else if (value instanceof Binder) { 480 putBinder(key, (Binder) value); 481 } else if (value instanceof IBinder) { 482 putIBinder(key, (IBinder) value); 483 } else { 484 super.putObject(key, value); 485 } 486 } 487 488 /** 489 * Inserts a byte value into the mapping of this Bundle, replacing 490 * any existing value for the given key. 491 * 492 * @param key a String, or null 493 * @param value a byte 494 */ 495 @Override putByte(@ullable String key, byte value)496 public void putByte(@Nullable String key, byte value) { 497 super.putByte(key, value); 498 } 499 500 /** 501 * Inserts a char value into the mapping of this Bundle, replacing 502 * any existing value for the given key. 503 * 504 * @param key a String, or null 505 * @param value a char 506 */ 507 @Override putChar(@ullable String key, char value)508 public void putChar(@Nullable String key, char value) { 509 super.putChar(key, value); 510 } 511 512 /** 513 * Inserts a short value into the mapping of this Bundle, replacing 514 * any existing value for the given key. 515 * 516 * @param key a String, or null 517 * @param value a short 518 */ 519 @Override putShort(@ullable String key, short value)520 public void putShort(@Nullable String key, short value) { 521 super.putShort(key, value); 522 } 523 524 /** 525 * Inserts a float value into the mapping of this Bundle, replacing 526 * any existing value for the given key. 527 * 528 * @param key a String, or null 529 * @param value a float 530 */ 531 @Override putFloat(@ullable String key, float value)532 public void putFloat(@Nullable String key, float value) { 533 super.putFloat(key, value); 534 } 535 536 /** 537 * Inserts a CharSequence value into the mapping of this Bundle, replacing 538 * any existing value for the given key. Either key or value may be null. 539 * 540 * @param key a String, or null 541 * @param value a CharSequence, or null 542 */ 543 @Override putCharSequence(@ullable String key, @Nullable CharSequence value)544 public void putCharSequence(@Nullable String key, @Nullable CharSequence value) { 545 super.putCharSequence(key, value); 546 } 547 548 /** 549 * Inserts a Parcelable value into the mapping of this Bundle, replacing 550 * any existing value for the given key. Either key or value may be null. 551 * 552 * @param key a String, or null 553 * @param value a Parcelable object, or null 554 */ putParcelable(@ullable String key, @Nullable Parcelable value)555 public void putParcelable(@Nullable String key, @Nullable Parcelable value) { 556 unparcel(); 557 mMap.put(key, value); 558 mFlags &= ~FLAG_HAS_FDS_KNOWN; 559 } 560 561 /** 562 * Inserts a Size value into the mapping of this Bundle, replacing 563 * any existing value for the given key. Either key or value may be null. 564 * 565 * @param key a String, or null 566 * @param value a Size object, or null 567 */ putSize(@ullable String key, @Nullable Size value)568 public void putSize(@Nullable String key, @Nullable Size value) { 569 unparcel(); 570 mMap.put(key, value); 571 } 572 573 /** 574 * Inserts a SizeF value into the mapping of this Bundle, replacing 575 * any existing value for the given key. Either key or value may be null. 576 * 577 * @param key a String, or null 578 * @param value a SizeF object, or null 579 */ putSizeF(@ullable String key, @Nullable SizeF value)580 public void putSizeF(@Nullable String key, @Nullable SizeF value) { 581 unparcel(); 582 mMap.put(key, value); 583 } 584 585 /** 586 * Inserts an array of Parcelable values into the mapping of this Bundle, 587 * replacing any existing value for the given key. Either key or value may 588 * be null. 589 * 590 * @param key a String, or null 591 * @param value an array of Parcelable objects, or null 592 */ putParcelableArray(@ullable String key, @Nullable Parcelable[] value)593 public void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) { 594 unparcel(); 595 mMap.put(key, value); 596 mFlags &= ~FLAG_HAS_FDS_KNOWN; 597 } 598 599 /** 600 * Inserts a List of Parcelable values into the mapping of this Bundle, 601 * replacing any existing value for the given key. Either key or value may 602 * be null. 603 * 604 * @param key a String, or null 605 * @param value an ArrayList of Parcelable objects, or null 606 */ putParcelableArrayList(@ullable String key, @Nullable ArrayList<? extends Parcelable> value)607 public void putParcelableArrayList(@Nullable String key, 608 @Nullable ArrayList<? extends Parcelable> value) { 609 unparcel(); 610 mMap.put(key, value); 611 mFlags &= ~FLAG_HAS_FDS_KNOWN; 612 } 613 614 /** {@hide} */ 615 @UnsupportedAppUsage putParcelableList(String key, List<? extends Parcelable> value)616 public void putParcelableList(String key, List<? extends Parcelable> value) { 617 unparcel(); 618 mMap.put(key, value); 619 mFlags &= ~FLAG_HAS_FDS_KNOWN; 620 } 621 622 /** 623 * Inserts a SparceArray of Parcelable values into the mapping of this 624 * Bundle, replacing any existing value for the given key. Either key 625 * or value may be null. 626 * 627 * @param key a String, or null 628 * @param value a SparseArray of Parcelable objects, or null 629 */ putSparseParcelableArray(@ullable String key, @Nullable SparseArray<? extends Parcelable> value)630 public void putSparseParcelableArray(@Nullable String key, 631 @Nullable SparseArray<? extends Parcelable> value) { 632 unparcel(); 633 mMap.put(key, value); 634 mFlags &= ~FLAG_HAS_FDS_KNOWN; 635 } 636 637 /** 638 * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing 639 * any existing value for the given key. Either key or value may be null. 640 * 641 * @param key a String, or null 642 * @param value an ArrayList<Integer> object, or null 643 */ 644 @Override putIntegerArrayList(@ullable String key, @Nullable ArrayList<Integer> value)645 public void putIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) { 646 super.putIntegerArrayList(key, value); 647 } 648 649 /** 650 * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing 651 * any existing value for the given key. Either key or value may be null. 652 * 653 * @param key a String, or null 654 * @param value an ArrayList<String> object, or null 655 */ 656 @Override putStringArrayList(@ullable String key, @Nullable ArrayList<String> value)657 public void putStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) { 658 super.putStringArrayList(key, value); 659 } 660 661 /** 662 * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing 663 * any existing value for the given key. Either key or value may be null. 664 * 665 * @param key a String, or null 666 * @param value an ArrayList<CharSequence> object, or null 667 */ 668 @Override putCharSequenceArrayList(@ullable String key, @Nullable ArrayList<CharSequence> value)669 public void putCharSequenceArrayList(@Nullable String key, 670 @Nullable ArrayList<CharSequence> value) { 671 super.putCharSequenceArrayList(key, value); 672 } 673 674 /** 675 * Inserts a Serializable value into the mapping of this Bundle, replacing 676 * any existing value for the given key. Either key or value may be null. 677 * 678 * @param key a String, or null 679 * @param value a Serializable object, or null 680 */ 681 @Override putSerializable(@ullable String key, @Nullable Serializable value)682 public void putSerializable(@Nullable String key, @Nullable Serializable value) { 683 super.putSerializable(key, value); 684 } 685 686 /** 687 * Inserts a byte array value into the mapping of this Bundle, replacing 688 * any existing value for the given key. Either key or value may be null. 689 * 690 * @param key a String, or null 691 * @param value a byte array object, or null 692 */ 693 @Override putByteArray(@ullable String key, @Nullable byte[] value)694 public void putByteArray(@Nullable String key, @Nullable byte[] value) { 695 super.putByteArray(key, value); 696 } 697 698 /** 699 * Inserts a short array value into the mapping of this Bundle, replacing 700 * any existing value for the given key. Either key or value may be null. 701 * 702 * @param key a String, or null 703 * @param value a short array object, or null 704 */ 705 @Override putShortArray(@ullable String key, @Nullable short[] value)706 public void putShortArray(@Nullable String key, @Nullable short[] value) { 707 super.putShortArray(key, value); 708 } 709 710 /** 711 * Inserts a char array value into the mapping of this Bundle, replacing 712 * any existing value for the given key. Either key or value may be null. 713 * 714 * @param key a String, or null 715 * @param value a char array object, or null 716 */ 717 @Override putCharArray(@ullable String key, @Nullable char[] value)718 public void putCharArray(@Nullable String key, @Nullable char[] value) { 719 super.putCharArray(key, value); 720 } 721 722 /** 723 * Inserts a float array value into the mapping of this Bundle, replacing 724 * any existing value for the given key. Either key or value may be null. 725 * 726 * @param key a String, or null 727 * @param value a float array object, or null 728 */ 729 @Override putFloatArray(@ullable String key, @Nullable float[] value)730 public void putFloatArray(@Nullable String key, @Nullable float[] value) { 731 super.putFloatArray(key, value); 732 } 733 734 /** 735 * Inserts a CharSequence array value into the mapping of this Bundle, replacing 736 * any existing value for the given key. Either key or value may be null. 737 * 738 * @param key a String, or null 739 * @param value a CharSequence array object, or null 740 */ 741 @Override putCharSequenceArray(@ullable String key, @Nullable CharSequence[] value)742 public void putCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) { 743 super.putCharSequenceArray(key, value); 744 } 745 746 /** 747 * Inserts a Bundle value into the mapping of this Bundle, replacing 748 * any existing value for the given key. Either key or value may be null. 749 * 750 * @param key a String, or null 751 * @param value a Bundle object, or null 752 */ putBundle(@ullable String key, @Nullable Bundle value)753 public void putBundle(@Nullable String key, @Nullable Bundle value) { 754 unparcel(); 755 mMap.put(key, value); 756 } 757 758 /** 759 * Inserts an {@link IBinder} value into the mapping of this Bundle, replacing 760 * any existing value for the given key. Either key or value may be null. 761 * 762 * <p class="note">You should be very careful when using this function. In many 763 * places where Bundles are used (such as inside of Intent objects), the Bundle 764 * can live longer inside of another process than the process that had originally 765 * created it. In that case, the IBinder you supply here will become invalid 766 * when your process goes away, and no longer usable, even if a new process is 767 * created for you later on.</p> 768 * 769 * @param key a String, or null 770 * @param value an IBinder object, or null 771 */ putBinder(@ullable String key, @Nullable IBinder value)772 public void putBinder(@Nullable String key, @Nullable IBinder value) { 773 unparcel(); 774 mMap.put(key, value); 775 } 776 777 /** 778 * Inserts an IBinder value into the mapping of this Bundle, replacing 779 * any existing value for the given key. Either key or value may be null. 780 * 781 * @param key a String, or null 782 * @param value an IBinder object, or null 783 * 784 * @deprecated 785 * @hide This is the old name of the function. 786 */ 787 @UnsupportedAppUsage 788 @Deprecated putIBinder(@ullable String key, @Nullable IBinder value)789 public void putIBinder(@Nullable String key, @Nullable IBinder value) { 790 unparcel(); 791 mMap.put(key, value); 792 } 793 794 /** 795 * Returns the value associated with the given key, or (byte) 0 if 796 * no mapping of the desired type exists for the given key. 797 * 798 * @param key a String 799 * @return a byte value 800 */ 801 @Override getByte(String key)802 public byte getByte(String key) { 803 return super.getByte(key); 804 } 805 806 /** 807 * Returns the value associated with the given key, or defaultValue if 808 * no mapping of the desired type exists for the given key. 809 * 810 * @param key a String 811 * @param defaultValue Value to return if key does not exist 812 * @return a byte value 813 */ 814 @Override getByte(String key, byte defaultValue)815 public Byte getByte(String key, byte defaultValue) { 816 return super.getByte(key, defaultValue); 817 } 818 819 /** 820 * Returns the value associated with the given key, or (char) 0 if 821 * no mapping of the desired type exists for the given key. 822 * 823 * @param key a String 824 * @return a char value 825 */ 826 @Override getChar(String key)827 public char getChar(String key) { 828 return super.getChar(key); 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 char value 838 */ 839 @Override getChar(String key, char defaultValue)840 public char getChar(String key, char defaultValue) { 841 return super.getChar(key, defaultValue); 842 } 843 844 /** 845 * Returns the value associated with the given key, or (short) 0 if 846 * no mapping of the desired type exists for the given key. 847 * 848 * @param key a String 849 * @return a short value 850 */ 851 @Override getShort(String key)852 public short getShort(String key) { 853 return super.getShort(key); 854 } 855 856 /** 857 * Returns the value associated with the given key, or defaultValue if 858 * no mapping of the desired type exists for the given key. 859 * 860 * @param key a String 861 * @param defaultValue Value to return if key does not exist 862 * @return a short value 863 */ 864 @Override getShort(String key, short defaultValue)865 public short getShort(String key, short defaultValue) { 866 return super.getShort(key, defaultValue); 867 } 868 869 /** 870 * Returns the value associated with the given key, or 0.0f if 871 * no mapping of the desired type exists for the given key. 872 * 873 * @param key a String 874 * @return a float value 875 */ 876 @Override getFloat(String key)877 public float getFloat(String key) { 878 return super.getFloat(key); 879 } 880 881 /** 882 * Returns the value associated with the given key, or defaultValue if 883 * no mapping of the desired type exists for the given key. 884 * 885 * @param key a String 886 * @param defaultValue Value to return if key does not exist 887 * @return a float value 888 */ 889 @Override getFloat(String key, float defaultValue)890 public float getFloat(String key, float defaultValue) { 891 return super.getFloat(key, defaultValue); 892 } 893 894 /** 895 * Returns the value associated with the given key, or null if 896 * no mapping of the desired type exists for the given key or a null 897 * value is explicitly associated with the key. 898 * 899 * @param key a String, or null 900 * @return a CharSequence value, or null 901 */ 902 @Override 903 @Nullable getCharSequence(@ullable String key)904 public CharSequence getCharSequence(@Nullable String key) { 905 return super.getCharSequence(key); 906 } 907 908 /** 909 * Returns the value associated with the given key, or defaultValue if 910 * no mapping of the desired type exists for the given key or if a null 911 * value is explicitly associatd with the given key. 912 * 913 * @param key a String, or null 914 * @param defaultValue Value to return if key does not exist or if a null 915 * value is associated with the given key. 916 * @return the CharSequence value associated with the given key, or defaultValue 917 * if no valid CharSequence object is currently mapped to that key. 918 */ 919 @Override getCharSequence(@ullable String key, CharSequence defaultValue)920 public CharSequence getCharSequence(@Nullable String key, CharSequence defaultValue) { 921 return super.getCharSequence(key, defaultValue); 922 } 923 924 /** 925 * Returns the value associated with the given key, or null if 926 * no mapping of the desired type exists for the given key or a null 927 * value is explicitly associated with the key. 928 * 929 * @param key a String, or null 930 * @return a Size value, or null 931 */ 932 @Nullable getSize(@ullable String key)933 public Size getSize(@Nullable String key) { 934 unparcel(); 935 final Object o = mMap.get(key); 936 try { 937 return (Size) o; 938 } catch (ClassCastException e) { 939 typeWarning(key, o, "Size", e); 940 return null; 941 } 942 } 943 944 /** 945 * Returns the value associated with the given key, or null if 946 * no mapping of the desired type exists for the given key or a null 947 * value is explicitly associated with the key. 948 * 949 * @param key a String, or null 950 * @return a Size value, or null 951 */ 952 @Nullable getSizeF(@ullable String key)953 public SizeF getSizeF(@Nullable String key) { 954 unparcel(); 955 final Object o = mMap.get(key); 956 try { 957 return (SizeF) o; 958 } catch (ClassCastException e) { 959 typeWarning(key, o, "SizeF", e); 960 return null; 961 } 962 } 963 964 /** 965 * Returns the value associated with the given key, or null if 966 * no mapping of the desired type exists for the given key or a null 967 * value is explicitly associated with the key. 968 * 969 * @param key a String, or null 970 * @return a Bundle value, or null 971 */ 972 @Nullable getBundle(@ullable String key)973 public Bundle getBundle(@Nullable String key) { 974 unparcel(); 975 Object o = mMap.get(key); 976 if (o == null) { 977 return null; 978 } 979 try { 980 return (Bundle) o; 981 } catch (ClassCastException e) { 982 typeWarning(key, o, "Bundle", e); 983 return null; 984 } 985 } 986 987 /** 988 * Returns the value associated with the given key, or {@code null} if 989 * no mapping of the desired type exists for the given key or a {@code null} 990 * value is explicitly associated with the key. 991 * 992 * <p><b>Note: </b> if the expected value is not a class provided by the Android platform, 993 * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first. 994 * Otherwise, this method might throw an exception or return {@code null}. 995 * 996 * @param key a String, or {@code null} 997 * @return a Parcelable value, or {@code null} 998 */ 999 @Nullable getParcelable(@ullable String key)1000 public <T extends Parcelable> T getParcelable(@Nullable String key) { 1001 unparcel(); 1002 Object o = mMap.get(key); 1003 if (o == null) { 1004 return null; 1005 } 1006 try { 1007 return (T) o; 1008 } catch (ClassCastException e) { 1009 typeWarning(key, o, "Parcelable", e); 1010 return null; 1011 } 1012 } 1013 1014 /** 1015 * Returns the value associated with the given key, or {@code null} if 1016 * no mapping of the desired type exists for the given key or a null 1017 * value is explicitly associated with the key. 1018 * 1019 * <p><b>Note: </b> if the expected value is not a class provided by the Android platform, 1020 * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first. 1021 * Otherwise, this method might throw an exception or return {@code null}. 1022 * 1023 * @param key a String, or {@code null} 1024 * @return a Parcelable[] value, or {@code null} 1025 */ 1026 @Nullable getParcelableArray(@ullable String key)1027 public Parcelable[] getParcelableArray(@Nullable String key) { 1028 unparcel(); 1029 Object o = mMap.get(key); 1030 if (o == null) { 1031 return null; 1032 } 1033 try { 1034 return (Parcelable[]) o; 1035 } catch (ClassCastException e) { 1036 typeWarning(key, o, "Parcelable[]", e); 1037 return null; 1038 } 1039 } 1040 1041 /** 1042 * Returns the value associated with the given key, or {@code null} if 1043 * no mapping of the desired type exists for the given key or a {@code null} 1044 * value is explicitly associated with the key. 1045 * 1046 * <p><b>Note: </b> if the expected value is not a class provided by the Android platform, 1047 * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first. 1048 * Otherwise, this method might throw an exception or return {@code null}. 1049 * 1050 * @param key a String, or {@code null} 1051 * @return an ArrayList<T> value, or {@code null} 1052 */ 1053 @Nullable getParcelableArrayList(@ullable String key)1054 public <T extends Parcelable> ArrayList<T> getParcelableArrayList(@Nullable String key) { 1055 unparcel(); 1056 Object o = mMap.get(key); 1057 if (o == null) { 1058 return null; 1059 } 1060 try { 1061 return (ArrayList<T>) o; 1062 } catch (ClassCastException e) { 1063 typeWarning(key, o, "ArrayList", e); 1064 return null; 1065 } 1066 } 1067 1068 /** 1069 * Returns the value associated with the given key, or null if 1070 * no mapping of the desired type exists for the given key or a null 1071 * value is explicitly associated with the key. 1072 * 1073 * @param key a String, or null 1074 * 1075 * @return a SparseArray of T values, or null 1076 */ 1077 @Nullable getSparseParcelableArray(@ullable String key)1078 public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(@Nullable String key) { 1079 unparcel(); 1080 Object o = mMap.get(key); 1081 if (o == null) { 1082 return null; 1083 } 1084 try { 1085 return (SparseArray<T>) o; 1086 } catch (ClassCastException e) { 1087 typeWarning(key, o, "SparseArray", e); 1088 return null; 1089 } 1090 } 1091 1092 /** 1093 * Returns the value associated with the given key, or null if 1094 * no mapping of the desired type exists for the given key or a null 1095 * value is explicitly associated with the key. 1096 * 1097 * @param key a String, or null 1098 * @return a Serializable value, or null 1099 */ 1100 @Override 1101 @Nullable getSerializable(@ullable String key)1102 public Serializable getSerializable(@Nullable String key) { 1103 return super.getSerializable(key); 1104 } 1105 1106 /** 1107 * Returns the value associated with the given key, or null if 1108 * no mapping of the desired type exists for the given key or a null 1109 * value is explicitly associated with the key. 1110 * 1111 * @param key a String, or null 1112 * @return an ArrayList<String> value, or null 1113 */ 1114 @Override 1115 @Nullable getIntegerArrayList(@ullable String key)1116 public ArrayList<Integer> getIntegerArrayList(@Nullable String key) { 1117 return super.getIntegerArrayList(key); 1118 } 1119 1120 /** 1121 * Returns the value associated with the given key, or null if 1122 * no mapping of the desired type exists for the given key or a null 1123 * value is explicitly associated with the key. 1124 * 1125 * @param key a String, or null 1126 * @return an ArrayList<String> value, or null 1127 */ 1128 @Override 1129 @Nullable getStringArrayList(@ullable String key)1130 public ArrayList<String> getStringArrayList(@Nullable String key) { 1131 return super.getStringArrayList(key); 1132 } 1133 1134 /** 1135 * Returns the value associated with the given key, or null if 1136 * no mapping of the desired type exists for the given key or a null 1137 * value is explicitly associated with the key. 1138 * 1139 * @param key a String, or null 1140 * @return an ArrayList<CharSequence> value, or null 1141 */ 1142 @Override 1143 @Nullable getCharSequenceArrayList(@ullable String key)1144 public ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) { 1145 return super.getCharSequenceArrayList(key); 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 byte[] value, or null 1155 */ 1156 @Override 1157 @Nullable getByteArray(@ullable String key)1158 public byte[] getByteArray(@Nullable String key) { 1159 return super.getByteArray(key); 1160 } 1161 1162 /** 1163 * Returns the value associated with the given key, or null if 1164 * no mapping of the desired type exists for the given key or a null 1165 * value is explicitly associated with the key. 1166 * 1167 * @param key a String, or null 1168 * @return a short[] value, or null 1169 */ 1170 @Override 1171 @Nullable getShortArray(@ullable String key)1172 public short[] getShortArray(@Nullable String key) { 1173 return super.getShortArray(key); 1174 } 1175 1176 /** 1177 * Returns the value associated with the given key, or null if 1178 * no mapping of the desired type exists for the given key or a null 1179 * value is explicitly associated with the key. 1180 * 1181 * @param key a String, or null 1182 * @return a char[] value, or null 1183 */ 1184 @Override 1185 @Nullable getCharArray(@ullable String key)1186 public char[] getCharArray(@Nullable String key) { 1187 return super.getCharArray(key); 1188 } 1189 1190 /** 1191 * Returns the value associated with the given key, or null if 1192 * no mapping of the desired type exists for the given key or a null 1193 * value is explicitly associated with the key. 1194 * 1195 * @param key a String, or null 1196 * @return a float[] value, or null 1197 */ 1198 @Override 1199 @Nullable getFloatArray(@ullable String key)1200 public float[] getFloatArray(@Nullable String key) { 1201 return super.getFloatArray(key); 1202 } 1203 1204 /** 1205 * Returns the value associated with the given key, or null if 1206 * no mapping of the desired type exists for the given key or a null 1207 * value is explicitly associated with the key. 1208 * 1209 * @param key a String, or null 1210 * @return a CharSequence[] value, or null 1211 */ 1212 @Override 1213 @Nullable getCharSequenceArray(@ullable String key)1214 public CharSequence[] getCharSequenceArray(@Nullable String key) { 1215 return super.getCharSequenceArray(key); 1216 } 1217 1218 /** 1219 * Returns the value associated with the given key, or null if 1220 * no mapping of the desired type exists for the given key or a null 1221 * value is explicitly associated with the key. 1222 * 1223 * @param key a String, or null 1224 * @return an IBinder value, or null 1225 */ 1226 @Nullable getBinder(@ullable String key)1227 public IBinder getBinder(@Nullable String key) { 1228 unparcel(); 1229 Object o = mMap.get(key); 1230 if (o == null) { 1231 return null; 1232 } 1233 try { 1234 return (IBinder) o; 1235 } catch (ClassCastException e) { 1236 typeWarning(key, o, "IBinder", e); 1237 return null; 1238 } 1239 } 1240 1241 /** 1242 * Returns the value associated with the given key, or null if 1243 * no mapping of the desired type exists for the given key or a null 1244 * value is explicitly associated with the key. 1245 * 1246 * @param key a String, or null 1247 * @return an IBinder value, or null 1248 * 1249 * @deprecated 1250 * @hide This is the old name of the function. 1251 */ 1252 @UnsupportedAppUsage 1253 @Deprecated 1254 @Nullable getIBinder(@ullable String key)1255 public IBinder getIBinder(@Nullable String key) { 1256 unparcel(); 1257 Object o = mMap.get(key); 1258 if (o == null) { 1259 return null; 1260 } 1261 try { 1262 return (IBinder) o; 1263 } catch (ClassCastException e) { 1264 typeWarning(key, o, "IBinder", e); 1265 return null; 1266 } 1267 } 1268 1269 public static final @android.annotation.NonNull Parcelable.Creator<Bundle> CREATOR = 1270 new Parcelable.Creator<Bundle>() { 1271 @Override 1272 public Bundle createFromParcel(Parcel in) { 1273 return in.readBundle(); 1274 } 1275 1276 @Override 1277 public Bundle[] newArray(int size) { 1278 return new Bundle[size]; 1279 } 1280 }; 1281 1282 /** 1283 * Report the nature of this Parcelable's contents 1284 */ 1285 @Override describeContents()1286 public int describeContents() { 1287 int mask = 0; 1288 if (hasFileDescriptors()) { 1289 mask |= Parcelable.CONTENTS_FILE_DESCRIPTOR; 1290 } 1291 return mask; 1292 } 1293 1294 /** 1295 * Writes the Bundle contents to a Parcel, typically in order for 1296 * it to be passed through an IBinder connection. 1297 * @param parcel The parcel to copy this bundle to. 1298 */ 1299 @Override writeToParcel(Parcel parcel, int flags)1300 public void writeToParcel(Parcel parcel, int flags) { 1301 final boolean oldAllowFds = parcel.pushAllowFds((mFlags & FLAG_ALLOW_FDS) != 0); 1302 try { 1303 super.writeToParcelInner(parcel, flags); 1304 } finally { 1305 parcel.restoreAllowFds(oldAllowFds); 1306 } 1307 } 1308 1309 /** 1310 * Reads the Parcel contents into this Bundle, typically in order for 1311 * it to be passed through an IBinder connection. 1312 * @param parcel The parcel to overwrite this bundle from. 1313 */ readFromParcel(Parcel parcel)1314 public void readFromParcel(Parcel parcel) { 1315 super.readFromParcelInner(parcel); 1316 mFlags = FLAG_ALLOW_FDS; 1317 maybePrefillHasFds(); 1318 } 1319 1320 @Override toString()1321 public synchronized String toString() { 1322 if (mParcelledData != null) { 1323 if (isEmptyParcel()) { 1324 return "Bundle[EMPTY_PARCEL]"; 1325 } else { 1326 return "Bundle[mParcelledData.dataSize=" + 1327 mParcelledData.dataSize() + "]"; 1328 } 1329 } 1330 return "Bundle[" + mMap.toString() + "]"; 1331 } 1332 1333 /** 1334 * @hide 1335 */ toShortString()1336 public synchronized String toShortString() { 1337 if (mParcelledData != null) { 1338 if (isEmptyParcel()) { 1339 return "EMPTY_PARCEL"; 1340 } else { 1341 return "mParcelledData.dataSize=" + mParcelledData.dataSize(); 1342 } 1343 } 1344 return mMap.toString(); 1345 } 1346 1347 /** @hide */ dumpDebug(ProtoOutputStream proto, long fieldId)1348 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 1349 final long token = proto.start(fieldId); 1350 1351 if (mParcelledData != null) { 1352 if (isEmptyParcel()) { 1353 proto.write(BundleProto.PARCELLED_DATA_SIZE, 0); 1354 } else { 1355 proto.write(BundleProto.PARCELLED_DATA_SIZE, mParcelledData.dataSize()); 1356 } 1357 } else { 1358 proto.write(BundleProto.MAP_DATA, mMap.toString()); 1359 } 1360 1361 proto.end(token); 1362 } 1363 } 1364