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 /** 439 * Inserts a byte value into the mapping of this Bundle, replacing 440 * any existing value for the given key. 441 * 442 * @param key a String, or null 443 * @param value a byte 444 */ 445 @Override putByte(@ullable String key, byte value)446 public void putByte(@Nullable String key, byte value) { 447 super.putByte(key, value); 448 } 449 450 /** 451 * Inserts a char value into the mapping of this Bundle, replacing 452 * any existing value for the given key. 453 * 454 * @param key a String, or null 455 * @param value a char 456 */ 457 @Override putChar(@ullable String key, char value)458 public void putChar(@Nullable String key, char value) { 459 super.putChar(key, value); 460 } 461 462 /** 463 * Inserts a short value into the mapping of this Bundle, replacing 464 * any existing value for the given key. 465 * 466 * @param key a String, or null 467 * @param value a short 468 */ 469 @Override putShort(@ullable String key, short value)470 public void putShort(@Nullable String key, short value) { 471 super.putShort(key, value); 472 } 473 474 /** 475 * Inserts a float value into the mapping of this Bundle, replacing 476 * any existing value for the given key. 477 * 478 * @param key a String, or null 479 * @param value a float 480 */ 481 @Override putFloat(@ullable String key, float value)482 public void putFloat(@Nullable String key, float value) { 483 super.putFloat(key, value); 484 } 485 486 /** 487 * Inserts a CharSequence value into the mapping of this Bundle, replacing 488 * any existing value for the given key. Either key or value may be null. 489 * 490 * @param key a String, or null 491 * @param value a CharSequence, or null 492 */ 493 @Override putCharSequence(@ullable String key, @Nullable CharSequence value)494 public void putCharSequence(@Nullable String key, @Nullable CharSequence value) { 495 super.putCharSequence(key, value); 496 } 497 498 /** 499 * Inserts a Parcelable value into the mapping of this Bundle, replacing 500 * any existing value for the given key. Either key or value may be null. 501 * 502 * @param key a String, or null 503 * @param value a Parcelable object, or null 504 */ putParcelable(@ullable String key, @Nullable Parcelable value)505 public void putParcelable(@Nullable String key, @Nullable Parcelable value) { 506 unparcel(); 507 mMap.put(key, value); 508 mFlags &= ~FLAG_HAS_FDS_KNOWN; 509 } 510 511 /** 512 * Inserts a Size value into the mapping of this Bundle, replacing 513 * any existing value for the given key. Either key or value may be null. 514 * 515 * @param key a String, or null 516 * @param value a Size object, or null 517 */ putSize(@ullable String key, @Nullable Size value)518 public void putSize(@Nullable String key, @Nullable Size value) { 519 unparcel(); 520 mMap.put(key, value); 521 } 522 523 /** 524 * Inserts a SizeF value into the mapping of this Bundle, replacing 525 * any existing value for the given key. Either key or value may be null. 526 * 527 * @param key a String, or null 528 * @param value a SizeF object, or null 529 */ putSizeF(@ullable String key, @Nullable SizeF value)530 public void putSizeF(@Nullable String key, @Nullable SizeF value) { 531 unparcel(); 532 mMap.put(key, value); 533 } 534 535 /** 536 * Inserts an array of Parcelable values into the mapping of this Bundle, 537 * replacing any existing value for the given key. Either key or value may 538 * be null. 539 * 540 * @param key a String, or null 541 * @param value an array of Parcelable objects, or null 542 */ putParcelableArray(@ullable String key, @Nullable Parcelable[] value)543 public void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) { 544 unparcel(); 545 mMap.put(key, value); 546 mFlags &= ~FLAG_HAS_FDS_KNOWN; 547 } 548 549 /** 550 * Inserts a List of Parcelable values into the mapping of this Bundle, 551 * replacing any existing value for the given key. Either key or value may 552 * be null. 553 * 554 * @param key a String, or null 555 * @param value an ArrayList of Parcelable objects, or null 556 */ putParcelableArrayList(@ullable String key, @Nullable ArrayList<? extends Parcelable> value)557 public void putParcelableArrayList(@Nullable String key, 558 @Nullable ArrayList<? extends Parcelable> value) { 559 unparcel(); 560 mMap.put(key, value); 561 mFlags &= ~FLAG_HAS_FDS_KNOWN; 562 } 563 564 /** {@hide} */ 565 @UnsupportedAppUsage putParcelableList(String key, List<? extends Parcelable> value)566 public void putParcelableList(String key, List<? extends Parcelable> value) { 567 unparcel(); 568 mMap.put(key, value); 569 mFlags &= ~FLAG_HAS_FDS_KNOWN; 570 } 571 572 /** 573 * Inserts a SparceArray of Parcelable values into the mapping of this 574 * Bundle, replacing any existing value for the given key. Either key 575 * or value may be null. 576 * 577 * @param key a String, or null 578 * @param value a SparseArray of Parcelable objects, or null 579 */ putSparseParcelableArray(@ullable String key, @Nullable SparseArray<? extends Parcelable> value)580 public void putSparseParcelableArray(@Nullable String key, 581 @Nullable SparseArray<? extends Parcelable> value) { 582 unparcel(); 583 mMap.put(key, value); 584 mFlags &= ~FLAG_HAS_FDS_KNOWN; 585 } 586 587 /** 588 * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing 589 * any existing value for the given key. Either key or value may be null. 590 * 591 * @param key a String, or null 592 * @param value an ArrayList<Integer> object, or null 593 */ 594 @Override putIntegerArrayList(@ullable String key, @Nullable ArrayList<Integer> value)595 public void putIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) { 596 super.putIntegerArrayList(key, value); 597 } 598 599 /** 600 * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing 601 * any existing value for the given key. Either key or value may be null. 602 * 603 * @param key a String, or null 604 * @param value an ArrayList<String> object, or null 605 */ 606 @Override putStringArrayList(@ullable String key, @Nullable ArrayList<String> value)607 public void putStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) { 608 super.putStringArrayList(key, value); 609 } 610 611 /** 612 * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing 613 * any existing value for the given key. Either key or value may be null. 614 * 615 * @param key a String, or null 616 * @param value an ArrayList<CharSequence> object, or null 617 */ 618 @Override putCharSequenceArrayList(@ullable String key, @Nullable ArrayList<CharSequence> value)619 public void putCharSequenceArrayList(@Nullable String key, 620 @Nullable ArrayList<CharSequence> value) { 621 super.putCharSequenceArrayList(key, value); 622 } 623 624 /** 625 * Inserts a Serializable value into the mapping of this Bundle, replacing 626 * any existing value for the given key. Either key or value may be null. 627 * 628 * @param key a String, or null 629 * @param value a Serializable object, or null 630 */ 631 @Override putSerializable(@ullable String key, @Nullable Serializable value)632 public void putSerializable(@Nullable String key, @Nullable Serializable value) { 633 super.putSerializable(key, value); 634 } 635 636 /** 637 * Inserts a byte array value into the mapping of this Bundle, replacing 638 * any existing value for the given key. Either key or value may be null. 639 * 640 * @param key a String, or null 641 * @param value a byte array object, or null 642 */ 643 @Override putByteArray(@ullable String key, @Nullable byte[] value)644 public void putByteArray(@Nullable String key, @Nullable byte[] value) { 645 super.putByteArray(key, value); 646 } 647 648 /** 649 * Inserts a short array value into the mapping of this Bundle, replacing 650 * any existing value for the given key. Either key or value may be null. 651 * 652 * @param key a String, or null 653 * @param value a short array object, or null 654 */ 655 @Override putShortArray(@ullable String key, @Nullable short[] value)656 public void putShortArray(@Nullable String key, @Nullable short[] value) { 657 super.putShortArray(key, value); 658 } 659 660 /** 661 * Inserts a char 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 char array object, or null 666 */ 667 @Override putCharArray(@ullable String key, @Nullable char[] value)668 public void putCharArray(@Nullable String key, @Nullable char[] value) { 669 super.putCharArray(key, value); 670 } 671 672 /** 673 * Inserts a float 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 float array object, or null 678 */ 679 @Override putFloatArray(@ullable String key, @Nullable float[] value)680 public void putFloatArray(@Nullable String key, @Nullable float[] value) { 681 super.putFloatArray(key, value); 682 } 683 684 /** 685 * Inserts a CharSequence 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 CharSequence array object, or null 690 */ 691 @Override putCharSequenceArray(@ullable String key, @Nullable CharSequence[] value)692 public void putCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) { 693 super.putCharSequenceArray(key, value); 694 } 695 696 /** 697 * Inserts a Bundle 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 Bundle object, or null 702 */ putBundle(@ullable String key, @Nullable Bundle value)703 public void putBundle(@Nullable String key, @Nullable Bundle value) { 704 unparcel(); 705 mMap.put(key, value); 706 } 707 708 /** 709 * Inserts an {@link IBinder} 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 * <p class="note">You should be very careful when using this function. In many 713 * places where Bundles are used (such as inside of Intent objects), the Bundle 714 * can live longer inside of another process than the process that had originally 715 * created it. In that case, the IBinder you supply here will become invalid 716 * when your process goes away, and no longer usable, even if a new process is 717 * created for you later on.</p> 718 * 719 * @param key a String, or null 720 * @param value an IBinder object, or null 721 */ putBinder(@ullable String key, @Nullable IBinder value)722 public void putBinder(@Nullable String key, @Nullable IBinder value) { 723 unparcel(); 724 mMap.put(key, value); 725 } 726 727 /** 728 * Inserts an IBinder value into the mapping of this Bundle, replacing 729 * any existing value for the given key. Either key or value may be null. 730 * 731 * @param key a String, or null 732 * @param value an IBinder object, or null 733 * 734 * @deprecated 735 * @hide This is the old name of the function. 736 */ 737 @UnsupportedAppUsage 738 @Deprecated putIBinder(@ullable String key, @Nullable IBinder value)739 public void putIBinder(@Nullable String key, @Nullable IBinder value) { 740 unparcel(); 741 mMap.put(key, value); 742 } 743 744 /** 745 * Returns the value associated with the given key, or (byte) 0 if 746 * no mapping of the desired type exists for the given key. 747 * 748 * @param key a String 749 * @return a byte value 750 */ 751 @Override getByte(String key)752 public byte getByte(String key) { 753 return super.getByte(key); 754 } 755 756 /** 757 * Returns the value associated with the given key, or defaultValue if 758 * no mapping of the desired type exists for the given key. 759 * 760 * @param key a String 761 * @param defaultValue Value to return if key does not exist 762 * @return a byte value 763 */ 764 @Override getByte(String key, byte defaultValue)765 public Byte getByte(String key, byte defaultValue) { 766 return super.getByte(key, defaultValue); 767 } 768 769 /** 770 * Returns the value associated with the given key, or (char) 0 if 771 * no mapping of the desired type exists for the given key. 772 * 773 * @param key a String 774 * @return a char value 775 */ 776 @Override getChar(String key)777 public char getChar(String key) { 778 return super.getChar(key); 779 } 780 781 /** 782 * Returns the value associated with the given key, or defaultValue if 783 * no mapping of the desired type exists for the given key. 784 * 785 * @param key a String 786 * @param defaultValue Value to return if key does not exist 787 * @return a char value 788 */ 789 @Override getChar(String key, char defaultValue)790 public char getChar(String key, char defaultValue) { 791 return super.getChar(key, defaultValue); 792 } 793 794 /** 795 * Returns the value associated with the given key, or (short) 0 if 796 * no mapping of the desired type exists for the given key. 797 * 798 * @param key a String 799 * @return a short value 800 */ 801 @Override getShort(String key)802 public short getShort(String key) { 803 return super.getShort(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 short value 813 */ 814 @Override getShort(String key, short defaultValue)815 public short getShort(String key, short defaultValue) { 816 return super.getShort(key, defaultValue); 817 } 818 819 /** 820 * Returns the value associated with the given key, or 0.0f if 821 * no mapping of the desired type exists for the given key. 822 * 823 * @param key a String 824 * @return a float value 825 */ 826 @Override getFloat(String key)827 public float getFloat(String key) { 828 return super.getFloat(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 float value 838 */ 839 @Override getFloat(String key, float defaultValue)840 public float getFloat(String key, float defaultValue) { 841 return super.getFloat(key, defaultValue); 842 } 843 844 /** 845 * Returns the value associated with the given key, or null if 846 * no mapping of the desired type exists for the given key or a null 847 * value is explicitly associated with the key. 848 * 849 * @param key a String, or null 850 * @return a CharSequence value, or null 851 */ 852 @Override 853 @Nullable getCharSequence(@ullable String key)854 public CharSequence getCharSequence(@Nullable String key) { 855 return super.getCharSequence(key); 856 } 857 858 /** 859 * Returns the value associated with the given key, or defaultValue if 860 * no mapping of the desired type exists for the given key or if a null 861 * value is explicitly associatd with the given key. 862 * 863 * @param key a String, or null 864 * @param defaultValue Value to return if key does not exist or if a null 865 * value is associated with the given key. 866 * @return the CharSequence value associated with the given key, or defaultValue 867 * if no valid CharSequence object is currently mapped to that key. 868 */ 869 @Override getCharSequence(@ullable String key, CharSequence defaultValue)870 public CharSequence getCharSequence(@Nullable String key, CharSequence defaultValue) { 871 return super.getCharSequence(key, defaultValue); 872 } 873 874 /** 875 * Returns the value associated with the given key, or null if 876 * no mapping of the desired type exists for the given key or a null 877 * value is explicitly associated with the key. 878 * 879 * @param key a String, or null 880 * @return a Size value, or null 881 */ 882 @Nullable getSize(@ullable String key)883 public Size getSize(@Nullable String key) { 884 unparcel(); 885 final Object o = mMap.get(key); 886 try { 887 return (Size) o; 888 } catch (ClassCastException e) { 889 typeWarning(key, o, "Size", e); 890 return null; 891 } 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 Size value, or null 901 */ 902 @Nullable getSizeF(@ullable String key)903 public SizeF getSizeF(@Nullable String key) { 904 unparcel(); 905 final Object o = mMap.get(key); 906 try { 907 return (SizeF) o; 908 } catch (ClassCastException e) { 909 typeWarning(key, o, "SizeF", e); 910 return null; 911 } 912 } 913 914 /** 915 * Returns the value associated with the given key, or null if 916 * no mapping of the desired type exists for the given key or a null 917 * value is explicitly associated with the key. 918 * 919 * @param key a String, or null 920 * @return a Bundle value, or null 921 */ 922 @Nullable getBundle(@ullable String key)923 public Bundle getBundle(@Nullable String key) { 924 unparcel(); 925 Object o = mMap.get(key); 926 if (o == null) { 927 return null; 928 } 929 try { 930 return (Bundle) o; 931 } catch (ClassCastException e) { 932 typeWarning(key, o, "Bundle", e); 933 return null; 934 } 935 } 936 937 /** 938 * Returns the value associated with the given key, or {@code null} if 939 * no mapping of the desired type exists for the given key or a {@code null} 940 * value is explicitly associated with the key. 941 * 942 * <p><b>Note: </b> if the expected value is not a class provided by the Android platform, 943 * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first. 944 * Otherwise, this method might throw an exception or return {@code null}. 945 * 946 * @param key a String, or {@code null} 947 * @return a Parcelable value, or {@code null} 948 */ 949 @Nullable getParcelable(@ullable String key)950 public <T extends Parcelable> T getParcelable(@Nullable String key) { 951 unparcel(); 952 Object o = mMap.get(key); 953 if (o == null) { 954 return null; 955 } 956 try { 957 return (T) o; 958 } catch (ClassCastException e) { 959 typeWarning(key, o, "Parcelable", e); 960 return null; 961 } 962 } 963 964 /** 965 * Returns the value associated with the given key, or {@code 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 * <p><b>Note: </b> if the expected value is not a class provided by the Android platform, 970 * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first. 971 * Otherwise, this method might throw an exception or return {@code null}. 972 * 973 * @param key a String, or {@code null} 974 * @return a Parcelable[] value, or {@code null} 975 */ 976 @Nullable getParcelableArray(@ullable String key)977 public Parcelable[] getParcelableArray(@Nullable String key) { 978 unparcel(); 979 Object o = mMap.get(key); 980 if (o == null) { 981 return null; 982 } 983 try { 984 return (Parcelable[]) o; 985 } catch (ClassCastException e) { 986 typeWarning(key, o, "Parcelable[]", e); 987 return null; 988 } 989 } 990 991 /** 992 * Returns the value associated with the given key, or {@code null} if 993 * no mapping of the desired type exists for the given key or a {@code null} 994 * value is explicitly associated with the key. 995 * 996 * <p><b>Note: </b> if the expected value is not a class provided by the Android platform, 997 * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first. 998 * Otherwise, this method might throw an exception or return {@code null}. 999 * 1000 * @param key a String, or {@code null} 1001 * @return an ArrayList<T> value, or {@code null} 1002 */ 1003 @Nullable getParcelableArrayList(@ullable String key)1004 public <T extends Parcelable> ArrayList<T> getParcelableArrayList(@Nullable String key) { 1005 unparcel(); 1006 Object o = mMap.get(key); 1007 if (o == null) { 1008 return null; 1009 } 1010 try { 1011 return (ArrayList<T>) o; 1012 } catch (ClassCastException e) { 1013 typeWarning(key, o, "ArrayList", e); 1014 return null; 1015 } 1016 } 1017 1018 /** 1019 * Returns the value associated with the given key, or null if 1020 * no mapping of the desired type exists for the given key or a null 1021 * value is explicitly associated with the key. 1022 * 1023 * @param key a String, or null 1024 * 1025 * @return a SparseArray of T values, or null 1026 */ 1027 @Nullable getSparseParcelableArray(@ullable String key)1028 public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(@Nullable String key) { 1029 unparcel(); 1030 Object o = mMap.get(key); 1031 if (o == null) { 1032 return null; 1033 } 1034 try { 1035 return (SparseArray<T>) o; 1036 } catch (ClassCastException e) { 1037 typeWarning(key, o, "SparseArray", e); 1038 return null; 1039 } 1040 } 1041 1042 /** 1043 * Returns the value associated with the given key, or null if 1044 * no mapping of the desired type exists for the given key or a null 1045 * value is explicitly associated with the key. 1046 * 1047 * @param key a String, or null 1048 * @return a Serializable value, or null 1049 */ 1050 @Override 1051 @Nullable getSerializable(@ullable String key)1052 public Serializable getSerializable(@Nullable String key) { 1053 return super.getSerializable(key); 1054 } 1055 1056 /** 1057 * Returns the value associated with the given key, or null if 1058 * no mapping of the desired type exists for the given key or a null 1059 * value is explicitly associated with the key. 1060 * 1061 * @param key a String, or null 1062 * @return an ArrayList<String> value, or null 1063 */ 1064 @Override 1065 @Nullable getIntegerArrayList(@ullable String key)1066 public ArrayList<Integer> getIntegerArrayList(@Nullable String key) { 1067 return super.getIntegerArrayList(key); 1068 } 1069 1070 /** 1071 * Returns the value associated with the given key, or null if 1072 * no mapping of the desired type exists for the given key or a null 1073 * value is explicitly associated with the key. 1074 * 1075 * @param key a String, or null 1076 * @return an ArrayList<String> value, or null 1077 */ 1078 @Override 1079 @Nullable getStringArrayList(@ullable String key)1080 public ArrayList<String> getStringArrayList(@Nullable String key) { 1081 return super.getStringArrayList(key); 1082 } 1083 1084 /** 1085 * Returns the value associated with the given key, or null if 1086 * no mapping of the desired type exists for the given key or a null 1087 * value is explicitly associated with the key. 1088 * 1089 * @param key a String, or null 1090 * @return an ArrayList<CharSequence> value, or null 1091 */ 1092 @Override 1093 @Nullable getCharSequenceArrayList(@ullable String key)1094 public ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) { 1095 return super.getCharSequenceArrayList(key); 1096 } 1097 1098 /** 1099 * Returns the value associated with the given key, or null if 1100 * no mapping of the desired type exists for the given key or a null 1101 * value is explicitly associated with the key. 1102 * 1103 * @param key a String, or null 1104 * @return a byte[] value, or null 1105 */ 1106 @Override 1107 @Nullable getByteArray(@ullable String key)1108 public byte[] getByteArray(@Nullable String key) { 1109 return super.getByteArray(key); 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 short[] value, or null 1119 */ 1120 @Override 1121 @Nullable getShortArray(@ullable String key)1122 public short[] getShortArray(@Nullable String key) { 1123 return super.getShortArray(key); 1124 } 1125 1126 /** 1127 * Returns the value associated with the given key, or null if 1128 * no mapping of the desired type exists for the given key or a null 1129 * value is explicitly associated with the key. 1130 * 1131 * @param key a String, or null 1132 * @return a char[] value, or null 1133 */ 1134 @Override 1135 @Nullable getCharArray(@ullable String key)1136 public char[] getCharArray(@Nullable String key) { 1137 return super.getCharArray(key); 1138 } 1139 1140 /** 1141 * Returns the value associated with the given key, or null if 1142 * no mapping of the desired type exists for the given key or a null 1143 * value is explicitly associated with the key. 1144 * 1145 * @param key a String, or null 1146 * @return a float[] value, or null 1147 */ 1148 @Override 1149 @Nullable getFloatArray(@ullable String key)1150 public float[] getFloatArray(@Nullable String key) { 1151 return super.getFloatArray(key); 1152 } 1153 1154 /** 1155 * Returns the value associated with the given key, or null if 1156 * no mapping of the desired type exists for the given key or a null 1157 * value is explicitly associated with the key. 1158 * 1159 * @param key a String, or null 1160 * @return a CharSequence[] value, or null 1161 */ 1162 @Override 1163 @Nullable getCharSequenceArray(@ullable String key)1164 public CharSequence[] getCharSequenceArray(@Nullable String key) { 1165 return super.getCharSequenceArray(key); 1166 } 1167 1168 /** 1169 * Returns the value associated with the given key, or null if 1170 * no mapping of the desired type exists for the given key or a null 1171 * value is explicitly associated with the key. 1172 * 1173 * @param key a String, or null 1174 * @return an IBinder value, or null 1175 */ 1176 @Nullable getBinder(@ullable String key)1177 public IBinder getBinder(@Nullable String key) { 1178 unparcel(); 1179 Object o = mMap.get(key); 1180 if (o == null) { 1181 return null; 1182 } 1183 try { 1184 return (IBinder) o; 1185 } catch (ClassCastException e) { 1186 typeWarning(key, o, "IBinder", e); 1187 return null; 1188 } 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 an IBinder value, or null 1198 * 1199 * @deprecated 1200 * @hide This is the old name of the function. 1201 */ 1202 @UnsupportedAppUsage 1203 @Deprecated 1204 @Nullable getIBinder(@ullable String key)1205 public IBinder getIBinder(@Nullable String key) { 1206 unparcel(); 1207 Object o = mMap.get(key); 1208 if (o == null) { 1209 return null; 1210 } 1211 try { 1212 return (IBinder) o; 1213 } catch (ClassCastException e) { 1214 typeWarning(key, o, "IBinder", e); 1215 return null; 1216 } 1217 } 1218 1219 public static final @android.annotation.NonNull Parcelable.Creator<Bundle> CREATOR = 1220 new Parcelable.Creator<Bundle>() { 1221 @Override 1222 public Bundle createFromParcel(Parcel in) { 1223 return in.readBundle(); 1224 } 1225 1226 @Override 1227 public Bundle[] newArray(int size) { 1228 return new Bundle[size]; 1229 } 1230 }; 1231 1232 /** 1233 * Report the nature of this Parcelable's contents 1234 */ 1235 @Override describeContents()1236 public int describeContents() { 1237 int mask = 0; 1238 if (hasFileDescriptors()) { 1239 mask |= Parcelable.CONTENTS_FILE_DESCRIPTOR; 1240 } 1241 return mask; 1242 } 1243 1244 /** 1245 * Writes the Bundle contents to a Parcel, typically in order for 1246 * it to be passed through an IBinder connection. 1247 * @param parcel The parcel to copy this bundle to. 1248 */ 1249 @Override writeToParcel(Parcel parcel, int flags)1250 public void writeToParcel(Parcel parcel, int flags) { 1251 final boolean oldAllowFds = parcel.pushAllowFds((mFlags & FLAG_ALLOW_FDS) != 0); 1252 try { 1253 super.writeToParcelInner(parcel, flags); 1254 } finally { 1255 parcel.restoreAllowFds(oldAllowFds); 1256 } 1257 } 1258 1259 /** 1260 * Reads the Parcel contents into this Bundle, typically in order for 1261 * it to be passed through an IBinder connection. 1262 * @param parcel The parcel to overwrite this bundle from. 1263 */ readFromParcel(Parcel parcel)1264 public void readFromParcel(Parcel parcel) { 1265 super.readFromParcelInner(parcel); 1266 mFlags = FLAG_ALLOW_FDS; 1267 maybePrefillHasFds(); 1268 } 1269 1270 @Override toString()1271 public synchronized String toString() { 1272 if (mParcelledData != null) { 1273 if (isEmptyParcel()) { 1274 return "Bundle[EMPTY_PARCEL]"; 1275 } else { 1276 return "Bundle[mParcelledData.dataSize=" + 1277 mParcelledData.dataSize() + "]"; 1278 } 1279 } 1280 return "Bundle[" + mMap.toString() + "]"; 1281 } 1282 1283 /** 1284 * @hide 1285 */ toShortString()1286 public synchronized String toShortString() { 1287 if (mParcelledData != null) { 1288 if (isEmptyParcel()) { 1289 return "EMPTY_PARCEL"; 1290 } else { 1291 return "mParcelledData.dataSize=" + mParcelledData.dataSize(); 1292 } 1293 } 1294 return mMap.toString(); 1295 } 1296 1297 /** @hide */ writeToProto(ProtoOutputStream proto, long fieldId)1298 public void writeToProto(ProtoOutputStream proto, long fieldId) { 1299 final long token = proto.start(fieldId); 1300 1301 if (mParcelledData != null) { 1302 if (isEmptyParcel()) { 1303 proto.write(BundleProto.PARCELLED_DATA_SIZE, 0); 1304 } else { 1305 proto.write(BundleProto.PARCELLED_DATA_SIZE, mParcelledData.dataSize()); 1306 } 1307 } else { 1308 proto.write(BundleProto.MAP_DATA, mMap.toString()); 1309 } 1310 1311 proto.end(token); 1312 } 1313 } 1314