Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c9504268 authored by Bernardo Rufino's avatar Bernardo Rufino Committed by Automerger Merge Worker
Browse files

Merge "Add safer Bundle APIs and deprecated old ones" am: c5589d2c am:...

Merge "Add safer Bundle APIs and deprecated old ones" am: c5589d2c am: ce09bba3 am: aed366dc am: 854cd54a

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1988908

Change-Id: I797488b82ad5471d90483a8fa657ce2bcdf846e9
parents f9514c51 854cd54a
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -30697,7 +30697,7 @@ package android.os {
  public class BaseBundle {
    method public void clear();
    method public boolean containsKey(String);
    method @Nullable public Object get(String);
    method @Deprecated @Nullable public Object get(String);
    method public boolean getBoolean(String);
    method public boolean getBoolean(String, boolean);
    method @Nullable public boolean[] getBooleanArray(@Nullable String);
@@ -30939,16 +30939,21 @@ package android.os {
    method public float getFloat(String, float);
    method @Nullable public float[] getFloatArray(@Nullable String);
    method @Nullable public java.util.ArrayList<java.lang.Integer> getIntegerArrayList(@Nullable String);
    method @Nullable public <T extends android.os.Parcelable> T getParcelable(@Nullable String);
    method @Nullable public android.os.Parcelable[] getParcelableArray(@Nullable String);
    method @Nullable public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayList(@Nullable String);
    method @Nullable public java.io.Serializable getSerializable(@Nullable String);
    method @Deprecated @Nullable public <T extends android.os.Parcelable> T getParcelable(@Nullable String);
    method @Nullable public <T> T getParcelable(@Nullable String, @NonNull Class<T>);
    method @Deprecated @Nullable public android.os.Parcelable[] getParcelableArray(@Nullable String);
    method @Nullable public <T> T[] getParcelableArray(@Nullable String, @NonNull Class<T>);
    method @Deprecated @Nullable public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayList(@Nullable String);
    method @Nullable public <T> java.util.ArrayList<T> getParcelableArrayList(@Nullable String, @NonNull Class<T>);
    method @Deprecated @Nullable public java.io.Serializable getSerializable(@Nullable String);
    method @Nullable public <T extends java.io.Serializable> T getSerializable(@Nullable String, @NonNull Class<T>);
    method public short getShort(String);
    method public short getShort(String, short);
    method @Nullable public short[] getShortArray(@Nullable String);
    method @Nullable public android.util.Size getSize(@Nullable String);
    method @Nullable public android.util.SizeF getSizeF(@Nullable String);
    method @Nullable public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(@Nullable String);
    method @Deprecated @Nullable public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(@Nullable String);
    method @Nullable public <T> android.util.SparseArray<T> getSparseParcelableArray(@Nullable String, @NonNull Class<T>);
    method @Nullable public java.util.ArrayList<java.lang.String> getStringArrayList(@Nullable String);
    method public boolean hasFileDescriptors();
    method public void putAll(android.os.Bundle);
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

/** Used by Parcel to signal that the type on the payload was not expected by the caller. */
class BadTypeParcelableException extends BadParcelableException {
    BadTypeParcelableException(String msg) {
        super(msg);
    }
    BadTypeParcelableException(Exception cause) {
        super(cause);
    }
    BadTypeParcelableException(String msg, Throwable cause) {
        super(msg, cause);
    }
}
+103 −44
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.os;

import static java.util.Objects.requireNonNull;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -31,7 +33,7 @@ import com.android.internal.util.IndentingPrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Set;
import java.util.function.Function;
import java.util.function.BiFunction;

/**
 * A mapping from String keys to values of various types. In most cases, you
@@ -254,8 +256,8 @@ public class BaseBundle {
        }
        try {
            return getValueAt(0, String.class);
        } catch (ClassCastException | BadParcelableException e) {
            typeWarning("getPairValue()", /* value */ null, "String", e);
        } catch (ClassCastException | BadTypeParcelableException e) {
            typeWarning("getPairValue()", "String", e);
            return null;
        }
    }
@@ -320,28 +322,46 @@ public class BaseBundle {
     * This call should always be made after {@link #unparcel()} or inside a lock after making sure
     * {@code mMap} is not null.
     *
     * @deprecated Use {@link #getValue(String, Class, Class[])}. This method should only be used in
     *      other deprecated APIs.
     *
     * @hide
     */
    @Deprecated
    @Nullable
    final Object getValue(String key) {
        return getValue(key, /* clazz */ null);
    }

    /** Same as {@link #getValue(String, Class, Class[])} with no item types. */
    @Nullable
    final <T> T getValue(String key, @Nullable Class<T> clazz) {
        // Avoids allocating Class[0] array
        return getValue(key, clazz, (Class<?>[]) null);
    }

    /**
     * Returns the value for key {@code key} for expected return type {@param clazz} (or {@code
     * Returns the value for key {@code key} for expected return type {@code clazz} (or pass {@code
     * null} for no type check).
     *
     * For {@code itemTypes}, see {@link Parcel#readValue(int, ClassLoader, Class, Class[])}.
     *
     * This call should always be made after {@link #unparcel()} or inside a lock after making sure
     * {@code mMap} is not null.
     *
     * @hide
     */
    final <T> T getValue(String key, @Nullable Class<T> clazz) {
    @Nullable
    final <T> T getValue(String key, @Nullable Class<T> clazz, @Nullable Class<?>... itemTypes) {
        int i = mMap.indexOfKey(key);
        return (i >= 0) ? getValueAt(i, clazz) : null;
        return (i >= 0) ? getValueAt(i, clazz, itemTypes) : null;
    }

    /**
     * Returns the value for a certain position in the array map.
     * Returns the value for a certain position in the array map for expected return type {@code
     * clazz} (or pass {@code null} for no type check).
     *
     * For {@code itemTypes}, see {@link Parcel#readValue(int, ClassLoader, Class, Class[])}.
     *
     * This call should always be made after {@link #unparcel()} or inside a lock after making sure
     * {@code mMap} is not null.
@@ -349,11 +369,12 @@ public class BaseBundle {
     * @hide
     */
    @SuppressWarnings("unchecked")
    final <T> T getValueAt(int i, @Nullable Class<T> clazz) {
    @Nullable
    final <T> T getValueAt(int i, @Nullable Class<T> clazz, @Nullable Class<?>... itemTypes) {
        Object object = mMap.valueAt(i);
        if (object instanceof Function<?, ?>) {
        if (object instanceof BiFunction<?, ?, ?>) {
            try {
                object = ((Function<Class<?>, ?>) object).apply(clazz);
                object = ((BiFunction<Class<?>, Class<?>[], ?>) object).apply(clazz, itemTypes);
            } catch (BadParcelableException e) {
                if (sShouldDefuse) {
                    Log.w(TAG, "Failed to parse item " + mMap.keyAt(i) + ", returning null.", e);
@@ -615,13 +636,43 @@ public class BaseBundle {
     *
     * @param key a String key
     * @return an Object, or null
     *
     * @deprecated Use the type-safe specific APIs depending on the type of the item to be
     *      retrieved, eg. {@link #getString(String)}.
     */
    @Deprecated
    @Nullable
    public Object get(String key) {
        unparcel();
        return getValue(key);
    }

    /**
     * Returns the object of type {@code clazz} for the given {@code key}, or {@code null} if:
     * <ul>
     *     <li>No mapping of the desired type exists for the given key.
     *     <li>A {@code null} value is explicitly associated with the key.
     *     <li>The object is not of type {@code clazz}.
     * </ul>
     *
     * <p>Use the more specific APIs where possible, especially in the case of containers such as
     * lists, since those APIs allow you to specify the type of the items.
     *
     * @param key String key
     * @param clazz The type of the object expected
     * @return an Object, or null
     */
    @Nullable
    <T> T get(@Nullable String key, @NonNull Class<T> clazz) {
        unparcel();
        try {
            return getValue(key, requireNonNull(clazz));
        } catch (ClassCastException | BadTypeParcelableException e) {
            typeWarning(key, clazz.getCanonicalName(), e);
            return null;
        }
    }

    /**
     * Removes any entry with the given key from the mapping of this Bundle.
     *
@@ -1019,6 +1070,10 @@ public class BaseBundle {
        typeWarning(key, value, className, "<null>", e);
    }

    void typeWarning(String key, String className, RuntimeException e) {
        typeWarning(key, /* value */ null, className, "<null>", e);
    }

    /**
     * Returns the value associated with the given key, or defaultValue if
     * no mapping of the desired type exists for the given key.
@@ -1358,7 +1413,11 @@ public class BaseBundle {
     *
     * @param key a String, or null
     * @return a Serializable value, or null
     *
     * @deprecated Use {@link #getSerializable(String, Class)}. This method should only be used in
     *      other deprecated APIs.
     */
    @Deprecated
    @Nullable
    Serializable getSerializable(@Nullable String key) {
        unparcel();
@@ -1374,6 +1433,36 @@ public class BaseBundle {
        }
    }

    /**
     * Returns the value associated with the given key, or {@code null} if:
     * <ul>
     *     <li>No mapping of the desired type exists for the given key.
     *     <li>A {@code null} value is explicitly associated with the key.
     *     <li>The object is not of type {@code clazz}.
     * </ul>
     *
     * @param key a String, or null
     * @param clazz The expected class of the returned type
     * @return a Serializable value, or null
     */
    @Nullable
    <T extends Serializable> T getSerializable(@Nullable String key, @NonNull Class<T> clazz) {
        return get(key, clazz);
    }


    @SuppressWarnings("unchecked")
    @Nullable
    <T> ArrayList<T> getArrayList(@Nullable String key, @NonNull Class<T> clazz) {
        unparcel();
        try {
            return getValue(key, ArrayList.class, requireNonNull(clazz));
        } catch (ClassCastException | BadTypeParcelableException e) {
            typeWarning(key, "ArrayList<" + clazz.getCanonicalName() + ">", e);
            return null;
        }
    }

    /**
     * Returns the value associated with the given key, or null if
     * no mapping of the desired type exists for the given key or a null
@@ -1384,17 +1473,7 @@ public class BaseBundle {
     */
    @Nullable
    ArrayList<Integer> getIntegerArrayList(@Nullable String key) {
        unparcel();
        Object o = getValue(key);
        if (o == null) {
            return null;
        }
        try {
            return (ArrayList<Integer>) o;
        } catch (ClassCastException e) {
            typeWarning(key, o, "ArrayList<Integer>", e);
            return null;
        }
        return getArrayList(key, Integer.class);
    }

    /**
@@ -1407,17 +1486,7 @@ public class BaseBundle {
     */
    @Nullable
    ArrayList<String> getStringArrayList(@Nullable String key) {
        unparcel();
        Object o = getValue(key);
        if (o == null) {
            return null;
        }
        try {
            return (ArrayList<String>) o;
        } catch (ClassCastException e) {
            typeWarning(key, o, "ArrayList<String>", e);
            return null;
        }
        return getArrayList(key, String.class);
    }

    /**
@@ -1430,17 +1499,7 @@ public class BaseBundle {
     */
    @Nullable
    ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) {
        unparcel();
        Object o = getValue(key);
        if (o == null) {
            return null;
        }
        try {
            return (ArrayList<CharSequence>) o;
        } catch (ClassCastException e) {
            typeWarning(key, o, "ArrayList<CharSequence>", e);
            return null;
        }
        return getArrayList(key, CharSequence.class);
    }

    /**
+137 −15
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static java.util.Objects.requireNonNull;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Size;
@@ -876,7 +877,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
    @Nullable
    public Bundle getBundle(@Nullable String key) {
        unparcel();
        Object o = getValue(key);
        Object o = mMap.get(key);
        if (o == null) {
            return null;
        }
@@ -899,7 +900,11 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
     *
     * @param key a String, or {@code null}
     * @return a Parcelable value, or {@code null}
     *
     * @deprecated Use the type-safer {@link #getParcelable(String, Class)} starting from Android
     *      {@link Build.VERSION_CODES#TIRAMISU}.
     */
    @Deprecated
    @Nullable
    public <T extends Parcelable> T getParcelable(@Nullable String key) {
        unparcel();
@@ -916,30 +921,28 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
    }

    /**
     * Returns the value associated with the given key, or {@code null} if
     * no mapping of the desired type exists for the given key or a {@code null}
     * value is explicitly associated with the key.
     * Returns the value associated with the given key or {@code null} if:
     * <ul>
     *     <li>No mapping of the desired type exists for the given key.
     *     <li>A {@code null} value is explicitly associated with the key.
     *     <li>The object is not of type {@code clazz}.
     * </ul>
     *
     * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
     * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
     * Otherwise, this method might throw an exception or return {@code null}.
     *
     * @param key a String, or {@code null}
     * @param clazz The type of the object expected or {@code null} for performing no checks.
     * @param clazz The type of the object expected
     * @return a Parcelable value, or {@code null}
     *
     * @hide
     */
    @SuppressWarnings("unchecked")
    @Nullable
    public <T> T getParcelable(@Nullable String key, @NonNull Class<T> clazz) {
        unparcel();
        try {
            return getValue(key, requireNonNull(clazz));
        } catch (ClassCastException | BadParcelableException e) {
            typeWarning(key, /* value */ null, "Parcelable", e);
            return null;
        }
        // The reason for not using <T extends Parcelable> is because the caller could provide a
        // super class to restrict the children that doesn't implement Parcelable itself while the
        // children do, more details at b/210800751 (same reasoning applies here).
        return get(key, clazz);
    }

    /**
@@ -953,7 +956,11 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
     *
     * @param key a String, or {@code null}
     * @return a Parcelable[] value, or {@code null}
     *
     * @deprecated Use the type-safer {@link #getParcelableArray(String, Class)} starting from
     *      Android {@link Build.VERSION_CODES#TIRAMISU}.
     */
    @Deprecated
    @Nullable
    public Parcelable[] getParcelableArray(@Nullable String key) {
        unparcel();
@@ -969,6 +976,39 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
        }
    }

    /**
     * Returns the value associated with the given key, or {@code null} if:
     * <ul>
     *     <li>No mapping of the desired type exists for the given key.
     *     <li>A {@code null} value is explicitly associated with the key.
     *     <li>The object is not of type {@code clazz}.
     * </ul>
     *
     * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
     * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
     * Otherwise, this method might throw an exception or return {@code null}.
     *
     * @param key a String, or {@code null}
     * @param clazz The type of the items inside the array
     * @return a Parcelable[] value, or {@code null}
     */
    @SuppressLint({"ArrayReturn", "NullableCollection"})
    @SuppressWarnings("unchecked")
    @Nullable
    public <T> T[] getParcelableArray(@Nullable String key, @NonNull Class<T> clazz) {
        // The reason for not using <T extends Parcelable> is because the caller could provide a
        // super class to restrict the children that doesn't implement Parcelable itself while the
        // children do, more details at b/210800751 (same reasoning applies here).
        unparcel();
        try {
            // In Java 12, we can pass clazz.arrayType() instead of Parcelable[] and later casting.
            return (T[]) getValue(key, Parcelable[].class, requireNonNull(clazz));
        } catch (ClassCastException | BadTypeParcelableException e) {
            typeWarning(key, clazz.getCanonicalName() + "[]", e);
            return null;
        }
    }

    /**
     * Returns the value associated with the given key, or {@code null} if
     * no mapping of the desired type exists for the given key or a {@code null}
@@ -980,7 +1020,11 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
     *
     * @param key a String, or {@code null}
     * @return an ArrayList<T> value, or {@code null}
     *
     * @deprecated Use the type-safer {@link #getParcelable(String, Class)} starting from Android
     *      {@link Build.VERSION_CODES#TIRAMISU}.
     */
    @Deprecated
    @Nullable
    public <T extends Parcelable> ArrayList<T> getParcelableArrayList(@Nullable String key) {
        unparcel();
@@ -996,15 +1040,44 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
        }
    }

    /**
     * Returns the value associated with the given key, or {@code null} if:
     * <ul>
     *     <li>No mapping of the desired type exists for the given key.
     *     <li>A {@code null} value is explicitly associated with the key.
     *     <li>The object is not of type {@code clazz}.
     * </ul>
     *
     * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
     * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
     * Otherwise, this method might throw an exception or return {@code null}.
     *
     * @param key   a String, or {@code null}
     * @param clazz The type of the items inside the array list
     * @return an ArrayList<T> value, or {@code null}
     */
    @SuppressLint("NullableCollection")
    @SuppressWarnings("unchecked")
    @Nullable
    public <T> ArrayList<T> getParcelableArrayList(@Nullable String key, @NonNull Class<T> clazz) {
        // The reason for not using <T extends Parcelable> is because the caller could provide a
        // super class to restrict the children that doesn't implement Parcelable itself while the
        // children do, more details at b/210800751 (same reasoning applies here).
        return getArrayList(key, clazz);
    }

    /**
     * Returns the value associated with the given key, or null if
     * no mapping of the desired type exists for the given key or a null
     * value is explicitly associated with the key.
     *
     * @param key a String, or null
     *
     * @return a SparseArray of T values, or null
     *
     * @deprecated Use the type-safer {@link #getSparseParcelableArray(String, Class)} starting from
     *      Android {@link Build.VERSION_CODES#TIRAMISU}.
     */
    @Deprecated
    @Nullable
    public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(@Nullable String key) {
        unparcel();
@@ -1020,6 +1093,33 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
        }
    }

    /**
     * Returns the value associated with the given key, or {@code null} if:
     * <ul>
     *     <li>No mapping of the desired type exists for the given key.
     *     <li>A {@code null} value is explicitly associated with the key.
     *     <li>The object is not of type {@code clazz}.
     * </ul>
     *
     * @param key a String, or null
     * @return a SparseArray of T values, or null
     */
    @SuppressWarnings("unchecked")
    @Nullable
    public <T> SparseArray<T> getSparseParcelableArray(@Nullable String key,
            @NonNull Class<T> clazz) {
        // The reason for not using <T extends Parcelable> is because the caller could provide a
        // super class to restrict the children that doesn't implement Parcelable itself while the
        // children do, more details at b/210800751 (same reasoning applies here).
        unparcel();
        try {
            return (SparseArray<T>) getValue(key, SparseArray.class, requireNonNull(clazz));
        } catch (ClassCastException | BadTypeParcelableException e) {
            typeWarning(key, "SparseArray<" + clazz.getCanonicalName() + ">", e);
            return null;
        }
    }

    /**
     * Returns the value associated with the given key, or null if
     * no mapping of the desired type exists for the given key or a null
@@ -1027,13 +1127,35 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
     *
     * @param key a String, or null
     * @return a Serializable value, or null
     *
     * @deprecated Use the type-safer {@link #getSerializable(String, Class)} starting from Android
     *      {@link Build.VERSION_CODES#TIRAMISU}.
     */
    @Deprecated
    @Override
    @Nullable
    public Serializable getSerializable(@Nullable String key) {
        return super.getSerializable(key);
    }

    /**
     * Returns the value associated with the given key, or {@code null} if:
     * <ul>
     *     <li>No mapping of the desired type exists for the given key.
     *     <li>A {@code null} value is explicitly associated with the key.
     *     <li>The object is not of type {@code clazz}.
     * </ul>
     *
     * @param key   a String, or null
     * @param clazz The expected class of the returned type
     * @return a Serializable value, or null
     */
    @Nullable
    public <T extends Serializable> T getSerializable(@Nullable String key,
            @NonNull Class<T> clazz) {
        return super.getSerializable(key, requireNonNull(clazz));
    }

    /**
     * Returns the value associated with the given key, or null if
     * no mapping of the desired type exists for the given key or a null
+134 −71

File changed.

Preview size limit exceeded, changes collapsed.

Loading