Home | History | Annotate | Download | only in os
      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.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      */
     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
     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
     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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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
    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
    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
    199     public ClassLoader getClassLoader() {
    200         return super.getClassLoader();
    201     }
    202 
    203     /** {@hide} */
    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      */
    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
    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
    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      */
    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
    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      */
    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      */
    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
    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      */
    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
    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
    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
    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
    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
    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
    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      */
    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      */
    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      */
    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      */
    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      */
    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
    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      */
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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      */
    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      */
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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      */
   1264     public void readFromParcel(Parcel parcel) {
   1265         super.readFromParcelInner(parcel);
   1266         mFlags = FLAG_ALLOW_FDS;
   1267         maybePrefillHasFds();
   1268     }
   1269 
   1270     @Override
   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      */
   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 */
   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