diff options
20 files changed, 589 insertions, 172 deletions
diff --git a/Android.bp b/Android.bp index 52e011f92098..b69fa631de82 100644 --- a/Android.bp +++ b/Android.bp @@ -449,21 +449,28 @@ java_library { } // TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp -metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " + - "--hide-package com.android.server " + - "--hide-package android.audio.policy.configuration.V7_0 " + - "--error UnhiddenSystemApi " + - "--hide RequiresPermission " + - "--hide CallbackInterface " + - "--hide MissingPermission --hide BroadcastBehavior " + - "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " + - "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " + - "--error NoSettingsProvider " + - "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " + +metalava_framework_docs_args = "" + "--api-lint-ignore-prefix android.icu. " + "--api-lint-ignore-prefix java. " + "--api-lint-ignore-prefix junit. " + - "--api-lint-ignore-prefix org. " + "--api-lint-ignore-prefix org. " + + "--error NoSettingsProvider " + + "--error UnhiddenSystemApi " + + "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " + + "--hide BroadcastBehavior " + + "--hide CallbackInterface " + + "--hide DeprecationMismatch " + + "--hide HiddenSuperclass " + + "--hide HiddenTypeParameter " + + "--hide MissingPermission " + + "--hide-package android.audio.policy.configuration.V7_0 " + + "--hide-package com.android.server " + + "--hide RequiresPermission " + + "--hide SdkConstant " + + "--hide Todo " + + "--hide Typo " + + "--hide UnavailableSymbol " + + "--manifest $(location core/res/AndroidManifest.xml) " packages_to_document = [ "android", diff --git a/StubLibraries.bp b/StubLibraries.bp index 5cb0a785bc2b..39fd511a90ca 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -365,6 +365,64 @@ java_library { }, } +//////////////////////////////////////////////////////////////////////// +// api-versions.xml generation, for public and system. This API database +// also contains the android.test.* APIs. +//////////////////////////////////////////////////////////////////////// + +java_library { + name: "android_stubs_current_with_test_libs", + static_libs: [ + "android_stubs_current", + "android.test.base.stubs", + "android.test.mock.stubs", + "android.test.runner.stubs", + ], + defaults: ["android.jar_defaults"], + visibility: [ + "//visibility:override", + "//visibility:private", + ], +} + +java_library { + name: "android_system_stubs_current_with_test_libs", + static_libs: [ + "android_system_stubs_current", + "android.test.base.stubs.system", + "android.test.mock.stubs.system", + "android.test.runner.stubs.system", + ], + defaults: ["android.jar_defaults"], + visibility: [ + "//visibility:override", + "//visibility:private", + ], +} + +droidstubs { + name: "api_versions_public", + srcs: [":android_stubs_current_with_test_libs{.jar}"], + generate_stubs: false, + api_levels_annotations_enabled: true, + api_levels_annotations_dirs: [ + "sdk-dir", + "api-versions-jars-dir", + ], +} + +droidstubs { + name: "api_versions_system", + srcs: [":android_system_stubs_current_with_test_libs{.jar}"], + generate_stubs: false, + api_levels_annotations_enabled: true, + api_levels_annotations_dirs: [ + "sdk-dir", + "api-versions-jars-dir", + ], + api_levels_sdk_type: "system", +} + ///////////////////////////////////////////////////////////////////// // hwbinder.stubs provides APIs required for building HIDL Java // libraries. diff --git a/core/api/current.txt b/core/api/current.txt index 3a8076c932b7..b5066d9a8cb0 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -26189,7 +26189,6 @@ package android.nfc.cardemulation { field public static final String CATEGORY_PAYMENT = "payment"; field public static final String EXTRA_CATEGORY = "category"; field public static final String EXTRA_SERVICE_COMPONENT = "component"; - field public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID"; field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1 field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2 field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0 @@ -29424,7 +29423,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); @@ -29665,16 +29664,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); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 2c7f456c5e76..5c6076be4dc9 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -10131,8 +10131,6 @@ package android.service.tracing { public class TraceReportService extends android.app.Service { ctor public TraceReportService(); - method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent); - method public boolean onMessage(@NonNull android.os.Message); method public void onReportTrace(@NonNull android.service.tracing.TraceReportService.TraceParams); } diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java index 0a9fe90f2524..9a780c8a2935 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -84,13 +84,6 @@ public final class CardEmulation { public static final String EXTRA_SERVICE_COMPONENT = "component"; /** - * The caller userId extra for {@link #ACTION_CHANGE_DEFAULT}. - * - * @see #ACTION_CHANGE_DEFAULT - */ - public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID"; - - /** * Category used for NFC payment services. */ public static final String CATEGORY_PAYMENT = "payment"; diff --git a/core/java/android/os/BadTypeParcelableException.java b/core/java/android/os/BadTypeParcelableException.java new file mode 100644 index 000000000000..2ca3bd2adca1 --- /dev/null +++ b/core/java/android/os/BadTypeParcelableException.java @@ -0,0 +1,30 @@ +/* + * 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); + } +} diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java index ad3de25fecc2..45812e551618 100644 --- a/core/java/android/os/BaseBundle.java +++ b/core/java/android/os/BaseBundle.java @@ -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.Supplier; +import java.util.function.BiFunction; /** * A mapping from String keys to values of various types. In most cases, you @@ -252,11 +254,10 @@ public class BaseBundle { if (size == 0) { return null; } - Object o = getValueAt(0); try { - return (String) o; - } catch (ClassCastException e) { - typeWarning("getPairValue()", o, "String", e); + return getValueAt(0, String.class); + } catch (ClassCastException | BadTypeParcelableException e) { + typeWarning("getPairValue()", "String", e); return null; } } @@ -309,7 +310,7 @@ public class BaseBundle { } for (int i = 0, n = mMap.size(); i < n; i++) { // Triggers deserialization of i-th item, if needed - getValueAt(i); + getValueAt(i, /* clazz */ null); } } } @@ -321,26 +322,59 @@ 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 {@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 + */ + @Nullable + final <T> T getValue(String key, @Nullable Class<T> clazz, @Nullable Class<?>... itemTypes) { int i = mMap.indexOfKey(key); - return (i >= 0) ? getValueAt(i) : 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. * * @hide */ - final Object getValueAt(int i) { + @SuppressWarnings("unchecked") + @Nullable + final <T> T getValueAt(int i, @Nullable Class<T> clazz, @Nullable Class<?>... itemTypes) { Object object = mMap.valueAt(i); - if (object instanceof Supplier<?>) { + if (object instanceof BiFunction<?, ?, ?>) { try { - object = ((Supplier<?>) object).get(); + 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); @@ -351,7 +385,7 @@ public class BaseBundle { } mMap.setValueAt(i, object); } - return object; + return (clazz != null) ? clazz.cast(object) : (T) object; } private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean recycleParcel, @@ -528,7 +562,7 @@ public class BaseBundle { } else { // Following semantic above of failing in case we get a serialized value vs a // deserialized one, we'll compare the map. If a certain element hasn't been - // deserialized yet, it's a Supplier (or more specifically a LazyValue, but let's + // deserialized yet, it's a function object (or more specifically a LazyValue, but let's // pretend we don't know that here :P), we'll use that element's equality comparison as // map naturally does. That will takes care of comparing the payload if needed (see // Parcel.readLazyValue() for details). @@ -602,7 +636,11 @@ 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(); @@ -610,6 +648,32 @@ public class BaseBundle { } /** + * 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. * * @param key a String key @@ -982,15 +1046,19 @@ public class BaseBundle { } // Log a message if the value was non-null but not of the expected type - void typeWarning(String key, Object value, String className, - Object defaultValue, ClassCastException e) { + void typeWarning(String key, @Nullable Object value, String className, + Object defaultValue, RuntimeException e) { StringBuilder sb = new StringBuilder(); sb.append("Key "); sb.append(key); sb.append(" expected "); sb.append(className); - sb.append(" but value was a "); - sb.append(value.getClass().getName()); + if (value != null) { + sb.append(" but value was a "); + sb.append(value.getClass().getName()); + } else { + sb.append(" but value was of a different type"); + } sb.append(". The default value "); sb.append(defaultValue); sb.append(" was returned."); @@ -998,11 +1066,14 @@ public class BaseBundle { Log.w(TAG, "Attempt to cast generated internal exception:", e); } - void typeWarning(String key, Object value, String className, - ClassCastException e) { + void typeWarning(String key, @Nullable Object value, String className, RuntimeException e) { 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. @@ -1342,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(); @@ -1359,6 +1434,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 * value is explicitly associated with the key. @@ -1368,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); } /** @@ -1391,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); } /** @@ -1414,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); } /** diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index b2bbfd6c163d..edbbb59ac77d 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -16,7 +16,11 @@ package android.os; +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; @@ -873,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; } @@ -896,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(); @@ -913,6 +921,31 @@ 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 object expected + * @return a Parcelable value, or {@code null} + */ + @SuppressWarnings("unchecked") + @Nullable + public <T> T getParcelable(@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 get(key, clazz); + } + + /** * 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 null * value is explicitly associated with the key. @@ -923,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(); @@ -940,6 +977,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} * value is explicitly associated with the key. @@ -950,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(); @@ -967,14 +1041,43 @@ 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(); @@ -991,13 +1094,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> + * + * @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 * value is explicitly associated with the key. * * @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) { @@ -1005,6 +1139,24 @@ 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 + * @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 * value is explicitly associated with the key. diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 13d1d96fadc8..d3b35a032aff 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -16,6 +16,8 @@ package android.os; +import static com.android.internal.util.Preconditions.checkArgument; + import static java.util.Objects.requireNonNull; import android.annotation.IntDef; @@ -65,6 +67,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.Supplier; @@ -287,26 +290,26 @@ public final class Parcel { private static final int VAL_NULL = -1; private static final int VAL_STRING = 0; private static final int VAL_INTEGER = 1; - private static final int VAL_MAP = 2; + private static final int VAL_MAP = 2; // length-prefixed private static final int VAL_BUNDLE = 3; - private static final int VAL_PARCELABLE = 4; + private static final int VAL_PARCELABLE = 4; // length-prefixed private static final int VAL_SHORT = 5; private static final int VAL_LONG = 6; private static final int VAL_FLOAT = 7; private static final int VAL_DOUBLE = 8; private static final int VAL_BOOLEAN = 9; private static final int VAL_CHARSEQUENCE = 10; - private static final int VAL_LIST = 11; - private static final int VAL_SPARSEARRAY = 12; + private static final int VAL_LIST = 11; // length-prefixed + private static final int VAL_SPARSEARRAY = 12; // length-prefixed private static final int VAL_BYTEARRAY = 13; private static final int VAL_STRINGARRAY = 14; private static final int VAL_IBINDER = 15; - private static final int VAL_PARCELABLEARRAY = 16; - private static final int VAL_OBJECTARRAY = 17; + private static final int VAL_PARCELABLEARRAY = 16; // length-prefixed + private static final int VAL_OBJECTARRAY = 17; // length-prefixed private static final int VAL_INTARRAY = 18; private static final int VAL_LONGARRAY = 19; private static final int VAL_BYTE = 20; - private static final int VAL_SERIALIZABLE = 21; + private static final int VAL_SERIALIZABLE = 21; // length-prefixed private static final int VAL_SPARSEBOOLEANARRAY = 22; private static final int VAL_BOOLEANARRAY = 23; private static final int VAL_CHARSEQUENCEARRAY = 24; @@ -3170,8 +3173,7 @@ public final class Parcel { */ @Deprecated public final void readMap(@NonNull Map outVal, @Nullable ClassLoader loader) { - int n = readInt(); - readMapInternal(outVal, n, loader, /* clazzKey */ null, /* clazzValue */ null); + readMapInternal(outVal, loader, /* clazzKey */ null, /* clazzValue */ null); } /** @@ -3186,8 +3188,7 @@ public final class Parcel { @NonNull Class<V> clazzValue) { Objects.requireNonNull(clazzKey); Objects.requireNonNull(clazzValue); - int n = readInt(); - readMapInternal(outVal, n, loader, clazzKey, clazzValue); + readMapInternal(outVal, loader, clazzKey, clazzValue); } /** @@ -3236,13 +3237,7 @@ public final class Parcel { @Deprecated @Nullable public HashMap readHashMap(@Nullable ClassLoader loader) { - int n = readInt(); - if (n < 0) { - return null; - } - HashMap m = new HashMap(n); - readMapInternal(m, n, loader, /* clazzKey */ null, /* clazzValue */ null); - return m; + return readHashMapInternal(loader, /* clazzKey */ null, /* clazzValue */ null); } /** @@ -3258,13 +3253,7 @@ public final class Parcel { @NonNull Class<? extends K> clazzKey, @NonNull Class<? extends V> clazzValue) { Objects.requireNonNull(clazzKey); Objects.requireNonNull(clazzValue); - int n = readInt(); - if (n < 0) { - return null; - } - HashMap<K, V> map = new HashMap<>(n); - readMapInternal(map, n, loader, clazzKey, clazzValue); - return map; + return readHashMapInternal(loader, clazzKey, clazzValue); } /** @@ -4289,16 +4278,17 @@ public final class Parcel { /** - * @param clazz The type of the object expected or {@code null} for performing no checks. + * @see #readValue(int, ClassLoader, Class, Class[]) */ @Nullable - private <T> T readValue(@Nullable ClassLoader loader, @Nullable Class<T> clazz) { + private <T> T readValue(@Nullable ClassLoader loader, @Nullable Class<T> clazz, + @Nullable Class<?>... itemTypes) { int type = readInt(); final T object; if (isLengthPrefixed(type)) { int length = readInt(); int start = dataPosition(); - object = readValue(type, loader, clazz); + object = readValue(type, loader, clazz, itemTypes); int actual = dataPosition() - start; if (actual != length) { Slog.wtfStack(TAG, @@ -4306,24 +4296,26 @@ public final class Parcel { + " consumed " + actual + " bytes, but " + length + " expected."); } } else { - object = readValue(type, loader, clazz); + object = readValue(type, loader, clazz, itemTypes); } return object; } /** - * This will return a {@link Supplier} for length-prefixed types that deserializes the object - * when {@link Supplier#get()} is called, for other types it will return the object itself. + * This will return a {@link BiFunction} for length-prefixed types that deserializes the object + * when {@link BiFunction#apply} is called (the arguments correspond to the ones of {@link + * #readValue(int, ClassLoader, Class, Class[])} after the class loader), for other types it + * will return the object itself. * - * <p>After calling {@link Supplier#get()} the parcel cursor will not change. Note that you + * <p>After calling {@link BiFunction#apply} the parcel cursor will not change. Note that you * shouldn't recycle the parcel, not at least until all objects have been retrieved. No * synchronization attempts are made. * - * </p>The supplier returned implements {@link #equals(Object)} and {@link #hashCode()}. Two - * suppliers are equal if either of the following is true: + * </p>The function returned implements {@link #equals(Object)} and {@link #hashCode()}. Two + * function objects are equal if either of the following is true: * <ul> - * <li>{@link Supplier#get()} has been called on both and both objects returned are equal. - * <li>{@link Supplier#get()} hasn't been called on either one and everything below is true: + * <li>{@link BiFunction#apply} has been called on both and both objects returned are equal. + * <li>{@link BiFunction#apply} hasn't been called on either one and everything below is true: * <ul> * <li>The {@code loader} parameters used to retrieve each are equal. * <li>They both have the same type. @@ -4350,7 +4342,7 @@ public final class Parcel { } - private static final class LazyValue implements Supplier<Object> { + private static final class LazyValue implements BiFunction<Class<?>, Class<?>[], Object> { /** * | 4B | 4B | * mSource = Parcel{... | type | length | object | ...} @@ -4382,7 +4374,7 @@ public final class Parcel { } @Override - public Object get() { + public Object apply(@Nullable Class<?> clazz, @Nullable Class<?>[] itemTypes) { Parcel source = mSource; if (source != null) { synchronized (source) { @@ -4391,7 +4383,7 @@ public final class Parcel { int restore = source.dataPosition(); try { source.setDataPosition(mPosition); - mObject = source.readValue(mLoader); + mObject = source.readValue(mLoader, clazz, itemTypes); } finally { source.setDataPosition(restore); } @@ -4471,14 +4463,25 @@ public final class Parcel { } } + /** Same as {@link #readValue(ClassLoader, Class, Class[])} without any item types. */ + private <T> T readValue(int type, @Nullable ClassLoader loader, @Nullable Class<T> clazz) { + // Avoids allocating Class[0] array + return readValue(type, loader, clazz, (Class<?>[]) null); + } + /** * Reads a value from the parcel of type {@code type}. Does NOT read the int representing the * type first. + * * @param clazz The type of the object expected or {@code null} for performing no checks. + * @param itemTypes If the value is a container, these represent the item types (eg. for a list + * it's the item type, for a map, it's the key type, followed by the value + * type). */ @SuppressWarnings("unchecked") @Nullable - private <T> T readValue(int type, @Nullable ClassLoader loader, @Nullable Class<T> clazz) { + private <T> T readValue(int type, @Nullable ClassLoader loader, @Nullable Class<T> clazz, + @Nullable Class<?>... itemTypes) { final Object object; switch (type) { case VAL_NULL: @@ -4494,7 +4497,11 @@ public final class Parcel { break; case VAL_MAP: - object = readHashMap(loader); + checkTypeToUnparcel(clazz, HashMap.class); + Class<?> keyType = ArrayUtils.getOrNull(itemTypes, 0); + Class<?> valueType = ArrayUtils.getOrNull(itemTypes, 1); + checkArgument((keyType == null) == (valueType == null)); + object = readHashMapInternal(loader, keyType, valueType); break; case VAL_PARCELABLE: @@ -4525,10 +4532,12 @@ public final class Parcel { object = readCharSequence(); break; - case VAL_LIST: - object = readArrayList(loader); + case VAL_LIST: { + checkTypeToUnparcel(clazz, ArrayList.class); + Class<?> itemType = ArrayUtils.getOrNull(itemTypes, 0); + object = readArrayListInternal(loader, itemType); break; - + } case VAL_BOOLEANARRAY: object = createBooleanArray(); break; @@ -4549,10 +4558,12 @@ public final class Parcel { object = readStrongBinder(); break; - case VAL_OBJECTARRAY: - object = readArray(loader); + case VAL_OBJECTARRAY: { + Class<?> itemType = ArrayUtils.getOrNull(itemTypes, 0); + checkArrayTypeToUnparcel(clazz, (itemType != null) ? itemType : Object.class); + object = readArrayInternal(loader, itemType); break; - + } case VAL_INTARRAY: object = createIntArray(); break; @@ -4569,14 +4580,18 @@ public final class Parcel { object = readSerializableInternal(loader, clazz); break; - case VAL_PARCELABLEARRAY: - object = readParcelableArray(loader); + case VAL_PARCELABLEARRAY: { + Class<?> itemType = ArrayUtils.getOrNull(itemTypes, 0); + checkArrayTypeToUnparcel(clazz, (itemType != null) ? itemType : Parcelable.class); + object = readParcelableArrayInternal(loader, itemType); break; - - case VAL_SPARSEARRAY: - object = readSparseArray(loader); + } + case VAL_SPARSEARRAY: { + checkTypeToUnparcel(clazz, SparseArray.class); + Class<?> itemType = ArrayUtils.getOrNull(itemTypes, 0); + object = readSparseArrayInternal(loader, itemType); break; - + } case VAL_SPARSEBOOLEANARRAY: object = readSparseBooleanArray(); break; @@ -4624,7 +4639,7 @@ public final class Parcel { + " at offset " + off); } if (object != null && clazz != null && !clazz.isInstance(object)) { - throw new BadParcelableException("Unparcelled object " + object + throw new BadTypeParcelableException("Unparcelled object " + object + " is not an instance of required class " + clazz.getName() + " provided in the parameter"); } @@ -4651,6 +4666,38 @@ public final class Parcel { } /** + * Checks that an array of type T[], where T is {@code componentTypeToUnparcel}, is a subtype of + * {@code requiredArrayType}. + */ + private void checkArrayTypeToUnparcel(@Nullable Class<?> requiredArrayType, + Class<?> componentTypeToUnparcel) { + if (requiredArrayType != null) { + // In Java 12, we could use componentTypeToUnparcel.arrayType() for the check + Class<?> requiredComponentType = requiredArrayType.getComponentType(); + if (requiredComponentType == null) { + throw new BadTypeParcelableException( + "About to unparcel an array but type " + + requiredArrayType.getCanonicalName() + + " required by caller is not an array."); + } + checkTypeToUnparcel(requiredComponentType, componentTypeToUnparcel); + } + } + + /** + * Checks that {@code typeToUnparcel} is a subtype of {@code requiredType}, if {@code + * requiredType} is not {@code null}. + */ + private void checkTypeToUnparcel(@Nullable Class<?> requiredType, Class<?> typeToUnparcel) { + if (requiredType != null && !requiredType.isAssignableFrom(typeToUnparcel)) { + throw new BadTypeParcelableException( + "About to unparcel a " + typeToUnparcel.getCanonicalName() + + ", which is not a subtype of type " + requiredType.getCanonicalName() + + " required by caller."); + } + } + + /** * Read and return a new Parcelable from the parcel. The given class loader * will be used to load any enclosed Parcelables. If it is null, the default * class loader will be used. @@ -4780,7 +4827,7 @@ public final class Parcel { if (clazz != null) { Class<?> parcelableClass = creator.getClass().getEnclosingClass(); if (!clazz.isAssignableFrom(parcelableClass)) { - throw new BadParcelableException("Parcelable creator " + name + " is not " + throw new BadTypeParcelableException("Parcelable creator " + name + " is not " + "a subclass of required class " + clazz.getName() + " provided in the parameter"); } @@ -4803,7 +4850,7 @@ public final class Parcel { } if (clazz != null) { if (!clazz.isAssignableFrom(parcelableClass)) { - throw new BadParcelableException("Parcelable creator " + name + " is not " + throw new BadTypeParcelableException("Parcelable creator " + name + " is not " + "a subclass of required class " + clazz.getName() + " provided in the parameter"); } @@ -4864,15 +4911,7 @@ public final class Parcel { @Deprecated @Nullable public Parcelable[] readParcelableArray(@Nullable ClassLoader loader) { - int N = readInt(); - if (N < 0) { - return null; - } - Parcelable[] p = new Parcelable[N]; - for (int i = 0; i < N; i++) { - p[i] = readParcelable(loader); - } - return p; + return readParcelableArrayInternal(loader, /* clazz */ null); } /** @@ -4884,14 +4923,20 @@ public final class Parcel { * trying to instantiate an element. */ @SuppressLint({"ArrayReturn", "NullableCollection"}) - @SuppressWarnings("unchecked") @Nullable public <T> T[] readParcelableArray(@Nullable ClassLoader loader, @NonNull Class<T> clazz) { + return readParcelableArrayInternal(loader, requireNonNull(clazz)); + } + + @SuppressWarnings("unchecked") + @Nullable + private <T> T[] readParcelableArrayInternal(@Nullable ClassLoader loader, + @Nullable Class<T> clazz) { int n = readInt(); if (n < 0) { return null; } - T[] p = (T[]) Array.newInstance(clazz, n); + T[] p = (T[]) ((clazz == null) ? new Parcelable[n] : Array.newInstance(clazz, n)); for (int i = 0; i < n; i++) { p[i] = readParcelableInternal(loader, clazz); } @@ -4954,7 +4999,7 @@ public final class Parcel { // the class the same way as ObjectInputStream, using the provided classloader. Class<?> cl = Class.forName(name, false, loader); if (!clazz.isAssignableFrom(cl)) { - throw new BadParcelableException("Serializable object " + throw new BadTypeParcelableException("Serializable object " + cl.getName() + " is not a subclass of required class " + clazz.getName() + " provided in the parameter"); } @@ -4979,7 +5024,7 @@ public final class Parcel { // the deserialized object, as we cannot resolve the class the same way as // ObjectInputStream. if (!clazz.isAssignableFrom(object.getClass())) { - throw new BadParcelableException("Serializable object " + throw new BadTypeParcelableException("Serializable object " + object.getClass().getName() + " is not a subclass of required class " + clazz.getName() + " provided in the parameter"); } @@ -5089,7 +5134,26 @@ public final class Parcel { readMapInternal(outVal, n, loader, /* clazzKey */null, /* clazzValue */null); } - /* package */ <K, V> void readMapInternal(@NonNull Map<? super K, ? super V> outVal, int n, + @Nullable + private <K, V> HashMap<K, V> readHashMapInternal(@Nullable ClassLoader loader, + @NonNull Class<? extends K> clazzKey, @NonNull Class<? extends V> clazzValue) { + int n = readInt(); + if (n < 0) { + return null; + } + HashMap<K, V> map = new HashMap<>(n); + readMapInternal(map, n, loader, clazzKey, clazzValue); + return map; + } + + private <K, V> void readMapInternal(@NonNull Map<? super K, ? super V> outVal, + @Nullable ClassLoader loader, @Nullable Class<K> clazzKey, + @Nullable Class<V> clazzValue) { + int n = readInt(); + readMapInternal(outVal, n, loader, clazzKey, clazzValue); + } + + private <K, V> void readMapInternal(@NonNull Map<? super K, ? super V> outVal, int n, @Nullable ClassLoader loader, @Nullable Class<K> clazzKey, @Nullable Class<V> clazzValue) { while (n > 0) { @@ -5100,7 +5164,7 @@ public final class Parcel { } } - /* package */ void readArrayMapInternal(@NonNull ArrayMap<? super String, Object> outVal, + private void readArrayMapInternal(@NonNull ArrayMap<? super String, Object> outVal, int size, @Nullable ClassLoader loader) { readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader); } diff --git a/core/java/android/service/tracing/TraceReportService.java b/core/java/android/service/tracing/TraceReportService.java index 3d16a3d41ea3..6fdc8e8eb961 100644 --- a/core/java/android/service/tracing/TraceReportService.java +++ b/core/java/android/service/tracing/TraceReportService.java @@ -112,7 +112,6 @@ public class TraceReportService extends Service { } } - // Methods to override. /** * Called when a trace is reported and sent to this class. * @@ -123,15 +122,10 @@ public class TraceReportService extends Service { public void onReportTrace(@NonNull TraceParams args) { } - // Optional methods to override. - // Realistically, these methods are internal implementation details but since this class is - // a SystemApi, it's better to err on the side of flexibility just in-case we need to override - // these methods down the line. - /** * Handles binder calls from system_server. */ - public boolean onMessage(@NonNull Message msg) { + private boolean onMessage(@NonNull Message msg) { if (msg.what == MSG_REPORT_TRACE) { if (!(msg.obj instanceof TraceReportParams)) { Log.e(TAG, "Received invalid type for report trace message."); @@ -153,10 +147,12 @@ public class TraceReportService extends Service { /** * Returns an IBinder for handling binder calls from system_server. + * + * @hide */ @Nullable @Override - public IBinder onBind(@NonNull Intent intent) { + public final IBinder onBind(@NonNull Intent intent) { if (mMessenger == null) { mMessenger = new Messenger(new Handler(Looper.getMainLooper(), this::onMessage)); } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 00f4eb83bdaa..5b0bc4ad1aec 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -3128,7 +3128,8 @@ public interface WindowManager extends ViewManager { /** * The window is allowed to extend into the {@link DisplayCutout} area, only if the - * {@link DisplayCutout} is fully contained within a system bar. Otherwise, the window is + * {@link DisplayCutout} is fully contained within a system bar or the {@link DisplayCutout} + * is not deeper than 16 dp, but this depends on the OEM choice. Otherwise, the window is * laid out such that it does not overlap with the {@link DisplayCutout} area. * * <p> @@ -3143,6 +3144,13 @@ public interface WindowManager extends ViewManager { * The usual precautions for not overlapping with the status and navigation bar are * sufficient for ensuring that no important content overlaps with the DisplayCutout. * + * <p> + * Note: OEMs can have an option to allow the window to always extend into the + * {@link DisplayCutout} area, no matter the cutout flag set, when the {@link DisplayCutout} + * is on the different side from system bars, only if the {@link DisplayCutout} overlaps at + * most 16dp with the windows. + * In such case, OEMs must provide an opt-in/out affordance for users. + * * @see DisplayCutout * @see WindowInsets * @see #layoutInDisplayCutoutMode @@ -3155,8 +3163,16 @@ public interface WindowManager extends ViewManager { * The window is always allowed to extend into the {@link DisplayCutout} areas on the short * edges of the screen. * + * <p> * The window will never extend into a {@link DisplayCutout} area on the long edges of the - * screen. + * screen, unless the {@link DisplayCutout} is not deeper than 16 dp, but this depends on + * the OEM choice. + * + * <p> + * Note: OEMs can have an option to allow the window to extend into the + * {@link DisplayCutout} area on the long edge side, only if the cutout overlaps at most + * 16dp with the windows. In such case, OEMs must provide an opt-in/out affordance for + * users. * * <p> * The window must make sure that no important content overlaps with the diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 452dad3b79db..9791da5f41eb 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -12521,7 +12521,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * Called when a context menu option for the text view is selected. Currently * this will be one of {@link android.R.id#selectAll}, {@link android.R.id#cut}, - * {@link android.R.id#copy}, {@link android.R.id#paste} or {@link android.R.id#shareText}. + * {@link android.R.id#copy}, {@link android.R.id#paste}, + * {@link android.R.id#pasteAsPlainText} (starting at API level 23) or + * {@link android.R.id#shareText}. * * @return true if the context menu item action was performed. */ @@ -12712,6 +12714,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * method. The default actions can also be removed from the menu using * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll}, * {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste}, + * {@link android.R.id#pasteAsPlainText} (starting at API level 23), * {@link android.R.id#replaceText} or {@link android.R.id#shareText} ids as parameters. * * <p>Returning false from @@ -12750,7 +12753,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * {@link android.view.ActionMode.Callback#onPrepareActionMode(android.view.ActionMode, * android.view.Menu)} method. The default actions can also be removed from the menu using * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll}, - * {@link android.R.id#paste} or {@link android.R.id#replaceText} ids as parameters.</p> + * {@link android.R.id#paste}, {@link android.R.id#pasteAsPlainText} (starting at API + * level 23) or {@link android.R.id#replaceText} ids as parameters.</p> * * <p>Returning false from * {@link android.view.ActionMode.Callback#onCreateActionMode(android.view.ActionMode, diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index c6fd6eec2f91..55df09a95838 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -888,6 +888,15 @@ public class ArrayUtils { } } + /** + * Returns the {@code i}-th item in {@code items}, if it exists and {@code items} is not {@code + * null}, otherwise returns {@code null}. + */ + @Nullable + public static <T> T getOrNull(@Nullable T[] items, int i) { + return (items != null && items.length > i) ? items[i] : null; + } + public static @Nullable <T> T firstOrNull(T[] items) { return items.length > 0 ? items[0] : null; } diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java index 9175809d9c7c..f681ba1c3853 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java @@ -28,6 +28,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.os.SystemClock; +import android.text.TextUtils; import android.util.SparseBooleanArray; import com.android.internal.annotations.VisibleForTesting; @@ -500,7 +501,7 @@ public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent && roaming == e.roaming && defaultNetwork == e.defaultNetwork && rxBytes == e.rxBytes && rxPackets == e.rxPackets && txBytes == e.txBytes && txPackets == e.txPackets - && operations == e.operations && iface.equals(e.iface); + && operations == e.operations && TextUtils.equals(iface, e.iface); } return false; } diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java index eeb56d05e706..b1936231148c 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java @@ -1875,7 +1875,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void deleteKernelTagData(int uid) { try { mCookieTagMap.forEach((key, value) -> { - if (value.uid == uid) { + // If SkDestroyListener deletes the socket tag while this code is running, + // forEach will either restart iteration from the beginning or return null, + // depending on when the deletion happens. + // If it returns null, continue iteration to delete the data and in fact it would + // just iterate from first key because BpfMap#getNextKey would return first key + // if the current key is not exist. + if (value != null && value.uid == uid) { try { mCookieTagMap.deleteEntry(key); } catch (ErrnoException e) { diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java index 72230b4062e1..4117d0f07e0f 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java @@ -177,7 +177,7 @@ public class SparseInputStream extends InputStream { ret = 0; break; case SparseChunk.FILL: - ret = mCur.fill[(4 - ((int) mLeft & 0x3)) & 0x3]; + ret = Byte.toUnsignedInt(mCur.fill[(4 - ((int) mLeft & 0x3)) & 0x3]); break; default: throw new IOException("Unsupported Chunk:" + mCur.toString()); diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/OWNERS b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/OWNERS new file mode 100644 index 000000000000..98f41234feb1 --- /dev/null +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/OWNERS @@ -0,0 +1,3 @@ +# Default reviewers for this and subdirectories. +alexflo@google.com +chrisgollner@google.com diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 3fb49e412ed2..30ae7d6b8d21 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -2006,7 +2006,8 @@ public class Vpn { .setCategory(Notification.CATEGORY_SYSTEM) .setVisibility(Notification.VISIBILITY_PUBLIC) .setOngoing(true) - .setColor(mContext.getColor(R.color.system_notification_accent_color)); + .setColor(mContext.getColor( + android.R.color.system_notification_accent_color)); notificationManager.notify(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, builder.build()); } finally { Binder.restoreCallingIdentity(token); diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java index 851ea3d01085..1b7d1ba59b06 100644 --- a/services/core/java/com/android/server/net/LockdownVpnTracker.java +++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java @@ -293,7 +293,7 @@ public class LockdownVpnTracker { .addAction(R.drawable.ic_menu_refresh, mContext.getString(R.string.reset), mResetIntent) .setColor(mContext.getColor( - com.android.internal.R.color.system_notification_accent_color)); + android.R.color.system_notification_accent_color)); mNotificationManager.notify(null /* tag */, SystemMessage.NOTE_VPN_STATUS, builder.build()); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index a518222c3bde..71893f49481f 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -288,7 +288,7 @@ class TaskSnapshotController { } final ActivityRecord activity = result.first; final WindowState mainWindow = result.second; - final Rect contentInsets = getSystemBarInsets(task.getBounds(), + final Rect contentInsets = getSystemBarInsets(mainWindow.getFrame(), mainWindow.getInsetsStateWithVisibilityOverride()); InsetUtils.addInsets(contentInsets, activity.getLetterboxInsets()); @@ -554,7 +554,7 @@ class TaskSnapshotController { final LayoutParams attrs = mainWindow.getAttrs(); final Rect taskBounds = task.getBounds(); final InsetsState insetsState = mainWindow.getInsetsStateWithVisibilityOverride(); - final Rect systemBarInsets = getSystemBarInsets(taskBounds, insetsState); + final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrame(), insetsState); final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags, attrs.privateFlags, attrs.insetsFlags.appearance, task.getTaskDescription(), mHighResTaskSnapshotScale, insetsState); |