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