Merge "AudioService: fix regression on hearing aid profile"
diff --git a/Android.bp b/Android.bp
index 52e011f..b69fa63 100644
--- a/Android.bp
+++ b/Android.bp
@@ -449,21 +449,28 @@
}
// 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 5cb0a78..39fd511 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -365,6 +365,64 @@
},
}
+////////////////////////////////////////////////////////////////////////
+// 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 3a8076c..b5066d9 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -26189,7 +26189,6 @@
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 @@
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 @@
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 2c7f456..5c6076b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10131,8 +10131,6 @@
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 0a9fe90..9a780c8 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -84,13 +84,6 @@
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 0000000..2ca3bd2
--- /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 ad3de25..45812e5 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 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 @@
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 @@
}
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 @@
* 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) {
- int i = mMap.indexOfKey(key);
- return (i >= 0) ? getValueAt(i) : null;
+ 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 a certain position in the array map.
+ * 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 Object getValueAt(int i) {
+ @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, itemTypes) : null;
+ }
+
+ /**
+ * 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
+ */
+ @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 @@
}
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 @@
} 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 @@
*
* @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 @@
}
/**
+ * 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 @@
}
// 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 @@
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 @@
*
* @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 @@
}
/**
+ * 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 @@
*/
@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 @@
*/
@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 @@
*/
@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 b2bbfd6..edbbb59 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 @@
@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 @@
*
* @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 @@
}
/**
+ * 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 @@
*
* @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 @@
}
/**
+ * 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 @@
*
* @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 @@
}
/**
+ * 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 @@
}
/**
+ * 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 @@
}
/**
+ * 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 13d1d96..d3b35a0 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.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 @@
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 @@
*/
@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 @@
@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 @@
@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 @@
@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 @@
/**
- * @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 @@
+ " 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 @@
}
- 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 @@
}
@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 @@
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 @@
}
}
+ /** 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 @@
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 @@
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 @@
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 @@
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 @@
+ " 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 @@
}
/**
+ * 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 @@
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 @@
}
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 @@
@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 @@
* 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 @@
// 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 @@
// 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 @@
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 @@
}
}
- /* 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 3d16a3d..6fdc8e8 100644
--- a/core/java/android/service/tracing/TraceReportService.java
+++ b/core/java/android/service/tracing/TraceReportService.java
@@ -112,7 +112,6 @@
}
}
- // Methods to override.
/**
* Called when a trace is reported and sent to this class.
*
@@ -123,15 +122,10 @@
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 @@
/**
* 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 00f4eb8..5b0bc4a 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -3128,7 +3128,8 @@
/**
* 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 @@
* 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 @@
* 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 452dad3..9791da5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12521,7 +12521,9 @@
/**
* 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 @@
* 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 @@
* {@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 c6fd6ee..55df09a 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -888,6 +888,15 @@
}
}
+ /**
+ * 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 9175809..f681ba1 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.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 @@
&& 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 eeb56d0..b193623 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 @@
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 72230b4..4117d0f 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
@@ -177,7 +177,7 @@
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 0000000..98f4123
--- /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 3fb49e4..30ae7d6 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 @@
.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 851ea3d..1b7d1ba 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 @@
.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 a518222..71893f4 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 @@
}
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 @@
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);