Merge "Remove ServiceManager usage from IpSecTransform"
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/core/java/android/net/InternalNetworkUpdateRequest.java
index 6f09383..f42c4b7 100644
--- a/core/java/android/net/InternalNetworkUpdateRequest.java
+++ b/core/java/android/net/InternalNetworkUpdateRequest.java
@@ -17,7 +17,6 @@
package android.net;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,7 +26,7 @@
public final class InternalNetworkUpdateRequest implements Parcelable {
@NonNull
private final StaticIpConfiguration mIpConfig;
- @Nullable
+ @NonNull
private final NetworkCapabilities mNetworkCapabilities;
@NonNull
@@ -37,20 +36,16 @@
@NonNull
public NetworkCapabilities getNetworkCapabilities() {
- return mNetworkCapabilities == null
- ? null : new NetworkCapabilities(mNetworkCapabilities);
+ return new NetworkCapabilities(mNetworkCapabilities);
}
/** @hide */
public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
- @Nullable final NetworkCapabilities networkCapabilities) {
+ @NonNull final NetworkCapabilities networkCapabilities) {
Objects.requireNonNull(ipConfig);
+ Objects.requireNonNull(networkCapabilities);
mIpConfig = new StaticIpConfiguration(ipConfig);
- if (null == networkCapabilities) {
- mNetworkCapabilities = null;
- } else {
- mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
- }
+ mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
}
private InternalNetworkUpdateRequest(@NonNull final Parcel source) {
diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp
index 0bda923..90bb76a 100644
--- a/framework-t/Sources.bp
+++ b/framework-t/Sources.bp
@@ -25,15 +25,21 @@
name: "framework-connectivity-netstats-internal-sources",
srcs: [
"src/android/app/usage/*.java",
- "src/android/net/DataUsage*.*",
- "src/android/net/INetworkStats*.*",
- "src/android/net/NetworkIdentity*.java",
+ "src/android/net/DataUsageRequest.*",
+ "src/android/net/INetworkStatsService.aidl",
+ "src/android/net/INetworkStatsSession.aidl",
+ "src/android/net/NetworkIdentity.java",
+ "src/android/net/NetworkIdentitySet.java",
"src/android/net/NetworkStateSnapshot.*",
- "src/android/net/NetworkStats*.*",
+ "src/android/net/NetworkStats.*",
+ "src/android/net/NetworkStatsAccess.*",
+ "src/android/net/NetworkStatsCollection.*",
+ "src/android/net/NetworkStatsHistory.*",
"src/android/net/NetworkTemplate.*",
"src/android/net/TrafficStats.java",
"src/android/net/UnderlyingNetworkInfo.*",
"src/android/net/netstats/**/*.*",
+ "src/com/android/server/NetworkManagementSocketTagger.java",
],
path: "src",
visibility: [
diff --git a/framework-t/src/android/app/usage/NetworkStats.java b/framework-t/src/android/app/usage/NetworkStats.java
index 216a4a0..d33666d 100644
--- a/framework-t/src/android/app/usage/NetworkStats.java
+++ b/framework-t/src/android/app/usage/NetworkStats.java
@@ -24,13 +24,15 @@
import android.net.NetworkTemplate;
import android.net.TrafficStats;
import android.os.RemoteException;
-import android.util.IntArray;
import android.util.Log;
+import com.android.net.module.util.CollectionUtils;
+
import dalvik.system.CloseGuard;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
/**
* Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects
@@ -543,6 +545,15 @@
}
/**
+ * Collects tagged summary results and sets summary enumeration mode.
+ * @throws RemoteException
+ */
+ void startTaggedSummaryEnumeration() throws RemoteException {
+ mSummary = mSession.getTaggedSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp);
+ mEnumerationIndex = 0;
+ }
+
+ /**
* Collects history results for uid and resets history enumeration index.
*/
void startHistoryEnumeration(int uid, int tag, int state) {
@@ -568,7 +579,7 @@
// the filtering logic below can be removed.
int[] uids = mSession.getRelevantUids();
// Filtering of uids with empty history.
- IntArray filteredUids = new IntArray(uids.length);
+ final ArrayList<Integer> filteredUids = new ArrayList<>();
for (int uid : uids) {
try {
NetworkStatsHistory history = mSession.getHistoryIntervalForUid(mTemplate, uid,
@@ -581,7 +592,7 @@
Log.w(TAG, "Error while getting history of uid " + uid, e);
}
}
- mUids = filteredUids.toArray();
+ mUids = CollectionUtils.toIntArray(filteredUids);
mUidOrUidIndex = -1;
stepHistory();
}
diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java
index ca83309..d00de36 100644
--- a/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -18,6 +18,7 @@
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -47,7 +48,6 @@
import android.os.RemoteException;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.DataUnit;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -55,6 +55,7 @@
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* Provides access to network usage history and statistics. Usage data is collected in
@@ -119,7 +120,7 @@
* is reached.
* @hide
*/
- public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2);
+ public static final long MIN_THRESHOLD_BYTES = 2 * 1_048_576L; // 2MiB
private final Context mContext;
private final INetworkStatsService mService;
@@ -139,9 +140,24 @@
mContext = context;
mService = service;
setPollOnOpen(true);
+ setAugmentWithSubscriptionPlan(true);
}
- /** @hide */
+ /**
+ * Set poll on open flag to indicate the poll is needed before service gets statistics
+ * result. This is default enabled. However, for any non-privileged caller, the poll might
+ * be omitted in case of rate limiting.
+ *
+ * @param pollOnOpen true if poll is needed.
+ * @hide
+ */
+ // The system will ignore any non-default values for non-privileged
+ // processes, so processes that don't hold the appropriate permissions
+ // can make no use of this API.
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK})
public void setPollOnOpen(boolean pollOnOpen) {
if (pollOnOpen) {
mFlags |= FLAG_POLL_ON_OPEN;
@@ -170,16 +186,44 @@
}
}
- /** @hide */
- public Bucket querySummaryForDevice(NetworkTemplate template,
- long startTime, long endTime) throws SecurityException, RemoteException {
- Bucket bucket = null;
- NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
- mService);
- bucket = stats.getDeviceSummaryForNetwork();
-
- stats.close();
- return bucket;
+ /**
+ * Query network usage statistics summaries.
+ *
+ * Result is summarised data usage for the whole
+ * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
+ * roaming. This means the bucket's start and end timestamp will be the same as the
+ * 'startTime' and 'endTime' arguments. State is going to be
+ * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
+ * tag {@link NetworkStats.Bucket#TAG_NONE},
+ * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
+ * metered {@link NetworkStats.Bucket#METERED_ALL},
+ * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
+ * This may take a long time, and apps should avoid calling this on their main thread.
+ *
+ * @param template Template used to match networks. See {@link NetworkTemplate}.
+ * @param startTime Start of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @param endTime End of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @return Bucket Summarised data usage.
+ *
+ * @hide
+ */
+ @NonNull
+ @WorkerThread
+ // @SystemApi(client = MODULE_LIBRARIES)
+ public Bucket querySummaryForDevice(@NonNull NetworkTemplate template,
+ long startTime, long endTime) {
+ try {
+ NetworkStats stats =
+ new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
+ Bucket bucket = stats.getDeviceSummaryForNetwork();
+ stats.close();
+ return bucket;
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return null; // To make the compiler happy.
}
/**
@@ -323,14 +367,70 @@
return querySummary(template, startTime, endTime);
}
- /** @hide */
- public NetworkStats querySummary(NetworkTemplate template, long startTime,
- long endTime) throws SecurityException, RemoteException {
- NetworkStats result;
- result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
- result.startSummaryEnumeration();
+ /**
+ * Query network usage statistics summaries.
+ *
+ * The results will only include traffic made by UIDs belonging to the calling user profile.
+ * The results are aggregated over time, so that all buckets will have the same start and
+ * end timestamps as the passed arguments. Not aggregated over state, uid, default network,
+ * metered, or roaming.
+ * This may take a long time, and apps should avoid calling this on their main thread.
+ *
+ * @param template Template used to match networks. See {@link NetworkTemplate}.
+ * @param startTime Start of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @param endTime End of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @return Statistics which is described above.
+ * @hide
+ */
+ @NonNull
+ // @SystemApi(client = MODULE_LIBRARIES)
+ @WorkerThread
+ public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime,
+ long endTime) throws SecurityException {
+ try {
+ NetworkStats result =
+ new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
+ result.startSummaryEnumeration();
+ return result;
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return null; // To make the compiler happy.
+ }
- return result;
+ /**
+ * Query tagged network usage statistics summaries.
+ *
+ * The results will only include tagged traffic made by UIDs belonging to the calling user
+ * profile. The results are aggregated over time, so that all buckets will have the same
+ * start and end timestamps as the passed arguments. Not aggregated over state, uid,
+ * default network, metered, or roaming.
+ * This may take a long time, and apps should avoid calling this on their main thread.
+ *
+ * @param template Template used to match networks. See {@link NetworkTemplate}.
+ * @param startTime Start of period, in milliseconds since the Unix epoch, see
+ * {@link System#currentTimeMillis}.
+ * @param endTime End of period, in milliseconds since the Unix epoch, see
+ * {@link System#currentTimeMillis}.
+ * @return Statistics which is described above.
+ * @hide
+ */
+ @NonNull
+ // @SystemApi(client = MODULE_LIBRARIES)
+ @WorkerThread
+ public NetworkStats queryTaggedSummary(@NonNull NetworkTemplate template, long startTime,
+ long endTime) throws SecurityException {
+ try {
+ NetworkStats result =
+ new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
+ result.startTaggedSummaryEnumeration();
+ return result;
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return null; // To make the compiler happy.
}
/**
@@ -484,6 +584,31 @@
return result;
}
+ /**
+ * Query realtime network usage statistics details with interfaces constrains.
+ * Return snapshot of current UID statistics, including any {@link TrafficStats#UID_TETHERING},
+ * video calling data usage and count of network operations that set by
+ * {@link TrafficStats#incrementOperationCount}. The returned data doesn't include any
+ * statistics that is reported by {@link NetworkStatsProvider}.
+ *
+ * @param requiredIfaces A list of interfaces the stats should be restricted to, or
+ * {@link NetworkStats#INTERFACES_ALL}.
+ *
+ * @hide
+ */
+ //@SystemApi
+ @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+ @NonNull public android.net.NetworkStats getDetailedUidStats(
+ @NonNull Set<String> requiredIfaces) {
+ Objects.requireNonNull(requiredIfaces, "requiredIfaces cannot be null");
+ try {
+ return mService.getDetailedUidStats(requiredIfaces.toArray(new String[0]));
+ } catch (RemoteException e) {
+ if (DBG) Log.d(TAG, "Remote exception when get detailed uid stats");
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/** @hide */
public void registerUsageCallback(NetworkTemplate template, int networkType,
long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
@@ -753,4 +878,83 @@
return msg.getData().getParcelable(key);
}
}
+
+ /**
+ * Mark given UID as being in foreground for stats purposes.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK})
+ public void setUidForeground(int uid, boolean uidForeground) {
+ try {
+ mService.setUidForeground(uid, uidForeground);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Set default value of global alert bytes, the value will be clamped to [128kB, 2MB].
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ Manifest.permission.NETWORK_STACK})
+ public void setDefaultGlobalAlert(long alertBytes) {
+ try {
+ // TODO: Sync internal naming with the API surface.
+ mService.advisePersistThreshold(alertBytes);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Force update of statistics.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK})
+ public void forceUpdate() {
+ try {
+ mService.forceUpdate();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Set the warning and limit to all registered custom network stats providers.
+ * Note that invocation of any interface will be sent to all providers.
+ *
+ * Asynchronicity notes : because traffic may be happening on the device at the same time, it
+ * doesn't make sense to wait for the warning and limit to be set – a caller still wouldn't
+ * know when exactly it was effective. All that can matter is that it's done quickly. Also,
+ * this method can't fail, so there is no status to return. All providers will see the new
+ * values soon.
+ * As such, this method returns immediately and sends the warning and limit to all providers
+ * as soon as possible through a one-way binder call.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK})
+ public void setStatsProviderWarningAndLimitAsync(@NonNull String iface, long warning,
+ long limit) {
+ try {
+ mService.setStatsProviderWarningAndLimitAsync(iface, warning, limit);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/framework-t/src/android/net/EthernetNetworkSpecifier.java b/framework-t/src/android/net/EthernetNetworkSpecifier.java
index 62c5761..925d12b 100644
--- a/framework-t/src/android/net/EthernetNetworkSpecifier.java
+++ b/framework-t/src/android/net/EthernetNetworkSpecifier.java
@@ -23,8 +23,6 @@
import android.os.Parcelable;
import android.text.TextUtils;
-import com.android.internal.util.Preconditions;
-
import java.util.Objects;
/**
@@ -47,7 +45,9 @@
* @param interfaceName Name of the ethernet interface the specifier refers to.
*/
public EthernetNetworkSpecifier(@NonNull String interfaceName) {
- Preconditions.checkStringNotEmpty(interfaceName);
+ if (TextUtils.isEmpty(interfaceName)) {
+ throw new IllegalArgumentException();
+ }
mInterfaceName = interfaceName;
}
diff --git a/framework-t/src/android/net/INetworkStatsService.aidl b/framework-t/src/android/net/INetworkStatsService.aidl
index 12937b5..a4babb5 100644
--- a/framework-t/src/android/net/INetworkStatsService.aidl
+++ b/framework-t/src/android/net/INetworkStatsService.aidl
@@ -94,4 +94,16 @@
/** Registers a network stats provider */
INetworkStatsProviderCallback registerNetworkStatsProvider(String tag,
in INetworkStatsProvider provider);
+
+ /** Mark given UID as being in foreground for stats purposes. */
+ void setUidForeground(int uid, boolean uidForeground);
+
+ /** Advise persistence threshold; may be overridden internally. */
+ void advisePersistThreshold(long thresholdBytes);
+
+ /**
+ * Set the warning and limit to all registered custom network stats providers.
+ * Note that invocation of any interface will be sent to all providers.
+ */
+ void setStatsProviderWarningAndLimitAsync(String iface, long warning, long limit);
}
diff --git a/framework-t/src/android/net/INetworkStatsSession.aidl b/framework-t/src/android/net/INetworkStatsSession.aidl
index dfedf66..babe0bf 100644
--- a/framework-t/src/android/net/INetworkStatsSession.aidl
+++ b/framework-t/src/android/net/INetworkStatsSession.aidl
@@ -46,6 +46,10 @@
*/
@UnsupportedAppUsage
NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
+
+ /** Return network layer usage summary per UID for tagged traffic that matches template. */
+ NetworkStats getTaggedSummaryForAllUid(in NetworkTemplate template, long start, long end);
+
/** Return historical network layer stats for specific UID traffic that matches template. */
@UnsupportedAppUsage
NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java
index 819ac6b..a423783 100644
--- a/framework-t/src/android/net/IpSecManager.java
+++ b/framework-t/src/android/net/IpSecManager.java
@@ -17,6 +17,7 @@
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
@@ -25,7 +26,6 @@
import android.annotation.TestApi;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.net.annotations.PolicyDirection;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -42,6 +42,8 @@
import java.io.FileDescriptor;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
@@ -89,6 +91,11 @@
@SystemApi(client = MODULE_LIBRARIES)
public static final int DIRECTION_FWD = 2;
+ /** @hide */
+ @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PolicyDirection {}
+
/**
* The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
*
diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java
index eb8f43e..8f1115e 100644
--- a/framework-t/src/android/net/NetworkIdentity.java
+++ b/framework-t/src/android/net/NetworkIdentity.java
@@ -21,7 +21,6 @@
import android.annotation.Nullable;
import android.content.Context;
import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
import android.service.NetworkIdentityProto;
import android.telephony.Annotation.NetworkType;
import android.util.proto.ProtoOutputStream;
@@ -228,11 +227,11 @@
final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities());
if (legacyType == TYPE_WIFI) {
- networkId = snapshot.getNetworkCapabilities().getSsid();
- if (networkId == null) {
- final WifiManager wifi = context.getSystemService(WifiManager.class);
- final WifiInfo info = wifi.getConnectionInfo();
- networkId = info != null ? info.getSSID() : null;
+ final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
+ .getTransportInfo();
+ if (transportInfo instanceof WifiInfo) {
+ final WifiInfo info = (WifiInfo) transportInfo;
+ networkId = info != null ? info.getCurrentNetworkKey() : null;
}
}
diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java
index 1986b83..9d532e7 100644
--- a/framework-t/src/android/net/NetworkStats.java
+++ b/framework-t/src/android/net/NetworkStats.java
@@ -31,7 +31,7 @@
import android.util.SparseBooleanArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
+import com.android.net.module.util.CollectionUtils;
import libcore.util.EmptyArray;
@@ -83,10 +83,7 @@
*/
// TODO: Rename TAG_ALL to TAG_ANY.
public static final int TAG_ALL = -1;
- /**
- * {@link #set} value for all sets combined, not including debug sets.
- * @hide
- */
+ /** {@link #set} value for all sets combined, not including debug sets. */
public static final int SET_ALL = -1;
/** {@link #set} value where background data is accounted. */
public static final int SET_DEFAULT = 0;
@@ -114,9 +111,6 @@
SET_ALL,
SET_DEFAULT,
SET_FOREGROUND,
- SET_DEBUG_START,
- SET_DBG_VPN_IN,
- SET_DBG_VPN_OUT
})
public @interface State {
}
@@ -131,10 +125,7 @@
// TODO: Rename TAG_NONE to TAG_ALL.
public static final int TAG_NONE = 0;
- /**
- * {@link #metered} value to account for all metered states.
- * @hide
- */
+ /** {@link #metered} value to account for all metered states. */
public static final int METERED_ALL = -1;
/** {@link #metered} value where native, unmetered data is accounted. */
public static final int METERED_NO = 0;
@@ -152,10 +143,7 @@
}
- /**
- * {@link #roaming} value to account for all roaming states.
- * @hide
- */
+ /** {@link #roaming} value to account for all roaming states. */
public static final int ROAMING_ALL = -1;
/** {@link #roaming} value where native, non-roaming data is accounted. */
public static final int ROAMING_NO = 0;
@@ -172,10 +160,7 @@
public @interface Roaming {
}
- /**
- * {@link #onDefaultNetwork} value to account for all default network states.
- * @hide
- */
+ /** {@link #onDefaultNetwork} value to account for all default network states. */
public static final int DEFAULT_NETWORK_ALL = -1;
/** {@link #onDefaultNetwork} value to account for usage while not the default network. */
public static final int DEFAULT_NETWORK_NO = 0;
@@ -398,6 +383,95 @@
this.operations += another.operations;
}
+ /**
+ * @return interface name of this entry.
+ * @hide
+ */
+ @Nullable public String getIface() {
+ return iface;
+ }
+
+ /**
+ * @return the uid of this entry.
+ */
+ public int getUid() {
+ return uid;
+ }
+
+ /**
+ * @return the set state of this entry. Should be one of the following
+ * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
+ */
+ @State public int getSet() {
+ return set;
+ }
+
+ /**
+ * @return the tag value of this entry.
+ */
+ public int getTag() {
+ return tag;
+ }
+
+ /**
+ * @return the metered state. Should be one of the following
+ * values: {link #METERED_YES}, {link #METERED_NO}.
+ */
+ @Meteredness public int getMetered() {
+ return metered;
+ }
+
+ /**
+ * @return the roaming state. Should be one of the following
+ * values: {link #ROAMING_YES}, {link #ROAMING_NO}.
+ */
+ @Roaming public int getRoaming() {
+ return roaming;
+ }
+
+ /**
+ * @return the default network state. Should be one of the following
+ * values: {link #DEFAULT_NETWORK_YES}, {link #DEFAULT_NETWORK_NO}.
+ */
+ @DefaultNetwork public int getDefaultNetwork() {
+ return defaultNetwork;
+ }
+
+ /**
+ * @return the number of received bytes.
+ */
+ public long getRxBytes() {
+ return rxBytes;
+ }
+
+ /**
+ * @return the number of received packets.
+ */
+ public long getRxPackets() {
+ return rxPackets;
+ }
+
+ /**
+ * @return the number of transmitted bytes.
+ */
+ public long getTxBytes() {
+ return txBytes;
+ }
+
+ /**
+ * @return the number of transmitted packets.
+ */
+ public long getTxPackets() {
+ return txPackets;
+ }
+
+ /**
+ * @return the count of network operations performed for this entry.
+ */
+ public long getOperations() {
+ return operations;
+ }
+
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
@@ -608,7 +682,7 @@
* @hide
*/
@UnsupportedAppUsage
- public Entry getValues(int i, Entry recycle) {
+ public Entry getValues(int i, @Nullable Entry recycle) {
final Entry entry = recycle != null ? recycle : new Entry();
entry.iface = iface[i];
entry.uid = uid[i];
@@ -1185,7 +1259,7 @@
* @hide
*/
public void removeUids(int[] uids) {
- filter(e -> !ArrayUtils.contains(uids, e.uid));
+ filter(e -> !CollectionUtils.contains(uids, e.uid));
}
/**
@@ -1218,7 +1292,7 @@
filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
&& (limitTag == TAG_ALL || limitTag == e.tag)
&& (limitIfaces == INTERFACES_ALL
- || ArrayUtils.contains(limitIfaces, e.iface)));
+ || CollectionUtils.contains(limitIfaces, e.iface)));
}
/**
diff --git a/framework-t/src/android/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java
index 591605d..b64fbdb 100644
--- a/framework-t/src/android/net/NetworkStatsAccess.java
+++ b/framework-t/src/android/net/NetworkStatsAccess.java
@@ -17,6 +17,7 @@
package android.net;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
@@ -106,7 +107,7 @@
/** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
public static @NetworkStatsAccess.Level int checkAccessLevel(
- Context context, int callingUid, String callingPackage) {
+ Context context, int callingPid, int callingUid, String callingPackage) {
final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class);
final TelephonyManager tm = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -123,8 +124,12 @@
final boolean isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage);
final int appId = UserHandle.getAppId(callingUid);
+ final boolean isNetworkStack = context.checkPermission(
+ android.Manifest.permission.NETWORK_STACK, callingPid, callingUid)
+ == PERMISSION_GRANTED;
+
if (hasCarrierPrivileges || isDeviceOwner
- || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) {
+ || appId == Process.SYSTEM_UID || isNetworkStack) {
// 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;
@@ -155,6 +160,8 @@
*/
public static boolean isAccessibleToUser(int uid, int callerUid,
@NetworkStatsAccess.Level int accessLevel) {
+ final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+ final int callerUserId = UserHandle.getUserHandleForUid(callerUid).getIdentifier();
switch (accessLevel) {
case NetworkStatsAccess.Level.DEVICE:
// Device-level access - can access usage for any uid.
@@ -165,13 +172,13 @@
// anonymized uids
return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
|| uid == UID_TETHERING || uid == UID_ALL
- || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
+ || userId == callerUserId;
case NetworkStatsAccess.Level.USER:
// User-level access - can access usage for any app running in the same user, along
// with some special uids (system, removed, or tethering).
return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
|| uid == UID_TETHERING
- || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
+ || userId == callerUserId;
case NetworkStatsAccess.Level.DEFAULT:
default:
// Default access level - can only access one's own usage.
@@ -185,8 +192,8 @@
AppOpsManager appOps = (AppOpsManager) context.getSystemService(
Context.APP_OPS_SERVICE);
- final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
- callingUid, callingPackage);
+ final int mode = appOps.noteOp(AppOpsManager.OPSTR_GET_USAGE_STATS,
+ callingUid, callingPackage, null /* attributionTag */, null /* message */);
if (mode == AppOpsManager.MODE_DEFAULT) {
// The default behavior here is to check if PackageManager has given the app
// permission.
diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java
index 8d1347e..9f9d73f 100644
--- a/framework-t/src/android/net/NetworkStatsCollection.java
+++ b/framework-t/src/android/net/NetworkStatsCollection.java
@@ -40,21 +40,15 @@
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
-import android.util.IntArray;
-import android.util.MathUtils;
+import android.util.IndentingPrintWriter;
+import android.util.Log;
import android.util.Range;
-import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.FastDataInput;
-import com.android.internal.util.FastDataOutput;
import com.android.internal.util.FileRotator;
-import com.android.internal.util.IndentingPrintWriter;
-
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.NetworkStatsUtils;
import libcore.io.IoUtils;
@@ -62,6 +56,7 @@
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
+import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -87,9 +82,6 @@
/** File header magic number: "ANET" */
private static final int FILE_MAGIC = 0x414E4554;
- /** Default buffer size from BufferedInputStream */
- private static final int BUFFER_SIZE = 8192;
-
private static final int VERSION_NETWORK_INIT = 1;
private static final int VERSION_UID_INIT = 1;
@@ -196,11 +188,11 @@
public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel,
final int callerUid) {
- IntArray uids = new IntArray();
+ final ArrayList<Integer> uids = new ArrayList<>();
for (int i = 0; i < mStats.size(); i++) {
final Key key = mStats.keyAt(i);
if (NetworkStatsAccess.isAccessibleToUser(key.uid, callerUid, accessLevel)) {
- int j = uids.binarySearch(key.uid);
+ int j = Collections.binarySearch(uids, new Integer(key.uid));
if (j < 0) {
j = ~j;
@@ -208,7 +200,7 @@
}
}
}
- return uids.toArray();
+ return CollectionUtils.toIntArray(uids);
}
/**
@@ -225,7 +217,8 @@
// 180 days of history should be enough for anyone; if we end up needing
// more, we'll dynamically grow the history object.
- final int bucketEstimate = (int) MathUtils.constrain(((end - start) / mBucketDuration), 0,
+ final int bucketEstimate = (int) NetworkStatsUtils.constrain(
+ ((end - start) / mBucketDuration), 0,
(180 * DateUtils.DAY_IN_MILLIS) / mBucketDuration);
final NetworkStatsHistory combined = new NetworkStatsHistory(
mBucketDuration, bucketEstimate, fields);
@@ -316,7 +309,7 @@
final long deltaTotal = combined.getTotalBytes() - beforeTotal;
if (deltaTotal != 0) {
- Slog.d(TAG, "Augmented network usage by " + deltaTotal + " bytes");
+ Log.d(TAG, "Augmented network usage by " + deltaTotal + " bytes");
}
// Finally we can slice data as originally requested
@@ -442,8 +435,7 @@
@Override
public void read(InputStream in) throws IOException {
- final FastDataInput dataIn = new FastDataInput(in, BUFFER_SIZE);
- read(dataIn);
+ read((DataInput) new DataInputStream(in));
}
private void read(DataInput in) throws IOException {
@@ -482,18 +474,17 @@
@Override
public void write(OutputStream out) throws IOException {
- final FastDataOutput dataOut = new FastDataOutput(out, BUFFER_SIZE);
- write(dataOut);
- dataOut.flush();
+ write((DataOutput) new DataOutputStream(out));
+ out.flush();
}
private void write(DataOutput out) throws IOException {
// cluster key lists grouped by ident
- final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = Maps.newHashMap();
+ final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = new HashMap<>();
for (Key key : mStats.keySet()) {
ArrayList<Key> keys = keysByIdent.get(key.ident);
if (keys == null) {
- keys = Lists.newArrayList();
+ keys = new ArrayList<>();
keysByIdent.put(key.ident, keys);
}
keys.add(key);
@@ -640,12 +631,12 @@
* {@link TrafficStats#UID_REMOVED}.
*/
public void removeUids(int[] uids) {
- final ArrayList<Key> knownKeys = Lists.newArrayList();
+ final ArrayList<Key> knownKeys = new ArrayList<>();
knownKeys.addAll(mStats.keySet());
// migrate all UID stats into special "removed" bucket
for (Key key : knownKeys) {
- if (ArrayUtils.contains(uids, key.uid)) {
+ if (CollectionUtils.contains(uids, key.uid)) {
// only migrate combined TAG_NONE history
if (key.tag == TAG_NONE) {
final NetworkStatsHistory uidHistory = mStats.get(key);
@@ -672,7 +663,7 @@
}
private ArrayList<Key> getSortedKeys() {
- final ArrayList<Key> keys = Lists.newArrayList();
+ final ArrayList<Key> keys = new ArrayList<>();
keys.addAll(mStats.keySet());
Collections.sort(keys);
return keys;
diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java
index 3eef4ee..428bc6d 100644
--- a/framework-t/src/android/net/NetworkStatsHistory.java
+++ b/framework-t/src/android/net/NetworkStatsHistory.java
@@ -28,7 +28,6 @@
import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-import static com.android.internal.util.ArrayUtils.total;
import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
import android.compat.annotation.UnsupportedAppUsage;
@@ -37,10 +36,11 @@
import android.os.Parcelable;
import android.service.NetworkStatsHistoryBucketProto;
import android.service.NetworkStatsHistoryProto;
-import android.util.MathUtils;
+import android.util.IndentingPrintWriter;
import android.util.proto.ProtoOutputStream;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.NetworkStatsUtils;
import libcore.util.EmptyArray;
@@ -174,7 +174,7 @@
txPackets = new long[bucketStart.length];
operations = new long[bucketStart.length];
bucketCount = bucketStart.length;
- totalBytes = total(rxBytes) + total(txBytes);
+ totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
break;
}
case VERSION_ADD_PACKETS:
@@ -189,7 +189,7 @@
txPackets = readVarLongArray(in);
operations = readVarLongArray(in);
bucketCount = bucketStart.length;
- totalBytes = total(rxBytes) + total(txBytes);
+ totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
break;
}
default: {
@@ -267,7 +267,7 @@
} else {
index -= 1;
}
- return MathUtils.constrain(index, 0, bucketCount - 1);
+ return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
}
/**
@@ -281,7 +281,7 @@
} else {
index += 1;
}
- return MathUtils.constrain(index, 0, bucketCount - 1);
+ return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
}
/**
@@ -349,6 +349,9 @@
// create any buckets needed by this range
ensureBuckets(start, end);
+ // Return fast if there is still no entry. This would typically happen when the start,
+ // end or duration are not valid values, e.g. start > end, negative duration value, etc.
+ if (bucketCount == 0) return;
// distribute data usage into buckets
long duration = end - start;
@@ -560,6 +563,9 @@
entry.txPackets = txPackets != null ? 0 : UNKNOWN;
entry.operations = operations != null ? 0 : UNKNOWN;
+ // Return fast if there is no entry.
+ if (bucketCount == 0) return entry;
+
final int startIndex = getIndexAfter(end);
for (int i = startIndex; i >= 0; i--) {
final long curStart = bucketStart[i];
diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
index 5da8e25..e9084b0 100644
--- a/framework-t/src/android/net/NetworkTemplate.java
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -16,6 +16,7 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
@@ -35,12 +36,13 @@
import static android.net.NetworkStats.ROAMING_ALL;
import static android.net.NetworkStats.ROAMING_NO;
import static android.net.NetworkStats.ROAMING_YES;
-import static android.net.wifi.WifiInfo.sanitizeSsid;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.wifi.WifiInfo;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -49,7 +51,7 @@
import android.text.TextUtils;
import android.util.ArraySet;
-import com.android.internal.util.ArrayUtils;
+import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkIdentityUtils;
import com.android.net.module.util.NetworkStatsUtils;
@@ -57,6 +59,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -70,7 +73,7 @@
*
* @hide
*/
-// @SystemApi(client = MODULE_LIBRARIES)
+@SystemApi(client = MODULE_LIBRARIES)
public final class NetworkTemplate implements Parcelable {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -213,11 +216,14 @@
public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
@NetworkType int ratType, int metered) {
if (TextUtils.isEmpty(subscriberId)) {
- return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
- metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+ return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null /* subscriberId */,
+ null /* matchSubscriberIds */,
+ new String[0] /* matchWifiNetworkKeys */, metered, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
- return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
+ return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[] { subscriberId },
+ new String[0] /* matchWifiNetworkKeys */,
metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
@@ -235,7 +241,7 @@
/**
* Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
- * regardless of SSID.
+ * regardless of key of the wifi network.
*
* @hide
*/
@@ -255,33 +261,40 @@
/**
* Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
- * given SSID.
+ * given key of the wifi network.
*
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * to know details about the key.
* @hide
*/
- public static NetworkTemplate buildTemplateWifi(@NonNull String networkId) {
- Objects.requireNonNull(networkId);
+ public static NetworkTemplate buildTemplateWifi(@NonNull String wifiNetworkKey) {
+ Objects.requireNonNull(wifiNetworkKey);
return new NetworkTemplate(MATCH_WIFI, null /* subscriberId */,
new String[] { null } /* matchSubscriberIds */,
- networkId, METERED_ALL, ROAMING_ALL,
+ new String[] { wifiNetworkKey }, METERED_ALL, ROAMING_ALL,
DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL);
}
/**
- * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID,
- * and IMSI.
+ * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given
+ * key of the wifi network and IMSI.
*
- * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code networkId} to get result regardless
- * of SSID.
+ * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code wifiNetworkKey} to get result regardless
+ * of key of the wifi network.
+ *
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * to know details about the key.
+ * @param subscriberId the IMSI associated to this wifi network.
*
* @hide
*/
- public static NetworkTemplate buildTemplateWifi(@Nullable String networkId,
+ public static NetworkTemplate buildTemplateWifi(@Nullable String wifiNetworkKey,
@Nullable String subscriberId) {
return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId },
- networkId, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
+ wifiNetworkKey != null
+ ? new String[] { wifiNetworkKey } : new String[0],
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
@@ -324,7 +337,9 @@
public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
Objects.requireNonNull(subscriberId);
return new NetworkTemplate(MATCH_CARRIER, subscriberId,
- new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL,
+ new String[] { subscriberId },
+ new String[0] /* matchWifiNetworkKeys */,
+ METERED_YES, ROAMING_ALL,
DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
@@ -342,8 +357,8 @@
*/
private final String[] mMatchSubscriberIds;
- // TODO: Change variable name to match the Api surface.
- private final String mNetworkId;
+ @NonNull
+ private final String[] mMatchWifiNetworkKeys;
// Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
private final int mMetered;
@@ -377,18 +392,19 @@
/** @hide */
// TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S)
@UnsupportedAppUsage
- public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
- this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
+ public NetworkTemplate(int matchRule, String subscriberId, String wifiNetworkKey) {
+ this(matchRule, subscriberId, new String[] { subscriberId }, wifiNetworkKey);
}
/** @hide */
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String networkId) {
+ String wifiNetworkKey) {
// Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
// to metered networks. It is now possible to match mobile with any meteredness, but
// in order to preserve backward compatibility of @UnsupportedAppUsage methods, this
//constructor passes METERED_YES for these types.
- this(matchRule, subscriberId, matchSubscriberIds, networkId,
+ this(matchRule, subscriberId, matchSubscriberIds,
+ wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
(matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES
: METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
@@ -397,23 +413,25 @@
/** @hide */
// TODO: Remove it after updating all of the caller.
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String networkId, int metered, int roaming, int defaultNetwork, int subType,
+ String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int subType,
int oemManaged) {
- this(matchRule, subscriberId, matchSubscriberIds, networkId, metered, roaming,
- defaultNetwork, subType, oemManaged,
+ this(matchRule, subscriberId, matchSubscriberIds,
+ wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
+ metered, roaming, defaultNetwork, subType, oemManaged,
NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
/** @hide */
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String networkId, int metered, int roaming, int defaultNetwork, int subType,
- int oemManaged, int subscriberIdMatchRule) {
+ String[] matchWifiNetworkKeys, int metered, int roaming,
+ int defaultNetwork, int subType, int oemManaged, int subscriberIdMatchRule) {
+ Objects.requireNonNull(matchWifiNetworkKeys);
mMatchRule = matchRule;
mSubscriberId = subscriberId;
// TODO: Check whether mMatchSubscriberIds = null or mMatchSubscriberIds = {null} when
// mSubscriberId is null
mMatchSubscriberIds = matchSubscriberIds;
- mNetworkId = networkId;
+ mMatchWifiNetworkKeys = matchWifiNetworkKeys;
mMetered = metered;
mRoaming = roaming;
mDefaultNetwork = defaultNetwork;
@@ -431,7 +449,7 @@
mMatchRule = in.readInt();
mSubscriberId = in.readString();
mMatchSubscriberIds = in.createStringArray();
- mNetworkId = in.readString();
+ mMatchWifiNetworkKeys = in.createStringArray();
mMetered = in.readInt();
mRoaming = in.readInt();
mDefaultNetwork = in.readInt();
@@ -445,7 +463,7 @@
dest.writeInt(mMatchRule);
dest.writeString(mSubscriberId);
dest.writeStringArray(mMatchSubscriberIds);
- dest.writeString(mNetworkId);
+ dest.writeStringArray(mMatchWifiNetworkKeys);
dest.writeInt(mMetered);
dest.writeInt(mRoaming);
dest.writeInt(mDefaultNetwork);
@@ -471,9 +489,7 @@
builder.append(", matchSubscriberIds=").append(
Arrays.toString(NetworkIdentityUtils.scrubSubscriberIds(mMatchSubscriberIds)));
}
- if (mNetworkId != null) {
- builder.append(", networkId=").append(mNetworkId);
- }
+ builder.append(", matchWifiNetworkKeys=").append(Arrays.toString(mMatchWifiNetworkKeys));
if (mMetered != METERED_ALL) {
builder.append(", metered=").append(NetworkStats.meteredToString(mMetered));
}
@@ -497,8 +513,8 @@
@Override
public int hashCode() {
- return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming,
- mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule);
+ return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys),
+ mMetered, mRoaming, mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule);
}
@Override
@@ -507,13 +523,13 @@
final NetworkTemplate other = (NetworkTemplate) obj;
return mMatchRule == other.mMatchRule
&& Objects.equals(mSubscriberId, other.mSubscriberId)
- && Objects.equals(mNetworkId, other.mNetworkId)
&& mMetered == other.mMetered
&& mRoaming == other.mRoaming
&& mDefaultNetwork == other.mDefaultNetwork
&& mSubType == other.mSubType
&& mOemManaged == other.mOemManaged
- && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule;
+ && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule
+ && Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys);
}
return false;
}
@@ -559,6 +575,7 @@
/**
* Get subscriber Id of the template.
+ * @hide
*/
@Nullable
@UnsupportedAppUsage
@@ -575,18 +592,19 @@
}
/**
- * Get Wifi Network Key of the template. See {@link WifiInfo#getCurrentNetworkKey()}.
+ * Get the set of Wifi Network Keys of the template.
+ * See {@link WifiInfo#getCurrentNetworkKey()}.
*/
- @Nullable
- public String getWifiNetworkKey() {
- return mNetworkId;
+ @NonNull
+ public Set<String> getWifiNetworkKeys() {
+ return new ArraySet<>(Arrays.asList(mMatchWifiNetworkKeys));
}
/** @hide */
- // TODO: Remove this and replace all callers with {@link #getWifiNetworkKey()}.
+ // TODO: Remove this and replace all callers with {@link #getWifiNetworkKeys()}.
@Nullable
public String getNetworkId() {
- return mNetworkId;
+ return getWifiNetworkKeys().isEmpty() ? null : getWifiNetworkKeys().iterator().next();
}
/**
@@ -703,28 +721,33 @@
*/
public boolean matchesSubscriberId(@Nullable String subscriberId) {
return mSubscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
- || ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
+ || CollectionUtils.contains(mMatchSubscriberIds, subscriberId);
}
/**
- * Check if network with matching SSID. Returns true when the SSID matches, or when
- * {@code mNetworkId} is {@code WIFI_NETWORK_KEY_ALL}.
+ * Check if network matches key of the wifi network.
+ * Returns true when the key matches, or when {@code mMatchWifiNetworkKeys} is
+ * empty.
+ *
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * to know details about the key.
*/
- private boolean matchesWifiNetworkId(@Nullable String networkId) {
- return Objects.equals(mNetworkId, WIFI_NETWORK_KEY_ALL)
- || Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId));
+ private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) {
+ Objects.requireNonNull(wifiNetworkKey);
+ return CollectionUtils.isEmpty(mMatchWifiNetworkKeys)
+ || CollectionUtils.contains(mMatchWifiNetworkKeys, wifiNetworkKey);
}
/**
- * Check if mobile network with matching IMSI.
+ * Check if mobile network matches IMSI.
*/
private boolean matchesMobile(NetworkIdentity ident) {
if (ident.mType == TYPE_WIMAX) {
// TODO: consider matching against WiMAX subscriber identity
return true;
} else {
- return ident.mType == TYPE_MOBILE && !ArrayUtils.isEmpty(mMatchSubscriberIds)
- && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
+ return ident.mType == TYPE_MOBILE && !CollectionUtils.isEmpty(mMatchSubscriberIds)
+ && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
&& matchesCollapsedRatType(ident);
}
}
@@ -814,7 +837,7 @@
switch (ident.mType) {
case TYPE_WIFI:
return matchesSubscriberId(ident.mSubscriberId)
- && matchesWifiNetworkId(ident.mNetworkId);
+ && matchesWifiNetworkKey(ident.mNetworkId);
default:
return false;
}
@@ -835,8 +858,8 @@
*/
private boolean matchesCarrier(NetworkIdentity ident) {
return ident.mSubscriberId != null
- && !ArrayUtils.isEmpty(mMatchSubscriberIds)
- && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
+ && !CollectionUtils.isEmpty(mMatchSubscriberIds)
+ && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
}
private boolean matchesMobileWildcard(NetworkIdentity ident) {
@@ -953,11 +976,13 @@
if (template.mSubscriberId == null) return template;
for (String[] merged : mergedList) {
- if (ArrayUtils.contains(merged, template.mSubscriberId)) {
+ if (CollectionUtils.contains(merged, template.mSubscriberId)) {
// Requested template subscriber is part of the merge group; return
// a template that matches all merged subscribers.
+ final String[] matchWifiNetworkKeys = template.mMatchWifiNetworkKeys;
return new NetworkTemplate(template.mMatchRule, merged[0], merged,
- template.mNetworkId);
+ CollectionUtils.isEmpty(matchWifiNetworkKeys)
+ ? null : matchWifiNetworkKeys[0]);
}
}
@@ -984,9 +1009,10 @@
private final int mMatchRule;
// Use a SortedSet to provide a deterministic order when fetching the first one.
@NonNull
- private final SortedSet<String> mMatchSubscriberIds = new TreeSet<>();
- @Nullable
- private String mWifiNetworkKey;
+ private final SortedSet<String> mMatchSubscriberIds =
+ new TreeSet<>(Comparator.nullsFirst(Comparator.naturalOrder()));
+ @NonNull
+ private final SortedSet<String> mMatchWifiNetworkKeys = new TreeSet<>();
// Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
private int mMetered;
@@ -1006,7 +1032,6 @@
assertRequestableMatchRule(matchRule);
// Initialize members with default values.
mMatchRule = matchRule;
- mWifiNetworkKey = WIFI_NETWORK_KEY_ALL;
mMetered = METERED_ALL;
mRoaming = ROAMING_ALL;
mDefaultNetwork = DEFAULT_NETWORK_ALL;
@@ -1030,15 +1055,28 @@
}
/**
- * Set the Wifi Network Key.
+ * Set the Wifi Network Keys. Calling this function with an empty set represents
+ * the intention of matching any Wifi Network Key.
*
- * @param wifiNetworkKey the Wifi Network Key, see {@link WifiInfo#getCurrentNetworkKey()}.
- * Or null to match all networks.
+ * @param wifiNetworkKeys the list of Wifi Network Key,
+ * see {@link WifiInfo#getCurrentNetworkKey()}.
+ * Or an empty list to match all networks.
+ * Note that {@code getCurrentNetworkKey()} might get null key
+ * when wifi disconnects. However, the caller should never invoke
+ * this function with a null Wifi Network Key since such statistics
+ * never exists.
* @return this builder.
*/
@NonNull
- public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) {
- mWifiNetworkKey = wifiNetworkKey;
+ public Builder setWifiNetworkKeys(@NonNull Set<String> wifiNetworkKeys) {
+ Objects.requireNonNull(wifiNetworkKeys);
+ for (String key : wifiNetworkKeys) {
+ if (key == null) {
+ throw new IllegalArgumentException("Null is not a valid key");
+ }
+ }
+ mMatchWifiNetworkKeys.clear();
+ mMatchWifiNetworkKeys.addAll(wifiNetworkKeys);
return this;
}
@@ -1122,9 +1160,17 @@
}
private void assertRequestableParameters() {
+ validateWifiNetworkKeys();
// TODO: Check all the input are legitimate.
}
+ private void validateWifiNetworkKeys() {
+ if (mMatchRule != MATCH_WIFI && !mMatchWifiNetworkKeys.isEmpty()) {
+ throw new IllegalArgumentException("Trying to build non wifi match rule: "
+ + mMatchRule + " with wifi network keys");
+ }
+ }
+
/**
* For backward compatibility, deduce match rule to a wildcard match rule
* if the Subscriber Ids are empty.
@@ -1133,7 +1179,7 @@
if (mMatchRule == MATCH_MOBILE && mMatchSubscriberIds.isEmpty()) {
return MATCH_MOBILE_WILDCARD;
} else if (mMatchRule == MATCH_WIFI && mMatchSubscriberIds.isEmpty()
- && mWifiNetworkKey == WIFI_NETWORK_KEY_ALL) {
+ && mMatchWifiNetworkKeys.isEmpty()) {
return MATCH_WIFI_WILDCARD;
}
return mMatchRule;
@@ -1153,8 +1199,8 @@
return new NetworkTemplate(getWildcardDeducedMatchRule(),
mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(),
mMatchSubscriberIds.toArray(new String[0]),
- mWifiNetworkKey, mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged,
- subscriberIdMatchRule);
+ mMatchWifiNetworkKeys.toArray(new String[0]), mMetered, mRoaming,
+ mDefaultNetwork, mRatType, mOemManaged, subscriberIdMatchRule);
}
}
}
diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java
index fa65061..1af32bf 100644
--- a/framework-t/src/android/net/TrafficStats.java
+++ b/framework-t/src/android/net/TrafficStats.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -27,9 +28,8 @@
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Build;
+import android.os.IBinder;
import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.DataUnit;
import com.android.server.NetworkManagementSocketTagger;
@@ -37,6 +37,8 @@
import java.io.FileDescriptor;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketException;
@@ -54,24 +56,25 @@
* use {@link NetworkStatsManager} instead.
*/
public class TrafficStats {
+ private static final String TAG = TrafficStats.class.getSimpleName();
/**
* The return value to indicate that the device does not support the statistic.
*/
public final static int UNSUPPORTED = -1;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long KB_IN_BYTES = 1024;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
- /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
@@ -174,12 +177,25 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
private synchronized static INetworkStatsService getStatsService() {
if (sStatsService == null) {
- sStatsService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+ sStatsService = getStatsBinder();
}
return sStatsService;
}
+ @Nullable
+ private static INetworkStatsService getStatsBinder() {
+ try {
+ final Method getServiceMethod = Class.forName("android.os.ServiceManager")
+ .getDeclaredMethod("getService", new Class[]{String.class});
+ final IBinder binder = (IBinder) getServiceMethod.invoke(
+ null, Context.NETWORK_STATS_SERVICE);
+ return INetworkStatsService.Stub.asInterface(binder);
+ } catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException
+ | InvocationTargetException e) {
+ throw new NullPointerException("Cannot get INetworkStatsService: " + e);
+ }
+ }
+
/**
* Snapshot of {@link NetworkStats} when the currently active profiling
* session started, or {@code null} if no session active.
@@ -266,6 +282,18 @@
}
/**
+ * Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. The tag used internally is well-defined to
+ * distinguish all download provider traffic.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void setThreadStatsTagDownload() {
+ setThreadStatsTag(TAG_SYSTEM_DOWNLOAD);
+ }
+
+ /**
* Get the active tag used when accounting {@link Socket} traffic originating
* from the current thread. Only one active tag per thread is supported.
* {@link #tagSocket(Socket)}.
diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java
index d1e432e..179d945 100644
--- a/service-t/src/com/android/server/IpSecService.java
+++ b/service-t/src/com/android/server/IpSecService.java
@@ -1236,37 +1236,53 @@
int callingUid = Binder.getCallingUid();
UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
final int resourceId = mNextResourceId++;
- FileDescriptor sockFd = null;
+
+ ParcelFileDescriptor pFd = null;
try {
if (!userRecord.mSocketQuotaTracker.isAvailable()) {
return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
}
- sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- mUidFdTagger.tag(sockFd, callingUid);
+ FileDescriptor sockFd = null;
+ try {
+ sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ pFd = ParcelFileDescriptor.dup(sockFd);
+ } finally {
+ IoUtils.closeQuietly(sockFd);
+ }
+ mUidFdTagger.tag(pFd.getFileDescriptor(), callingUid);
// This code is common to both the unspecified and specified port cases
Os.setsockoptInt(
- sockFd,
+ pFd.getFileDescriptor(),
OsConstants.IPPROTO_UDP,
OsConstants.UDP_ENCAP,
OsConstants.UDP_ENCAP_ESPINUDP);
- mNetd.ipSecSetEncapSocketOwner(new ParcelFileDescriptor(sockFd), callingUid);
+ mNetd.ipSecSetEncapSocketOwner(pFd, callingUid);
if (port != 0) {
Log.v(TAG, "Binding to port " + port);
- Os.bind(sockFd, INADDR_ANY, port);
+ Os.bind(pFd.getFileDescriptor(), INADDR_ANY, port);
} else {
- port = bindToRandomPort(sockFd);
+ port = bindToRandomPort(pFd.getFileDescriptor());
}
userRecord.mEncapSocketRecords.put(
resourceId,
new RefcountedResource<EncapSocketRecord>(
- new EncapSocketRecord(resourceId, sockFd, port), binder));
- return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port, sockFd);
+ new EncapSocketRecord(resourceId, pFd.getFileDescriptor(), port),
+ binder));
+ return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port,
+ pFd.getFileDescriptor());
} catch (IOException | ErrnoException e) {
- IoUtils.closeQuietly(sockFd);
+ try {
+ if (pFd != null) {
+ pFd.close();
+ }
+ } catch (IOException ex) {
+ // Nothing can be done at this point
+ Log.e(TAG, "Failed to close pFd.");
+ }
}
// If we make it to here, then something has gone wrong and we couldn't open a socket.
// The only reasonable condition that would cause that is resource unavailable.
diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java
index e6433db..bb123a3 100644
--- a/service-t/src/com/android/server/net/NetworkStatsFactory.java
+++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java
@@ -24,19 +24,19 @@
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.INetd;
import android.net.NetworkStats;
import android.net.UnderlyingNetworkInfo;
-import android.net.util.NetdService;
import android.os.RemoteException;
import android.os.StrictMode;
import android.os.SystemClock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ProcFileReader;
+import com.android.net.module.util.CollectionUtils;
import libcore.io.IoUtils;
@@ -70,7 +70,7 @@
private final boolean mUseBpfStats;
- private INetd mNetdService;
+ private final INetd mNetd;
/**
* Guards persistent data access in this class
@@ -158,12 +158,12 @@
NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces);
}
- public NetworkStatsFactory() {
- this(new File("/proc/"), true);
+ public NetworkStatsFactory(@NonNull INetd netd) {
+ this(new File("/proc/"), true, netd);
}
@VisibleForTesting
- public NetworkStatsFactory(File procRoot, boolean useBpfStats) {
+ public NetworkStatsFactory(File procRoot, boolean useBpfStats, @NonNull INetd netd) {
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
@@ -172,6 +172,7 @@
mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1);
mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
}
+ mNetd = netd;
}
public NetworkStats readBpfNetworkStatsDev() throws IOException {
@@ -298,10 +299,7 @@
// Ask netd to do a active map stats swap. When the binder call successfully returns,
// the system server should be able to safely read and clean the inactive map
// without race problem.
- if (mNetdService == null) {
- mNetdService = NetdService.getInstance();
- }
- mNetdService.trafficSwapActiveStatsMap();
+ mNetd.trafficSwapActiveStatsMap();
}
/**
@@ -434,7 +432,7 @@
entry.txBytes = reader.nextLong();
entry.txPackets = reader.nextLong();
- if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface))
+ if ((limitIfaces == null || CollectionUtils.contains(limitIfaces, entry.iface))
&& (limitUid == UID_ALL || limitUid == entry.uid)
&& (limitTag == TAG_ALL || limitTag == entry.tag)) {
stats.insertEntry(entry);
diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java
index 1a0866d..b57a4f9 100644
--- a/service-t/src/com/android/server/net/NetworkStatsObservers.java
+++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java
@@ -18,8 +18,6 @@
import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
-import static com.android.internal.util.Preconditions.checkArgument;
-
import android.app.usage.NetworkStatsManager;
import android.net.DataUsageRequest;
import android.net.NetworkIdentitySet;
@@ -38,7 +36,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.util.ArrayMap;
-import android.util.Slog;
+import android.util.Log;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -83,7 +81,7 @@
RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid,
accessLevel);
- if (LOGV) Slog.v(TAG, "Registering observer for " + request);
+ if (LOGV) Log.v(TAG, "Registering observer for " + request);
getHandler().sendMessage(mHandler.obtainMessage(MSG_REGISTER, requestInfo));
return request;
}
@@ -116,7 +114,7 @@
if (mHandler == null) {
synchronized (this) {
if (mHandler == null) {
- if (LOGV) Slog.v(TAG, "Creating handler");
+ if (LOGV) Log.v(TAG, "Creating handler");
mHandler = new Handler(getHandlerLooperLocked(), mHandlerCallback);
}
}
@@ -172,15 +170,15 @@
RequestInfo requestInfo;
requestInfo = mDataUsageRequests.get(request.requestId);
if (requestInfo == null) {
- if (LOGV) Slog.v(TAG, "Trying to unregister unknown request " + request);
+ if (LOGV) Log.v(TAG, "Trying to unregister unknown request " + request);
return;
}
if (Process.SYSTEM_UID != callingUid && requestInfo.mCallingUid != callingUid) {
- Slog.w(TAG, "Caller uid " + callingUid + " is not owner of " + request);
+ Log.w(TAG, "Caller uid " + callingUid + " is not owner of " + request);
return;
}
- if (LOGV) Slog.v(TAG, "Unregistering " + request);
+ if (LOGV) Log.v(TAG, "Unregistering " + request);
mDataUsageRequests.remove(request.requestId);
requestInfo.unlinkDeathRecipient();
requestInfo.callCallback(NetworkStatsManager.CALLBACK_RELEASED);
@@ -201,7 +199,7 @@
// Cap the minimum threshold to a safe default to avoid too many callbacks
long thresholdInBytes = Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes);
if (thresholdInBytes < request.thresholdInBytes) {
- Slog.w(TAG, "Threshold was too low for " + request
+ Log.w(TAG, "Threshold was too low for " + request
+ ". Overriding to a safer default of " + thresholdInBytes + " bytes");
}
return new DataUsageRequest(mNextDataUsageRequestId.incrementAndGet(),
@@ -216,7 +214,10 @@
accessLevel);
} else {
// Safety check in case a new access level is added and we forgot to update this
- checkArgument(accessLevel >= NetworkStatsAccess.Level.DEVICESUMMARY);
+ if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) {
+ throw new IllegalArgumentException(
+ "accessLevel " + accessLevel + " is less than DEVICESUMMARY.");
+ }
return new NetworkUsageRequestInfo(this, request, messenger, binder, callingUid,
accessLevel);
}
@@ -255,8 +256,9 @@
@Override
public void binderDied() {
- if (LOGV) Slog.v(TAG, "RequestInfo binderDied("
- + mRequest + ", " + mBinder + ")");
+ if (LOGV) {
+ Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mBinder + ")");
+ }
mStatsObserver.unregister(mRequest, Process.SYSTEM_UID);
callCallback(NetworkStatsManager.CALLBACK_RELEASED);
}
@@ -299,13 +301,13 @@
msg.setData(bundle);
try {
if (LOGV) {
- Slog.v(TAG, "sending notification " + callbackTypeToName(callbackType)
+ Log.v(TAG, "sending notification " + callbackTypeToName(callbackType)
+ " for " + mRequest);
}
mMessenger.send(msg);
} catch (RemoteException e) {
// May occur naturally in the race of binder death.
- Slog.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest);
+ Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest);
}
}
@@ -341,7 +343,7 @@
protected boolean checkStats() {
long bytesSoFar = getTotalBytesForNetwork(mRequest.template);
if (LOGV) {
- Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
+ Log.v(TAG, bytesSoFar + " bytes so far since notification for "
+ mRequest.template);
}
if (bytesSoFar > mRequest.thresholdInBytes) {
@@ -416,7 +418,7 @@
return history.getTotalBytes();
} catch (SecurityException e) {
if (LOGV) {
- Slog.w(TAG, "CallerUid " + mCallingUid + " may have lost access to uid "
+ Log.w(TAG, "CallerUid " + mCallingUid + " may have lost access to uid "
+ uid);
}
return 0;
diff --git a/service-t/src/com/android/server/net/NetworkStatsRecorder.java b/service-t/src/com/android/server/net/NetworkStatsRecorder.java
index 5e27c77..c371f08 100644
--- a/service-t/src/com/android/server/net/NetworkStatsRecorder.java
+++ b/service-t/src/com/android/server/net/NetworkStatsRecorder.java
@@ -32,15 +32,12 @@
import android.os.Binder;
import android.os.DropBoxManager;
import android.service.NetworkStatsRecorderProto;
+import android.util.IndentingPrintWriter;
import android.util.Log;
-import android.util.MathUtils;
-import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.FileRotator;
-import com.android.internal.util.IndentingPrintWriter;
-
-import com.google.android.collect.Sets;
+import com.android.net.module.util.NetworkStatsUtils;
import libcore.io.IoUtils;
@@ -132,8 +129,8 @@
}
public void setPersistThreshold(long thresholdBytes) {
- if (LOGV) Slog.v(TAG, "setPersistThreshold() with " + thresholdBytes);
- mPersistThresholdBytes = MathUtils.constrain(
+ if (LOGV) Log.v(TAG, "setPersistThreshold() with " + thresholdBytes);
+ mPersistThresholdBytes = NetworkStatsUtils.constrain(
thresholdBytes, 1 * KB_IN_BYTES, 100 * MB_IN_BYTES);
}
@@ -185,7 +182,7 @@
}
private NetworkStatsCollection loadLocked(long start, long end) {
- if (LOGD) Slog.d(TAG, "loadLocked() reading from disk for " + mCookie);
+ if (LOGD) Log.d(TAG, "loadLocked() reading from disk for " + mCookie);
final NetworkStatsCollection res = new NetworkStatsCollection(mBucketDuration);
try {
mRotator.readMatching(res, start, end);
@@ -207,7 +204,7 @@
*/
public void recordSnapshotLocked(NetworkStats snapshot,
Map<String, NetworkIdentitySet> ifaceIdent, long currentTimeMillis) {
- final HashSet<String> unknownIfaces = Sets.newHashSet();
+ final HashSet<String> unknownIfaces = new HashSet<>();
// skip recording when snapshot missing
if (snapshot == null) return;
@@ -272,7 +269,7 @@
mLastSnapshot = snapshot;
if (LOGV && unknownIfaces.size() > 0) {
- Slog.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats");
+ Log.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats");
}
}
@@ -296,7 +293,7 @@
public void forcePersistLocked(long currentTimeMillis) {
Objects.requireNonNull(mRotator, "missing FileRotator");
if (mPending.isDirty()) {
- if (LOGD) Slog.d(TAG, "forcePersistLocked() writing for " + mCookie);
+ if (LOGD) Log.d(TAG, "forcePersistLocked() writing for " + mCookie);
try {
mRotator.rewriteActive(mPendingRewriter, currentTimeMillis);
mRotator.maybeRotate(currentTimeMillis);
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 2beca73..0abc523 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -25,7 +25,6 @@
import static android.content.Intent.EXTRA_UID;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
-import static android.net.NetworkStack.checkNetworkStackPermission;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.IFACE_VT;
@@ -43,9 +42,9 @@
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
-import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.TrafficStats.KB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.net.TrafficStats.UID_TETHERING;
import static android.net.TrafficStats.UNSUPPORTED;
import static android.os.Trace.TRACE_TAG_NETWORK;
import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
@@ -72,7 +71,7 @@
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport;
-import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
+import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
@@ -90,13 +89,14 @@
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.DataUsageRequest;
-import android.net.INetworkManagementEventObserver;
+import android.net.INetd;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkIdentity;
import android.net.NetworkIdentitySet;
+import android.net.NetworkPolicyManager;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkStateSnapshot;
@@ -107,13 +107,14 @@
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TelephonyNetworkSpecifier;
+import android.net.TetherStatsParcel;
+import android.net.TetheringManager;
import android.net.TrafficStats;
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
import android.net.netstats.provider.INetworkStatsProvider;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
-import android.os.BestClock;
import android.os.Binder;
import android.os.DropBoxManager;
import android.os.Environment;
@@ -121,12 +122,12 @@
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
@@ -141,28 +142,29 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
+import android.util.IndentingPrintWriter;
import android.util.Log;
-import android.util.MathUtils;
-import android.util.Slog;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.DumpUtils;
import com.android.internal.util.FileRotator;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
+import com.android.net.module.util.BestClock;
import com.android.net.module.util.BinderUtils;
-import com.android.server.EventLogTags;
-import com.android.server.LocalServices;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.NetworkStatsUtils;
+import com.android.net.module.util.PermissionUtils;
import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.Clock;
import java.time.ZoneOffset;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -206,8 +208,15 @@
private static final String TAG_NETSTATS_ERROR = "netstats_error";
+ /**
+ * EventLog tags used when logging into the event log. Note the values must be sync with
+ * frameworks/base/services/core/java/com/android/server/EventLogTags.logtags to get correct
+ * name translation.
+ */
+ private static final int LOG_TAG_NETSTATS_MOBILE_SAMPLE = 51100;
+ private static final int LOG_TAG_NETSTATS_WIFI_SAMPLE = 51101;
+
private final Context mContext;
- private final INetworkManagementService mNetworkManager;
private final NetworkStatsFactory mStatsFactory;
private final AlarmManager mAlarmManager;
private final Clock mClock;
@@ -222,6 +231,9 @@
private final ContentObserver mContentObserver;
private final ContentResolver mContentResolver;
+ protected INetd mNetd;
+ private final AlertObserver mAlertObserver = new AlertObserver();
+
@VisibleForTesting
public static final String ACTION_NETWORK_STATS_POLL =
"com.android.server.action.NETWORK_STATS_POLL";
@@ -404,19 +416,20 @@
}
}
- public static NetworkStatsService create(Context context,
- INetworkManagementService networkManager) {
+ /** Creates a new NetworkStatsService */
+ public static NetworkStatsService create(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock =
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
-
- final NetworkStatsService service = new NetworkStatsService(context, networkManager,
+ final INetd netd = INetd.Stub.asInterface(
+ (IBinder) context.getSystemService(Context.NETD_SERVICE));
+ final NetworkStatsService service = new NetworkStatsService(context,
+ INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
alarmManager, wakeLock, getDefaultClock(),
- new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(),
+ new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(netd),
new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(),
new Dependencies());
- service.registerLocalService();
return service;
}
@@ -424,14 +437,12 @@
// This must not be called outside of tests, even within the same package, as this constructor
// does not register the local service. Use the create() helper above.
@VisibleForTesting
- NetworkStatsService(Context context, INetworkManagementService networkManager,
- AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
- NetworkStatsSettings settings, NetworkStatsFactory factory,
- NetworkStatsObservers statsObservers, File systemDir, File baseDir,
- @NonNull Dependencies deps) {
+ NetworkStatsService(Context context, INetd netd, AlarmManager alarmManager,
+ PowerManager.WakeLock wakeLock, Clock clock, NetworkStatsSettings settings,
+ NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir,
+ File baseDir, @NonNull Dependencies deps) {
mContext = Objects.requireNonNull(context, "missing Context");
- mNetworkManager = Objects.requireNonNull(networkManager,
- "missing INetworkManagementService");
+ mNetd = Objects.requireNonNull(netd, "missing Netd");
mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
mClock = Objects.requireNonNull(clock, "missing Clock");
mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
@@ -446,7 +457,7 @@
handlerThread.start();
mHandler = new NetworkStatsHandler(handlerThread.getLooper());
mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
- mHandler.getLooper(), new HandlerExecutor(mHandler), this);
+ new HandlerExecutor(mHandler), this);
mContentResolver = mContext.getContentResolver();
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
mNetworkStatsSubscriptionsMonitor);
@@ -472,11 +483,10 @@
*/
@NonNull
public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context,
- @NonNull Looper looper, @NonNull Executor executor,
- @NonNull NetworkStatsService service) {
+ @NonNull Executor executor, @NonNull NetworkStatsService service) {
// TODO: Update RatType passively in NSS, instead of querying into the monitor
// when notifyNetworkStatus.
- return new NetworkStatsSubscriptionsMonitor(context, looper, executor,
+ return new NetworkStatsSubscriptionsMonitor(context, executor,
(subscriberId, type) -> service.handleOnCollapsedRatTypeChanged());
}
@@ -500,9 +510,24 @@
}
}
- private void registerLocalService() {
- LocalServices.addService(NetworkStatsManagerInternal.class,
- new NetworkStatsManagerInternalImpl());
+ /**
+ * Observer that watches for {@link INetdUnsolicitedEventListener} alerts.
+ */
+ @VisibleForTesting
+ public class AlertObserver extends BaseNetdUnsolicitedEventListener {
+ @Override
+ public void onQuotaLimitReached(@NonNull String alertName, @NonNull String ifName) {
+ PermissionUtils.enforceNetworkStackPermission(mContext);
+
+ if (LIMIT_GLOBAL_ALERT.equals(alertName)) {
+ // kick off background poll to collect network stats unless there is already
+ // such a call pending; UID stats are handled during normal polling interval.
+ if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
+ mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
+ mSettings.getPollDelay());
+ }
+ }
+ }
}
public void systemReady() {
@@ -529,8 +554,9 @@
}
// watch for tethering changes
- final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
- mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler);
+ final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
+ tetheringManager.registerTetheringEventCallback(
+ new HandlerExecutor(mHandler), mTetherListener);
// listen for periodic polling events
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
@@ -549,9 +575,9 @@
mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
try {
- mNetworkManager.registerObserver(mAlertObserver);
- } catch (RemoteException e) {
- // ignored; service lives in system_server
+ mNetd.registerUnsolicitedEventListener(mAlertObserver);
+ } catch (RemoteException | ServiceSpecificException e) {
+ Log.wtf(TAG, "Error registering event listener :", e);
}
// schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}.
@@ -586,7 +612,8 @@
@GuardedBy("mStatsLock")
private void shutdownLocked() {
- mContext.unregisterReceiver(mTetherReceiver);
+ final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
+ tetheringManager.unregisterTetheringEventCallback(mTetherListener);
mContext.unregisterReceiver(mPollReceiver);
mContext.unregisterReceiver(mRemovedReceiver);
mContext.unregisterReceiver(mUserReceiver);
@@ -638,15 +665,15 @@
}
/**
- * Register for a global alert that is delivered through {@link INetworkManagementEventObserver}
+ * Register for a global alert that is delivered through {@link AlertObserver}
* or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has
* been transferred.
*/
private void registerGlobalAlert() {
try {
- mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
+ mNetd.bandwidthSetGlobalAlert(mGlobalAlertBytes);
} catch (IllegalStateException e) {
- Slog.w(TAG, "problem registering for global alert: " + e);
+ Log.w(TAG, "problem registering for global alert: " + e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
@@ -655,8 +682,6 @@
@Override
public INetworkStatsSession openSession() {
- // NOTE: if callers want to get non-augmented data, they should go
- // through the public API
return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null);
}
@@ -682,12 +707,25 @@
return now - lastCallTime < POLL_RATE_LIMIT_MS;
}
- private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
+ private int restrictFlagsForCaller(int flags) {
+ // All non-privileged callers are not allowed to turn off POLL_ON_OPEN.
+ final boolean isPrivileged = PermissionUtils.checkAnyPermissionOf(mContext,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK);
+ if (!isPrivileged) {
+ flags |= NetworkStatsManager.FLAG_POLL_ON_OPEN;
+ }
+ // Non-system uids are rate limited for POLL_ON_OPEN.
final int callingUid = Binder.getCallingUid();
- final int usedFlags = isRateLimitedForPoll(callingUid)
+ flags = isRateLimitedForPoll(callingUid)
? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
: flags;
- if ((usedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
+ return flags;
+ }
+
+ private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
+ final int restrictedFlags = restrictFlagsForCaller(flags);
+ if ((restrictedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
| NetworkStatsManager.FLAG_POLL_FORCE)) != 0) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -701,7 +739,7 @@
// for its lifetime; when caller closes only weak references remain.
return new INetworkStatsSession.Stub() {
- private final int mCallingUid = callingUid;
+ private final int mCallingUid = Binder.getCallingUid();
private final String mCallingPackage = callingPackage;
private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
callingPackage);
@@ -735,21 +773,21 @@
@Override
public NetworkStats getDeviceSummaryForNetwork(
NetworkTemplate template, long start, long end) {
- return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
- mCallingUid);
+ return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
+ mAccessLevel, mCallingUid);
}
@Override
public NetworkStats getSummaryForNetwork(
NetworkTemplate template, long start, long end) {
- return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
- mCallingUid);
+ return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
+ mAccessLevel, mCallingUid);
}
@Override
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
- return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel,
- mCallingUid);
+ return internalGetHistoryForNetwork(template, restrictedFlags, fields,
+ mAccessLevel, mCallingUid);
}
@Override
@@ -765,8 +803,18 @@
}
return stats;
} catch (NullPointerException e) {
- // TODO: Track down and fix the cause of this crash and remove this catch block.
- Slog.wtf(TAG, "NullPointerException in getSummaryForAllUid", e);
+ throw e;
+ }
+ }
+
+ @Override
+ public NetworkStats getTaggedSummaryForAllUid(
+ NetworkTemplate template, long start, long end) {
+ try {
+ final NetworkStats tagStats = getUidTagComplete()
+ .getSummary(template, start, end, mAccessLevel, mCallingUid);
+ return tagStats;
+ } catch (NullPointerException e) {
throw e;
}
}
@@ -811,7 +859,7 @@
private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
return NetworkStatsAccess.checkAccessLevel(
- mContext, Binder.getCallingUid(), callingPackage);
+ mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
}
/**
@@ -823,15 +871,15 @@
SubscriptionPlan plan = null;
if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0
&& mSettings.getAugmentEnabled()) {
- if (LOGD) Slog.d(TAG, "Resolving plan for " + template);
+ if (LOGD) Log.d(TAG, "Resolving plan for " + template);
final long token = Binder.clearCallingIdentity();
try {
- plan = LocalServices.getService(NetworkPolicyManagerInternal.class)
+ plan = mContext.getSystemService(NetworkPolicyManager.class)
.getSubscriptionPlan(template);
} finally {
Binder.restoreCallingIdentity(token);
}
- if (LOGD) Slog.d(TAG, "Resolved to plan " + plan);
+ if (LOGD) Log.d(TAG, "Resolved to plan " + plan);
}
return plan;
}
@@ -876,8 +924,6 @@
private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
assertSystemReady();
- // NOTE: if callers want to get non-augmented data, they should go
- // through the public API
return internalGetSummaryForNetwork(template,
NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end,
NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes();
@@ -923,6 +969,7 @@
@Override
public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
+ enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
try {
final String[] ifacesToQuery =
mStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
@@ -936,7 +983,7 @@
@Override
public String[] getMobileIfaces() {
// TODO (b/192758557): Remove debug log.
- if (ArrayUtils.contains(mMobileIfaces, null)) {
+ if (CollectionUtils.contains(mMobileIfaces, null)) {
throw new NullPointerException(
"null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
}
@@ -966,7 +1013,8 @@
}
@VisibleForTesting
- void setUidForeground(int uid, boolean uidForeground) {
+ public void setUidForeground(int uid, boolean uidForeground) {
+ PermissionUtils.enforceNetworkStackPermission(mContext);
synchronized (mStatsLock) {
final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
@@ -985,7 +1033,7 @@
@NonNull NetworkStateSnapshot[] networkStates,
@Nullable String activeIface,
@NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) {
- checkNetworkStackPermission(mContext);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
final long token = Binder.clearCallingIdentity();
try {
@@ -1002,7 +1050,7 @@
@Override
public void forceUpdate() {
- mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
final long token = Binder.clearCallingIdentity();
try {
@@ -1012,11 +1060,14 @@
}
}
- private void advisePersistThreshold(long thresholdBytes) {
+ /** Advise persistence threshold; may be overridden internally. */
+ public void advisePersistThreshold(long thresholdBytes) {
+ PermissionUtils.enforceNetworkStackPermission(mContext);
// clamp threshold into safe range
- mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
+ mPersistThreshold = NetworkStatsUtils.constrain(thresholdBytes,
+ 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
if (LOGV) {
- Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
+ Log.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
+ mPersistThreshold);
}
@@ -1153,14 +1204,15 @@
}
/**
- * Receiver that watches for {@link Tethering} to claim interface pairs.
+ * Listener that watches for {@link TetheringManager} to claim interface pairs.
*/
- private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- performPoll(FLAG_PERSIST_NETWORK);
- }
- };
+ private final TetheringManager.TetheringEventCallback mTetherListener =
+ new TetheringManager.TetheringEventCallback() {
+ @Override
+ public void onUpstreamChanged(@Nullable Network network) {
+ performPoll(FLAG_PERSIST_NETWORK);
+ }
+ };
private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
@Override
@@ -1200,13 +1252,13 @@
// On background handler thread, and USER_REMOVED is protected
// broadcast.
- final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- if (userId == -1) return;
+ final UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
+ if (userHandle == null) return;
synchronized (mStatsLock) {
mWakeLock.acquire();
try {
- removeUserLocked(userId);
+ removeUserLocked(userHandle);
} finally {
mWakeLock.release();
}
@@ -1225,26 +1277,6 @@
};
/**
- * Observer that watches for {@link INetworkManagementService} alerts.
- */
- private final INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
- @Override
- public void limitReached(String limitName, String iface) {
- // only someone like NMS should be calling us
- NetworkStack.checkNetworkStackPermission(mContext);
-
- if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
- // kick off background poll to collect network stats unless there is already
- // such a call pending; UID stats are handled during normal polling interval.
- if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
- mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
- mSettings.getPollDelay());
- }
- }
- }
- };
-
- /**
* Handle collapsed RAT type changed event.
*/
@VisibleForTesting
@@ -1279,7 +1311,7 @@
private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks,
@NonNull NetworkStateSnapshot[] snapshots) {
if (!mSystemReady) return;
- if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()");
+ if (LOGV) Log.v(TAG, "handleNotifyNetworkStatusLocked()");
// take one last stats snapshot before updating iface mapping. this
// isn't perfect, since the kernel may already be counting traffic from
@@ -1303,7 +1335,8 @@
final int displayTransport =
getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes());
final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport);
- final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.getNetwork());
+ final boolean isDefault = CollectionUtils.contains(
+ mDefaultNetworks, snapshot.getNetwork());
final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED
: getSubTypeForStateSnapshot(snapshot);
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
@@ -1386,7 +1419,7 @@
mMobileIfaces = mobileIfaces.toArray(new String[0]);
// TODO (b/192758557): Remove debug log.
- if (ArrayUtils.contains(mMobileIfaces, null)) {
+ if (CollectionUtils.contains(mMobileIfaces, null)) {
throw new NullPointerException(
"null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
}
@@ -1401,7 +1434,7 @@
if (spec instanceof TelephonyNetworkSpecifier) {
return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
} else {
- Slog.wtf(TAG, "getSubIdForState invalid NetworkSpecifier");
+ Log.wtf(TAG, "getSubIdForState invalid NetworkSpecifier");
return INVALID_SUBSCRIPTION_ID;
}
}
@@ -1485,7 +1518,7 @@
try {
recordSnapshotLocked(currentTime);
} catch (IllegalStateException e) {
- Slog.w(TAG, "problem reading network stats: " + e);
+ Log.w(TAG, "problem reading network stats: " + e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
@@ -1510,7 +1543,7 @@
@GuardedBy("mStatsLock")
private void performPollLocked(int flags) {
if (!mSystemReady) return;
- if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
+ if (LOGV) Log.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked");
final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
@@ -1608,7 +1641,7 @@
xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
- EventLogTags.writeNetstatsMobileSample(
+ EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
@@ -1620,7 +1653,7 @@
xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
- EventLogTags.writeNetstatsWifiSample(
+ EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
@@ -1632,7 +1665,7 @@
*/
@GuardedBy("mStatsLock")
private void removeUidsLocked(int... uids) {
- if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
+ if (LOGV) Log.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
// Perform one last poll before removing
performPollLocked(FLAG_PERSIST_ALL);
@@ -1650,73 +1683,40 @@
* Clean up {@link #mUidRecorder} after user is removed.
*/
@GuardedBy("mStatsLock")
- private void removeUserLocked(int userId) {
- if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
+ private void removeUserLocked(@NonNull UserHandle userHandle) {
+ if (LOGV) Log.v(TAG, "removeUserLocked() for UserHandle=" + userHandle);
// Build list of UIDs that we should clean up
- int[] uids = new int[0];
+ final ArrayList<Integer> uids = new ArrayList<>();
final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
PackageManager.MATCH_ANY_USER
| PackageManager.MATCH_DISABLED_COMPONENTS);
for (ApplicationInfo app : apps) {
- final int uid = UserHandle.getUid(userId, app.uid);
- uids = ArrayUtils.appendInt(uids, uid);
+ final int uid = userHandle.getUid(app.uid);
+ uids.add(uid);
}
- removeUidsLocked(uids);
+ removeUidsLocked(CollectionUtils.toIntArray(uids));
}
- private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal {
- @Override
- public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
- Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkTotalBytes");
- try {
- return NetworkStatsService.this.getNetworkTotalBytes(template, start, end);
- } finally {
- Trace.traceEnd(TRACE_TAG_NETWORK);
- }
+ /**
+ * Set the warning and limit to all registered custom network stats providers.
+ * Note that invocation of any interface will be sent to all providers.
+ */
+ public void setStatsProviderWarningAndLimitAsync(
+ @NonNull String iface, long warning, long limit) {
+ PermissionUtils.enforceNetworkStackPermission(mContext);
+ if (LOGV) {
+ Log.v(TAG, "setStatsProviderWarningAndLimitAsync("
+ + iface + "," + warning + "," + limit + ")");
}
-
- @Override
- public NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
- Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkUidBytes");
- try {
- return NetworkStatsService.this.getNetworkUidBytes(template, start, end);
- } finally {
- Trace.traceEnd(TRACE_TAG_NETWORK);
- }
- }
-
- @Override
- public void setUidForeground(int uid, boolean uidForeground) {
- NetworkStatsService.this.setUidForeground(uid, uidForeground);
- }
-
- @Override
- public void advisePersistThreshold(long thresholdBytes) {
- NetworkStatsService.this.advisePersistThreshold(thresholdBytes);
- }
-
- @Override
- public void forceUpdate() {
- NetworkStatsService.this.forceUpdate();
- }
-
- @Override
- public void setStatsProviderWarningAndLimitAsync(
- @NonNull String iface, long warning, long limit) {
- if (LOGV) {
- Slog.v(TAG, "setStatsProviderWarningAndLimitAsync("
- + iface + "," + warning + "," + limit + ")");
- }
- invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface,
- warning, limit));
- }
+ invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface,
+ warning, limit));
}
@Override
protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
- if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
+ if (!PermissionUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
long duration = DateUtils.DAY_IN_MILLIS;
final HashSet<String> argSet = new HashSet<String>();
@@ -1777,15 +1777,15 @@
pw.println("Configs:");
pw.increaseIndent();
- pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled());
+ pw.print(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled());
pw.println();
pw.decreaseIndent();
pw.println("Active interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveIfaces.size(); i++) {
- pw.printPair("iface", mActiveIfaces.keyAt(i));
- pw.printPair("ident", mActiveIfaces.valueAt(i));
+ pw.print("iface", mActiveIfaces.keyAt(i));
+ pw.print("ident", mActiveIfaces.valueAt(i));
pw.println();
}
pw.decreaseIndent();
@@ -1793,8 +1793,8 @@
pw.println("Active UID interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveUidIfaces.size(); i++) {
- pw.printPair("iface", mActiveUidIfaces.keyAt(i));
- pw.printPair("ident", mActiveUidIfaces.valueAt(i));
+ pw.print("iface", mActiveUidIfaces.keyAt(i));
+ pw.print("ident", mActiveUidIfaces.valueAt(i));
pw.println();
}
pw.decreaseIndent();
@@ -1867,7 +1867,7 @@
@GuardedBy("mStatsLock")
private void dumpProtoLocked(FileDescriptor fd) {
- final ProtoOutputStream proto = new ProtoOutputStream(fd);
+ final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd));
// TODO Right now it writes all history. Should it limit to the "since-boot" log?
@@ -1954,13 +1954,29 @@
*/
// TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded
// tethering stats.
- private NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
+ private @NonNull NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
+ // We only need to return per-UID stats. Per-device stats are already counted by
+ // interface counters.
+ if (how != STATS_PER_UID) {
+ return new NetworkStats(SystemClock.elapsedRealtime(), 0);
+ }
+
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
try {
- return mNetworkManager.getNetworkStatsTethering(how);
+ final TetherStatsParcel[] tetherStatsParcels = mNetd.tetherGetStats();
+ for (TetherStatsParcel tetherStats : tetherStatsParcels) {
+ try {
+ stats.combineValues(new NetworkStats.Entry(tetherStats.iface, UID_TETHERING,
+ SET_DEFAULT, TAG_NONE, tetherStats.rxBytes, tetherStats.rxPackets,
+ tetherStats.txBytes, tetherStats.txPackets, 0L));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalStateException("invalid tethering stats " + e);
+ }
+ }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e);
- return new NetworkStats(0L, 10);
}
+ return stats;
}
// TODO: It is copied from ConnectivityService, consider refactor these check permission
@@ -1999,10 +2015,12 @@
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
Objects.requireNonNull(provider, "provider is null");
Objects.requireNonNull(tag, "tag is null");
+ final NetworkPolicyManager netPolicyManager = mContext
+ .getSystemService(NetworkPolicyManager.class);
try {
NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl(
tag, provider, mStatsProviderSem, mAlertObserver,
- mStatsProviderCbList);
+ mStatsProviderCbList, netPolicyManager);
mStatsProviderCbList.add(callback);
Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid="
+ getCallingUid() + "/" + getCallingPid());
@@ -2042,8 +2060,9 @@
@NonNull final INetworkStatsProvider mProvider;
@NonNull private final Semaphore mSemaphore;
- @NonNull final INetworkManagementEventObserver mAlertObserver;
+ @NonNull final AlertObserver mAlertObserver;
@NonNull final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList;
+ @NonNull final NetworkPolicyManager mNetworkPolicyManager;
@NonNull private final Object mProviderStatsLock = new Object();
@@ -2056,8 +2075,9 @@
NetworkStatsProviderCallbackImpl(
@NonNull String tag, @NonNull INetworkStatsProvider provider,
@NonNull Semaphore semaphore,
- @NonNull INetworkManagementEventObserver alertObserver,
- @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList)
+ @NonNull AlertObserver alertObserver,
+ @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList,
+ @NonNull NetworkPolicyManager networkPolicyManager)
throws RemoteException {
mTag = tag;
mProvider = provider;
@@ -2065,6 +2085,7 @@
mSemaphore = semaphore;
mAlertObserver = alertObserver;
mStatsProviderCbList = cbList;
+ mNetworkPolicyManager = networkPolicyManager;
}
@NonNull
@@ -2104,15 +2125,14 @@
// This binder object can only have been obtained by a process that holds
// NETWORK_STATS_PROVIDER. Thus, no additional permission check is required.
BinderUtils.withCleanCallingIdentity(() ->
- mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
+ mAlertObserver.onQuotaLimitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
}
@Override
public void notifyWarningOrLimitReached() {
Log.d(TAG, mTag + ": notifyWarningOrLimitReached");
BinderUtils.withCleanCallingIdentity(() ->
- LocalServices.getService(NetworkPolicyManagerInternal.class)
- .onStatsProviderWarningOrLimitReached(mTag));
+ mNetworkPolicyManager.notifyStatsProviderWarningOrLimitReached());
}
@Override
diff --git a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index 5646c75..4875f1c 100644
--- a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -18,22 +18,23 @@
import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA;
import static android.net.NetworkTemplate.getCollapsedRatType;
+import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED;
+import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
import android.annotation.NonNull;
import android.content.Context;
-import android.os.Looper;
import android.telephony.Annotation;
-import android.telephony.NetworkRegistrationInfo;
-import android.telephony.PhoneStateListener;
-import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyDisplayInfo;
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;
+import com.android.net.module.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
@@ -64,7 +65,7 @@
private final Delegate mDelegate;
/**
- * Receivers that watches for {@link ServiceState} changes for each subscription, to
+ * Receivers that watches for {@link TelephonyDisplayInfo} changes for each subscription, to
* monitor the transitioning between Radio Access Technology(RAT) types for each sub.
*/
@NonNull
@@ -79,9 +80,9 @@
@NonNull
private final Executor mExecutor;
- NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Looper looper,
+ NetworkStatsSubscriptionsMonitor(@NonNull Context context,
@NonNull Executor executor, @NonNull Delegate delegate) {
- super(looper);
+ super();
mSubscriptionManager = (SubscriptionManager) context.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -99,35 +100,36 @@
// 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);
- });
+ final List<Pair<Integer, String>> filteredNewSubs = new ArrayList<>();
+ for (final int subId : newSubs) {
+ final String subscriberId =
+ mTeleManager.createForSubscriptionId(subId).getSubscriberId();
+ if (!TextUtils.isEmpty(subscriberId)) {
+ filteredNewSubs.add(new Pair(subId, subscriberId));
+ }
+ }
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) {
+ if (CollectionUtils.any(mRatListeners, it -> it.equalsKey(sub.first, sub.second))) {
continue;
}
- final RatTypeListener listener =
- new RatTypeListener(mExecutor, this, sub.first, sub.second);
+ final RatTypeListener listener = new RatTypeListener(this, sub.first, sub.second);
mRatListeners.add(listener);
// Register listener to the telephony manager that associated with specific sub.
mTeleManager.createForSubscriptionId(sub.first)
- .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
+ .registerTelephonyCallback(mExecutor, listener);
Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + sub.first);
}
for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
// If there is no subId and IMSI matched the listener, removes it.
- if (CollectionUtils.find(filteredNewSubs,
- it -> listener.equalsKey(it.first, it.second)) == null) {
+ if (!CollectionUtils.any(filteredNewSubs,
+ it -> listener.equalsKey(it.first, it.second))) {
handleRemoveRatTypeListener(listener);
}
}
@@ -148,9 +150,10 @@
* @return collapsed RatType for the given subscriberId
*/
public int getRatTypeForSubscriberId(@NonNull String subscriberId) {
- final RatTypeListener match = CollectionUtils.find(mRatListeners,
+ final int index = CollectionUtils.indexOf(mRatListeners,
it -> TextUtils.equals(subscriberId, it.mSubscriberId));
- return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ return index != -1 ? mRatListeners.get(index).mLastCollapsedRatType
+ : TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
/**
@@ -173,7 +176,7 @@
private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) {
mTeleManager.createForSubscriptionId(listener.mSubId)
- .listen(listener, PhoneStateListener.LISTEN_NONE);
+ .unregisterTelephonyCallback(listener);
Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId);
mRatListeners.remove(listener);
@@ -183,7 +186,8 @@
listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN);
}
- static class RatTypeListener extends PhoneStateListener {
+ static class RatTypeListener extends TelephonyCallback
+ implements TelephonyCallback.DisplayInfoListener {
// Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}.
@NonNull
private final int mSubId;
@@ -197,29 +201,27 @@
@NonNull
private final NetworkStatsSubscriptionsMonitor mMonitor;
- RatTypeListener(@NonNull Executor executor,
- @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId,
+ RatTypeListener(@NonNull NetworkStatsSubscriptionsMonitor monitor, int subId,
@NonNull String subscriberId) {
- super(executor);
mSubId = subId;
mSubscriberId = subscriberId;
mMonitor = monitor;
}
@Override
- public void onServiceStateChanged(@NonNull ServiceState ss) {
+ public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) {
// In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony
// would report RAT = 5G_NR.
// However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and
// network allocates a secondary 5G cell so telephony reports RAT = LTE along with
// NR state as connected. In such case, attributes the data usage to NR.
// See b/160727498.
- final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE
- || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA)
- && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED;
+ final boolean is5GNsa = displayInfo.getNetworkType() == NETWORK_TYPE_LTE
+ && (displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_NSA
+ || displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_ADVANCED);
final int networkType =
- (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType());
+ (is5GNsa ? NETWORK_TYPE_5G_NSA : displayInfo.getNetworkType());
final int collapsedRatType = getCollapsedRatType(networkType);
if (collapsedRatType == mLastCollapsedRatType) return;