Merge "Sort metalava_framework_docs_args"
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/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index ad3de25..244335d 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -31,7 +31,7 @@
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Set;
-import java.util.function.Supplier;
+import java.util.function.Function;
/**
* A mapping from String keys to values of various types. In most cases, you
@@ -252,11 +252,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 | BadParcelableException e) {
+ typeWarning("getPairValue()", /* value */ null, "String", e);
return null;
}
}
@@ -309,7 +308,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);
}
}
}
@@ -324,8 +323,21 @@
* @hide
*/
final Object getValue(String key) {
+ return getValue(key, /* clazz */ null);
+ }
+
+ /**
+ * Returns the value for key {@code key} for expected return type {@param clazz} (or {@code
+ * null} for no type check).
+ *
+ * This call should always be made after {@link #unparcel()} or inside a lock after making sure
+ * {@code mMap} is not null.
+ *
+ * @hide
+ */
+ final <T> T getValue(String key, @Nullable Class<T> clazz) {
int i = mMap.indexOfKey(key);
- return (i >= 0) ? getValueAt(i) : null;
+ return (i >= 0) ? getValueAt(i, clazz) : null;
}
/**
@@ -336,11 +348,12 @@
*
* @hide
*/
- final Object getValueAt(int i) {
+ @SuppressWarnings("unchecked")
+ final <T> T getValueAt(int i, @Nullable Class<T> clazz) {
Object object = mMap.valueAt(i);
- if (object instanceof Supplier<?>) {
+ if (object instanceof Function<?, ?>) {
try {
- object = ((Supplier<?>) object).get();
+ object = ((Function<Class<?>, ?>) object).apply(clazz);
} catch (BadParcelableException e) {
if (sShouldDefuse) {
Log.w(TAG, "Failed to parse item " + mMap.keyAt(i) + ", returning null.", e);
@@ -351,7 +364,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 +541,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).
@@ -982,15 +995,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,8 +1015,7 @@
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);
}
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index b2bbfd6..2b13f20 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -16,6 +16,9 @@
package android.os;
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
@@ -914,6 +917,33 @@
/**
* 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.
+ *
+ * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
+ * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
+ * Otherwise, this method might throw an exception or return {@code null}.
+ *
+ * @param key a String, or {@code null}
+ * @param clazz The type of the object expected or {@code null} for performing no checks.
+ * @return a Parcelable value, or {@code null}
+ *
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ @Nullable
+ public <T> T getParcelable(@Nullable String key, @NonNull Class<T> clazz) {
+ unparcel();
+ try {
+ return getValue(key, requireNonNull(clazz));
+ } catch (ClassCastException | BadParcelableException e) {
+ typeWarning(key, /* value */ null, "Parcelable", e);
+ return null;
+ }
+ }
+
+ /**
+ * 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.
*
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 13d1d96..32cee94 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -4312,18 +4312,19 @@
}
/**
- * 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 Function} for length-prefixed types that deserializes the object
+ * when {@link Function#apply} is called with the expected class of the return object (or {@code
+ * null} for no type check), for other types it will return the object itself.
*
- * <p>After calling {@link Supplier#get()} the parcel cursor will not change. Note that you
- * shouldn't recycle the parcel, not at least until all objects have been retrieved. No
+ * <p>After calling {@link Function#apply(Object)} 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 Function#apply} has been called on both and both objects returned are equal.
+ * <li>{@link Function#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 +4351,7 @@
}
- private static final class LazyValue implements Supplier<Object> {
+ private static final class LazyValue implements Function<Class<?>, Object> {
/**
* | 4B | 4B |
* mSource = Parcel{... | type | length | object | ...}
@@ -4382,7 +4383,7 @@
}
@Override
- public Object get() {
+ public Object apply(@Nullable Class<?> clazz) {
Parcel source = mSource;
if (source != null) {
synchronized (source) {
@@ -4391,7 +4392,7 @@
int restore = source.dataPosition();
try {
source.setDataPosition(mPosition);
- mObject = source.readValue(mLoader);
+ mObject = source.readValue(mLoader, clazz);
} finally {
source.setDataPosition(restore);
}
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/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) {