Merge rvc-qpr-dev-plus-aosp-without-vendor@6881855
Bug: 172690556
Merged-In: I78222391b83a4add8e964340ec08bb8a1306e1c6
Change-Id: I28bbf40820674675ccf765c912aa8140d3f74ab2
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index fc8248e..1ddfe0d 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -34,6 +34,7 @@
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
import android.os.Binder;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -129,7 +130,7 @@
/**
* {@hide}
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public NetworkStatsManager(Context context) throws ServiceNotFoundException {
this(context, INetworkStatsService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
@@ -153,7 +154,7 @@
}
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@TestApi
public void setPollForce(boolean pollForce) {
if (pollForce) {
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index d975017..84a8e1c 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -23,6 +23,7 @@
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
@@ -37,7 +38,6 @@
* @hide
*/
@SystemApi
-@TestApi
@SystemService(Context.ETHERNET_SERVICE)
public class EthernetManager {
private static final String TAG = "EthernetManager";
@@ -77,7 +77,7 @@
* @param isAvailable {@code true} if Ethernet port exists.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
void onAvailabilityChanged(String iface, boolean isAvailable);
}
@@ -98,7 +98,7 @@
* @return the Ethernet Configuration, contained in {@link IpConfiguration}.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public IpConfiguration getConfiguration(String iface) {
try {
return mService.getConfiguration(iface);
@@ -111,7 +111,7 @@
* Set Ethernet configuration.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void setConfiguration(String iface, IpConfiguration config) {
try {
mService.setConfiguration(iface, config);
@@ -124,7 +124,7 @@
* Indicates whether the system currently has one or more Ethernet interfaces.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public boolean isAvailable() {
return getAvailableInterfaces().length > 0;
}
@@ -135,7 +135,7 @@
* @param iface Ethernet interface name
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public boolean isAvailable(String iface) {
try {
return mService.isAvailable(iface);
@@ -150,7 +150,7 @@
* @throws IllegalArgumentException If the listener is null.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void addListener(Listener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
@@ -169,7 +169,7 @@
* Returns an array of available Ethernet interface names.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public String[] getAvailableInterfaces() {
try {
return mService.getAvailableInterfaces();
@@ -184,7 +184,7 @@
* @throws IllegalArgumentException If the listener is null.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void removeListener(Listener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 5fa515a..1a3dc97 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -42,7 +42,7 @@
* PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted
* READ_NETWORK_USAGE_STATS is checked for.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage);
/** Return data layer snapshot of UID network usage. */
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 38d9883..e89451e 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -17,6 +17,7 @@
import android.annotation.NonNull;
import android.annotation.StringDef;
+import android.content.res.Resources;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,6 +28,12 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
/**
* This class represents a single algorithm that can be used by an {@link IpSecTransform}.
@@ -52,6 +59,27 @@
public static final String CRYPT_AES_CBC = "cbc(aes)";
/**
+ * AES-CTR Encryption/Ciphering Algorithm.
+ *
+ * <p>Valid lengths for keying material are {160, 224, 288}.
+ *
+ * <p>As per <a href="https://tools.ietf.org/html/rfc3686#section-5.1">RFC3686 (Section
+ * 5.1)</a>, keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit
+ * nonce. RFC compliance requires that the nonce must be unique per security association.
+ *
+ * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
+ * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
+ * included in the returned algorithm set. The returned algorithm set will not change unless the
+ * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
+ * requested on an unsupported device.
+ *
+ * <p>@see {@link #getSupportedAlgorithms()}
+ */
+ // This algorithm may be available on devices released before Android 12, and is guaranteed
+ // to be available on devices first shipped with Android 12 or later.
+ public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
+
+ /**
* MD5 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
* new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
*
@@ -99,6 +127,25 @@
public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
/**
+ * AES-XCBC Authentication/Integrity Algorithm.
+ *
+ * <p>Keys for this algorithm must be 128 bits in length.
+ *
+ * <p>The only valid truncation length is 96 bits.
+ *
+ * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
+ * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
+ * included in the returned algorithm set. The returned algorithm set will not change unless the
+ * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
+ * requested on an unsupported device.
+ *
+ * <p>@see {@link #getSupportedAlgorithms()}
+ */
+ // This algorithm may be available on devices released before Android 12, and is guaranteed
+ // to be available on devices first shipped with Android 12 or later.
+ public static final String AUTH_AES_XCBC = "xcbc(aes)";
+
+ /**
* AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm.
*
* <p>Valid lengths for keying material are {160, 224, 288}.
@@ -111,19 +158,69 @@
*/
public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
+ /**
+ * ChaCha20-Poly1305 Authentication/Integrity + Encryption/Ciphering Algorithm.
+ *
+ * <p>Keys for this algorithm must be 288 bits in length.
+ *
+ * <p>As per <a href="https://tools.ietf.org/html/rfc7634#section-2">RFC7634 (Section 2)</a>,
+ * keying material consists of a 256 bit key followed by a 32-bit salt. The salt is fixed per
+ * security association.
+ *
+ * <p>The only valid ICV (truncation) length is 128 bits.
+ *
+ * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
+ * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
+ * included in the returned algorithm set. The returned algorithm set will not change unless the
+ * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
+ * requested on an unsupported device.
+ *
+ * <p>@see {@link #getSupportedAlgorithms()}
+ */
+ // This algorithm may be available on devices released before Android 12, and is guaranteed
+ // to be available on devices first shipped with Android 12 or later.
+ public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
+
/** @hide */
@StringDef({
CRYPT_AES_CBC,
+ CRYPT_AES_CTR,
AUTH_HMAC_MD5,
AUTH_HMAC_SHA1,
AUTH_HMAC_SHA256,
AUTH_HMAC_SHA384,
AUTH_HMAC_SHA512,
- AUTH_CRYPT_AES_GCM
+ AUTH_AES_XCBC,
+ AUTH_CRYPT_AES_GCM,
+ AUTH_CRYPT_CHACHA20_POLY1305
})
@Retention(RetentionPolicy.SOURCE)
public @interface AlgorithmName {}
+ /** @hide */
+ @VisibleForTesting
+ public static final Map<String, Integer> ALGO_TO_REQUIRED_FIRST_SDK = new HashMap<>();
+
+ private static final int SDK_VERSION_ZERO = 0;
+
+ static {
+ ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO);
+
+ // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined
+ ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1);
+ }
+
+ private static final Set<String> ENABLED_ALGOS =
+ Collections.unmodifiableSet(loadAlgos(Resources.getSystem()));
+
private final String mName;
private final byte[] mKey;
private final int mTruncLenBits;
@@ -137,6 +234,7 @@
*
* @param algorithm name of the algorithm.
* @param key key padded to a multiple of 8 bits.
+ * @throws IllegalArgumentException if algorithm or key length is invalid.
*/
public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) {
this(algorithm, key, 0);
@@ -152,6 +250,7 @@
* @param algorithm name of the algorithm.
* @param key key padded to a multiple of 8 bits.
* @param truncLenBits number of bits of output hash to use.
+ * @throws IllegalArgumentException if algorithm, key length or truncation length is invalid.
*/
public IpSecAlgorithm(
@NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
@@ -206,13 +305,59 @@
}
};
- private static void checkValidOrThrow(String name, int keyLen, int truncLen) {
- boolean isValidLen = true;
- boolean isValidTruncLen = true;
+ /**
+ * Returns supported IPsec algorithms for the current device.
+ *
+ * <p>Some algorithms may not be supported on old devices. Callers MUST check if an algorithm is
+ * supported before using it.
+ */
+ @NonNull
+ public static Set<String> getSupportedAlgorithms() {
+ return ENABLED_ALGOS;
+ }
- switch(name) {
+ /** @hide */
+ @VisibleForTesting
+ public static Set<String> loadAlgos(Resources systemResources) {
+ final Set<String> enabledAlgos = new HashSet<>();
+
+ // Load and validate the optional algorithm resource. Undefined or duplicate algorithms in
+ // the resource are not allowed.
+ final String[] resourceAlgos = systemResources.getStringArray(
+ com.android.internal.R.array.config_optionalIpSecAlgorithms);
+ for (String str : resourceAlgos) {
+ if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) {
+ // This error should be caught by CTS and never be thrown to API callers
+ throw new IllegalArgumentException("Invalid or repeated algorithm " + str);
+ }
+ }
+
+ for (Entry<String, Integer> entry : ALGO_TO_REQUIRED_FIRST_SDK.entrySet()) {
+ if (Build.VERSION.FIRST_SDK_INT >= entry.getValue()) {
+ enabledAlgos.add(entry.getKey());
+ }
+ }
+
+ return enabledAlgos;
+ }
+
+ private static void checkValidOrThrow(String name, int keyLen, int truncLen) {
+ final boolean isValidLen;
+ final boolean isValidTruncLen;
+
+ if (!getSupportedAlgorithms().contains(name)) {
+ throw new IllegalArgumentException("Unsupported algorithm: " + name);
+ }
+
+ switch (name) {
case CRYPT_AES_CBC:
isValidLen = keyLen == 128 || keyLen == 192 || keyLen == 256;
+ isValidTruncLen = true;
+ break;
+ case CRYPT_AES_CTR:
+ // The keying material for AES-CTR is a key plus a 32-bit salt
+ isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
+ isValidTruncLen = true;
break;
case AUTH_HMAC_MD5:
isValidLen = keyLen == 128;
@@ -234,12 +379,22 @@
isValidLen = keyLen == 512;
isValidTruncLen = truncLen >= 256 && truncLen <= 512;
break;
+ case AUTH_AES_XCBC:
+ isValidLen = keyLen == 128;
+ isValidTruncLen = truncLen == 96;
+ break;
case AUTH_CRYPT_AES_GCM:
// The keying material for GCM is a key plus a 32-bit salt
isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128;
break;
+ case AUTH_CRYPT_CHACHA20_POLY1305:
+ // The keying material for ChaCha20Poly1305 is a key plus a 32-bit salt
+ isValidLen = keyLen == 256 + 32;
+ isValidTruncLen = truncLen == 128;
+ break;
default:
+ // Should never hit here.
throw new IllegalArgumentException("Couldn't find an algorithm: " + name);
}
@@ -260,6 +415,7 @@
case AUTH_HMAC_SHA256:
case AUTH_HMAC_SHA384:
case AUTH_HMAC_SHA512:
+ case AUTH_AES_XCBC:
return true;
default:
return false;
@@ -268,12 +424,24 @@
/** @hide */
public boolean isEncryption() {
- return getName().equals(CRYPT_AES_CBC);
+ switch (getName()) {
+ case CRYPT_AES_CBC: // fallthrough
+ case CRYPT_AES_CTR:
+ return true;
+ default:
+ return false;
+ }
}
/** @hide */
public boolean isAead() {
- return getName().equals(AUTH_CRYPT_AES_GCM);
+ switch (getName()) {
+ case AUTH_CRYPT_AES_GCM: // fallthrough
+ case AUTH_CRYPT_CHACHA20_POLY1305:
+ return true;
+ default:
+ return false;
+ }
}
// Because encryption keys are sensitive and userdebug builds are used by large user pools
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 34e48eb..cf40ce5 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -219,11 +220,11 @@
* generated.
*/
private long elapsedRealtime;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private int size;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private int capacity;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private String[] iface;
@UnsupportedAppUsage
private int[] uid;
@@ -231,21 +232,21 @@
private int[] set;
@UnsupportedAppUsage
private int[] tag;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private int[] metered;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private int[] roaming;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private int[] defaultNetwork;
@UnsupportedAppUsage
private long[] rxBytes;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private long[] rxPackets;
@UnsupportedAppUsage
private long[] txBytes;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private long[] txPackets;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private long[] operations;
/**
@@ -258,7 +259,7 @@
@SystemApi
public static class Entry {
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public String iface;
/** @hide */
@UnsupportedAppUsage
@@ -267,7 +268,7 @@
@UnsupportedAppUsage
public int set;
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int tag;
/**
* Note that this is only populated w/ the default value when read from /proc or written
@@ -294,20 +295,20 @@
@UnsupportedAppUsage
public long rxBytes;
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public long rxPackets;
/** @hide */
@UnsupportedAppUsage
public long txBytes;
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public long txPackets;
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public long operations;
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public Entry() {
this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
}
@@ -454,7 +455,7 @@
}
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public NetworkStats(Parcel parcel) {
elapsedRealtime = parcel.readLong();
size = parcel.readInt();
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index 51f09a0..fba7561 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -32,6 +32,7 @@
import static com.android.internal.util.ArrayUtils.total;
import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.NetworkStatsHistoryBucketProto;
@@ -91,18 +92,18 @@
public static class Entry {
public static final long UNKNOWN = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public long bucketDuration;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public long bucketStart;
public long activeTime;
@UnsupportedAppUsage
public long rxBytes;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public long rxPackets;
@UnsupportedAppUsage
public long txBytes;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public long txPackets;
public long operations;
}
@@ -134,7 +135,7 @@
recordEntireHistory(existing);
}
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public NetworkStatsHistory(Parcel in) {
bucketDuration = in.readLong();
bucketStart = readLongArray(in);
@@ -220,7 +221,7 @@
return 0;
}
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int size() {
return bucketCount;
}
@@ -258,7 +259,7 @@
* Return index of bucket that contains or is immediately before the
* requested time.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int getIndexBefore(long time) {
int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
if (index < 0) {
@@ -286,7 +287,7 @@
/**
* Return specific stats entry.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public Entry getValues(int i, Entry recycle) {
final Entry entry = recycle != null ? recycle : new Entry();
entry.bucketStart = bucketStart[i];
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index cd26079..72be835 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -37,6 +37,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.NetworkType;
@@ -159,7 +160,7 @@
* Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks,
* regardless of IMSI.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static NetworkTemplate buildTemplateMobileWildcard() {
return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
}
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index e7bba69..fa65061 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -301,7 +301,7 @@
* Changes only take effect during subsequent calls to
* {@link #tagSocket(Socket)}.
*/
- @SuppressLint("Doclava125")
+ @SuppressLint("RequiresPermission")
public static void setThreadStatsUid(int uid) {
NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
}
@@ -339,7 +339,7 @@
*
* @see #setThreadStatsUid(int)
*/
- @SuppressLint("Doclava125")
+ @SuppressLint("RequiresPermission")
public static void clearThreadStatsUid() {
NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
}
@@ -565,7 +565,7 @@
}
/** {@hide} */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static long getMobileTcpRxPackets() {
long total = 0;
for (String iface : getMobileIfaces()) {
@@ -581,7 +581,7 @@
}
/** {@hide} */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static long getMobileTcpTxPackets() {
long total = 0;
for (String iface : getMobileIfaces()) {
@@ -597,10 +597,17 @@
}
/**
- * Return the number of packets transmitted on the specified interface since
- * device boot. Statistics are measured at the network layer, so both TCP and
+ * Return the number of packets transmitted on the specified interface since the interface
+ * was created. Statistics are measured at the network layer, so both TCP and
* UDP usage are included.
*
+ * Note that the returned values are partial statistics that do not count data from several
+ * sources and do not apply several adjustments that are necessary for correctness, such
+ * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
+ * determine whether traffic is being transferred on the specific interface but are not a
+ * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
+ * APIs.
+ *
* @param iface The name of the interface.
* @return The number of transmitted packets.
*/
@@ -613,10 +620,17 @@
}
/**
- * Return the number of packets received on the specified interface since
- * device boot. Statistics are measured at the network layer, so both TCP
+ * Return the number of packets received on the specified interface since the interface was
+ * created. Statistics are measured at the network layer, so both TCP
* and UDP usage are included.
*
+ * Note that the returned values are partial statistics that do not count data from several
+ * sources and do not apply several adjustments that are necessary for correctness, such
+ * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
+ * determine whether traffic is being transferred on the specific interface but are not a
+ * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
+ * APIs.
+ *
* @param iface The name of the interface.
* @return The number of received packets.
*/
@@ -628,9 +642,22 @@
}
}
- /** {@hide} */
- @UnsupportedAppUsage
- public static long getTxBytes(String iface) {
+ /**
+ * Return the number of bytes transmitted on the specified interface since the interface
+ * was created. Statistics are measured at the network layer, so both TCP and
+ * UDP usage are included.
+ *
+ * Note that the returned values are partial statistics that do not count data from several
+ * sources and do not apply several adjustments that are necessary for correctness, such
+ * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
+ * determine whether traffic is being transferred on the specific interface but are not a
+ * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
+ * APIs.
+ *
+ * @param iface The name of the interface.
+ * @return The number of transmitted bytes.
+ */
+ public static long getTxBytes(@NonNull String iface) {
try {
return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES);
} catch (RemoteException e) {
@@ -638,9 +665,22 @@
}
}
- /** {@hide} */
- @UnsupportedAppUsage
- public static long getRxBytes(String iface) {
+ /**
+ * Return the number of bytes received on the specified interface since the interface
+ * was created. Statistics are measured at the network layer, so both TCP
+ * and UDP usage are included.
+ *
+ * Note that the returned values are partial statistics that do not count data from several
+ * sources and do not apply several adjustments that are necessary for correctness, such
+ * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
+ * determine whether traffic is being transferred on the specific interface but are not a
+ * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
+ * APIs.
+ *
+ * @param iface The name of the interface.
+ * @return The number of received bytes.
+ */
+ public static long getRxBytes(@NonNull String iface) {
try {
return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES);
} catch (RemoteException e) {
@@ -976,11 +1016,17 @@
}
}
- // NOTE: keep these in sync with android_net_TrafficStats.cpp
- private static final int TYPE_RX_BYTES = 0;
- private static final int TYPE_RX_PACKETS = 1;
- private static final int TYPE_TX_BYTES = 2;
- private static final int TYPE_TX_PACKETS = 3;
- private static final int TYPE_TCP_RX_PACKETS = 4;
- private static final int TYPE_TCP_TX_PACKETS = 5;
+ // NOTE: keep these in sync with {@code com_android_server_net_NetworkStatsService.cpp}.
+ /** {@hide} */
+ public static final int TYPE_RX_BYTES = 0;
+ /** {@hide} */
+ public static final int TYPE_RX_PACKETS = 1;
+ /** {@hide} */
+ public static final int TYPE_TX_BYTES = 2;
+ /** {@hide} */
+ public static final int TYPE_TX_PACKETS = 3;
+ /** {@hide} */
+ public static final int TYPE_TCP_RX_PACKETS = 4;
+ /** {@hide} */
+ public static final int TYPE_TCP_TX_PACKETS = 5;
}
diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl
index 9484c74..e9e8935 100644
--- a/core/java/android/net/nsd/INsdManager.aidl
+++ b/core/java/android/net/nsd/INsdManager.aidl
@@ -25,7 +25,7 @@
*/
interface INsdManager
{
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
Messenger getMessenger();
void setEnabled(boolean enable);
}
diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
deleted file mode 100644
index 29c0a81..0000000
--- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020 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.net.util;
-
-/**
- * This class defines Message.what base addresses for various state machine.
- */
-public class TetheringMessageBase {
- public static final int BASE_MAIN_SM = 0;
- public static final int BASE_IPSERVER = 100;
-
-}
diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java
index 7c1c1c7..ddc5ef2 100644
--- a/services/core/java/com/android/server/net/NetworkStatsAccess.java
+++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java
@@ -24,10 +24,10 @@
import android.Manifest;
import android.annotation.IntDef;
import android.app.AppOpsManager;
-import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.os.Process;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
@@ -111,12 +111,12 @@
boolean hasCarrierPrivileges = tm != null &&
tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) ==
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
- boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
- DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid);
+ final int appId = UserHandle.getAppId(callingUid);
if (hasCarrierPrivileges || isDeviceOwner
- || UserHandle.getAppId(callingUid) == android.os.Process.SYSTEM_UID) {
- // Carrier-privileged apps and device owners, and the system can access data usage for
- // all apps on the device.
+ || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) {
+ // Carrier-privileged apps and device owners, and the system (including the
+ // network stack) can access data usage for all apps on the device.
return NetworkStatsAccess.Level.DEVICE;
}
@@ -126,8 +126,9 @@
return NetworkStatsAccess.Level.DEVICESUMMARY;
}
- boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode.
+ boolean isProfileOwner = dpmi != null && (dpmi.isActiveProfileOwner(callingUid)
+ || dpmi.isActiveDeviceOwner(callingUid));
if (isProfileOwner) {
// Apps with the AppOps permission, profile owners, and apps with the privileged
// permission can access data usage for all apps in this user/profile.
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 71e7c8a..81a6641 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -552,7 +552,8 @@
// schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}.
final PendingIntent pollIntent =
- PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
+ PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL),
+ PendingIntent.FLAG_IMMUTABLE);
final long currentRealtime = SystemClock.elapsedRealtime();
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
@@ -1083,12 +1084,10 @@
return nativeIfaceStats;
} else {
// When tethering offload is in use, nativeIfaceStats does not contain usage from
- // offload, add it back here.
- // When tethering offload is not in use, nativeIfaceStats contains tethering usage.
- // this does not cause double-counting of tethering traffic, because
- // NetdTetheringStatsProvider returns zero NetworkStats
- // when called with STATS_PER_IFACE.
- return nativeIfaceStats + getTetherStats(iface, type);
+ // offload, add it back here. Note that the included statistics might be stale
+ // since polling newest stats from hardware might impact system health and not
+ // suitable for TrafficStats API use cases.
+ return nativeIfaceStats + getProviderIfaceStats(iface, type);
}
}
@@ -1099,39 +1098,28 @@
return nativeTotalStats;
} else {
// Refer to comment in getIfaceStats
- return nativeTotalStats + getTetherStats(IFACE_ALL, type);
+ return nativeTotalStats + getProviderIfaceStats(IFACE_ALL, type);
}
}
- private long getTetherStats(String iface, int type) {
- final NetworkStats tetherSnapshot;
- final long token = Binder.clearCallingIdentity();
- try {
- tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE);
- } catch (RemoteException e) {
- Slog.w(TAG, "Error get TetherStats: " + e);
- return 0;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- HashSet<String> limitIfaces;
+ private long getProviderIfaceStats(@Nullable String iface, int type) {
+ final NetworkStats providerSnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
+ final HashSet<String> limitIfaces;
if (iface == IFACE_ALL) {
limitIfaces = null;
} else {
- limitIfaces = new HashSet<String>();
+ limitIfaces = new HashSet<>();
limitIfaces.add(iface);
}
- NetworkStats.Entry entry = tetherSnapshot.getTotal(null, limitIfaces);
- if (LOGD) Slog.d(TAG, "TetherStats: iface=" + iface + " type=" + type +
- " entry=" + entry);
+ final NetworkStats.Entry entry = providerSnapshot.getTotal(null, limitIfaces);
switch (type) {
- case 0: // TYPE_RX_BYTES
+ case TrafficStats.TYPE_RX_BYTES:
return entry.rxBytes;
- case 1: // TYPE_RX_PACKETS
+ case TrafficStats.TYPE_RX_PACKETS:
return entry.rxPackets;
- case 2: // TYPE_TX_BYTES
+ case TrafficStats.TYPE_TX_BYTES:
return entry.txBytes;
- case 3: // TYPE_TX_PACKETS
+ case TrafficStats.TYPE_TX_PACKETS:
return entry.txPackets;
default:
return 0;
@@ -1428,14 +1416,6 @@
final NetworkStats devSnapshot = readNetworkStatsSummaryDev();
Trace.traceEnd(TRACE_TAG_NETWORK);
- // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats
- // providers that isn't already counted by dev and XT stats.
- Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotTether");
- final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE);
- Trace.traceEnd(TRACE_TAG_NETWORK);
- xtSnapshot.combineAllValues(tetherSnapshot);
- devSnapshot.combineAllValues(tetherSnapshot);
-
// Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data
// from stats providers that isn't already counted by dev and XT stats.
Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider");
@@ -1510,29 +1490,7 @@
final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
- // Request asynchronous stats update from all providers for next poll. And wait a bit of
- // time to allow providers report-in given that normally binder call should be fast. Note
- // that size of list might be changed because addition/removing at the same time. For
- // addition, the stats of the missed provider can only be collected in next poll;
- // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS
- // once that happened.
- // TODO: request with a valid token.
- Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
- final int registeredCallbackCount = mStatsProviderCbList.size();
- mStatsProviderSem.drainPermits();
- invokeForAllStatsProviderCallbacks(
- (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
- try {
- mStatsProviderSem.tryAcquire(registeredCallbackCount,
- MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- // Strictly speaking it's possible a provider happened to deliver between the timeout
- // and the log, and that doesn't matter too much as this is just a debug log.
- Log.d(TAG, "requestStatsUpdate - providers responded "
- + mStatsProviderSem.availablePermits()
- + "/" + registeredCallbackCount + " : " + e);
- }
- Trace.traceEnd(TRACE_TAG_NETWORK);
+ performPollFromProvidersLocked();
// TODO: consider marking "untrusted" times in historical stats
final long currentTime = mClock.millis();
@@ -1577,6 +1535,33 @@
Trace.traceEnd(TRACE_TAG_NETWORK);
}
+ @GuardedBy("mStatsLock")
+ private void performPollFromProvidersLocked() {
+ // Request asynchronous stats update from all providers for next poll. And wait a bit of
+ // time to allow providers report-in given that normally binder call should be fast. Note
+ // that size of list might be changed because addition/removing at the same time. For
+ // addition, the stats of the missed provider can only be collected in next poll;
+ // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS
+ // once that happened.
+ // TODO: request with a valid token.
+ Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
+ final int registeredCallbackCount = mStatsProviderCbList.size();
+ mStatsProviderSem.drainPermits();
+ invokeForAllStatsProviderCallbacks(
+ (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
+ try {
+ mStatsProviderSem.tryAcquire(registeredCallbackCount,
+ MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ // Strictly speaking it's possible a provider happened to deliver between the timeout
+ // and the log, and that doesn't matter too much as this is just a debug log.
+ Log.d(TAG, "requestStatsUpdate - providers responded "
+ + mStatsProviderSem.availablePermits()
+ + "/" + registeredCallbackCount + " : " + e);
+ }
+ Trace.traceEnd(TRACE_TAG_NETWORK);
+ }
+
/**
* Sample recent statistics summary into {@link EventLog}.
*/
@@ -1930,9 +1915,13 @@
}
/**
- * Return snapshot of current tethering statistics. Will return empty
- * {@link NetworkStats} if any problems are encountered.
+ * Return snapshot of current non-offloaded tethering statistics. Will return empty
+ * {@link NetworkStats} if any problems are encountered, or queried by {@code STATS_PER_IFACE}
+ * since it is already included by {@link #nativeGetIfaceStat}.
+ * See {@code OffloadTetheringStatsProvider} for offloaded tethering stats.
*/
+ // TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded
+ // tethering stats.
private NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
try {
return mNetworkManager.getNetworkStatsTethering(how);
@@ -2225,13 +2214,6 @@
}
}
- private static int TYPE_RX_BYTES;
- private static int TYPE_RX_PACKETS;
- private static int TYPE_TX_BYTES;
- private static int TYPE_TX_PACKETS;
- private static int TYPE_TCP_RX_PACKETS;
- private static int TYPE_TCP_TX_PACKETS;
-
private static native long nativeGetTotalStat(int type, boolean useBpfStats);
private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats);
private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats);
diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index d202a2a..5646c75 100644
--- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -30,6 +30,7 @@
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.CollectionUtils;
@@ -94,39 +95,41 @@
// also needed to track CBRS.
final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager);
- for (final int subId : newSubs) {
- final RatTypeListener match = CollectionUtils.find(mRatListeners,
- it -> it.mSubId == subId);
- if (match != null) continue;
+ // IMSI is needed for every newly added sub. Listener stores subscriberId into it to
+ // prevent binder call to telephony when querying RAT. Keep listener registration with empty
+ // IMSI is meaningless since the RAT type changed is ambiguous for multi-SIM if reported
+ // with empty IMSI. So filter the subs w/o a valid IMSI to prevent such registration.
+ final List<Pair<Integer, String>> filteredNewSubs =
+ CollectionUtils.mapNotNull(newSubs, subId -> {
+ final String subscriberId = mTeleManager.getSubscriberId(subId);
+ return TextUtils.isEmpty(subscriberId) ? null : new Pair(subId, subscriberId);
+ });
- // Create listener for every newly added sub. Also store subscriberId into it to
- // prevent binder call to telephony when querying RAT. If the subscriberId is empty
- // for any reason, such as SIM PIN locked, skip registration.
- // SubscriberId will be unavailable again if 1. modem crashed 2. reboot
- // 3. re-insert SIM. If that happens, the listeners will be eventually synchronized
- // with active sub list once all subscriberIds are ready.
- final String subscriberId = mTeleManager.getSubscriberId(subId);
- if (TextUtils.isEmpty(subscriberId)) {
- Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub "
- + subId + ", skip listener registration");
+ for (final Pair<Integer, String> sub : filteredNewSubs) {
+ // Fully match listener with subId and IMSI, since in some rare cases, IMSI might be
+ // suddenly change regardless of subId, such as switch IMSI feature in modem side.
+ // If that happens, register new listener with new IMSI and remove old one later.
+ if (CollectionUtils.find(mRatListeners,
+ it -> it.equalsKey(sub.first, sub.second)) != null) {
continue;
}
+
final RatTypeListener listener =
- new RatTypeListener(mExecutor, this, subId, subscriberId);
+ new RatTypeListener(mExecutor, this, sub.first, sub.second);
mRatListeners.add(listener);
// Register listener to the telephony manager that associated with specific sub.
- mTeleManager.createForSubscriptionId(subId)
+ mTeleManager.createForSubscriptionId(sub.first)
.listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
- Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId);
+ Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + sub.first);
}
for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
- // If the new list contains the subId of the listener, keeps it.
- final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId);
- if (match != null) continue;
-
- handleRemoveRatTypeListener(listener);
+ // If there is no subId and IMSI matched the listener, removes it.
+ if (CollectionUtils.find(filteredNewSubs,
+ it -> listener.equalsKey(it.first, it.second)) == null) {
+ handleRemoveRatTypeListener(listener);
+ }
}
}
@@ -232,5 +235,9 @@
public int getSubId() {
return mSubId;
}
+
+ boolean equalsKey(int subId, @NonNull String subscriberId) {
+ return mSubId == subId && TextUtils.equals(mSubscriberId, subscriberId);
+ }
}
}
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 0275f3e..10b248a 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -215,21 +215,6 @@
};
int register_android_server_net_NetworkStatsService(JNIEnv* env) {
- jclass netStatsService = env->FindClass("com/android/server/net/NetworkStatsService");
- jfieldID rxBytesId = env->GetStaticFieldID(netStatsService, "TYPE_RX_BYTES", "I");
- jfieldID rxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_RX_PACKETS", "I");
- jfieldID txBytesId = env->GetStaticFieldID(netStatsService, "TYPE_TX_BYTES", "I");
- jfieldID txPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TX_PACKETS", "I");
- jfieldID tcpRxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_RX_PACKETS", "I");
- jfieldID tcpTxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_TX_PACKETS", "I");
-
- env->SetStaticIntField(netStatsService, rxBytesId, RX_BYTES);
- env->SetStaticIntField(netStatsService, rxPacketsId, RX_PACKETS);
- env->SetStaticIntField(netStatsService, txBytesId, TX_BYTES);
- env->SetStaticIntField(netStatsService, txPacketsId, TX_PACKETS);
- env->SetStaticIntField(netStatsService, tcpRxPacketsId, TCP_RX_PACKETS);
- env->SetStaticIntField(netStatsService, tcpTxPacketsId, TCP_TX_PACKETS);
-
return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods,
NELEM(gMethods));
}