Merge "Monitor interface added and update bpf interface map"
diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp
index d3d8bba..223bdcd 100644
--- a/framework-t/Sources.bp
+++ b/framework-t/Sources.bp
@@ -129,6 +129,11 @@
"src/android/net/EthernetNetworkSpecifier.java",
"src/android/net/IEthernetManager.aidl",
"src/android/net/IEthernetServiceListener.aidl",
+ "src/android/net/IInternalNetworkManagementListener.aidl",
+ "src/android/net/InternalNetworkUpdateRequest.java",
+ "src/android/net/InternalNetworkUpdateRequest.aidl",
+ "src/android/net/InternalNetworkManagementException.java",
+ "src/android/net/InternalNetworkManagementException.aidl",
"src/android/net/ITetheredInterfaceCallback.aidl",
],
path: "src",
diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java
index 4b906c9..8813f98 100644
--- a/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -17,6 +17,8 @@
package android.app.usage;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import android.Manifest;
import android.annotation.NonNull;
@@ -55,7 +57,6 @@
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
@@ -125,6 +126,19 @@
private final Context mContext;
private final INetworkStatsService mService;
+ /**
+ * Type constants for reading different types of Data Usage.
+ * @hide
+ */
+ // @SystemApi(client = MODULE_LIBRARIES)
+ public static final String PREFIX_DEV = "dev";
+ /** @hide */
+ public static final String PREFIX_XT = "xt";
+ /** @hide */
+ public static final String PREFIX_UID = "uid";
+ /** @hide */
+ public static final String PREFIX_UID_TAG = "uid_tag";
+
/** @hide */
public static final int FLAG_POLL_ON_OPEN = 1 << 0;
/** @hide */
@@ -143,6 +157,11 @@
setAugmentWithSubscriptionPlan(true);
}
+ /** @hide */
+ public INetworkStatsService getBinder() {
+ return mService;
+ }
+
/**
* 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
@@ -211,9 +230,10 @@
*/
@NonNull
@WorkerThread
- // @SystemApi(client = MODULE_LIBRARIES)
+ @SystemApi(client = MODULE_LIBRARIES)
public Bucket querySummaryForDevice(@NonNull NetworkTemplate template,
long startTime, long endTime) {
+ Objects.requireNonNull(template);
try {
NetworkStats stats =
new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
@@ -385,10 +405,11 @@
* @hide
*/
@NonNull
- // @SystemApi(client = MODULE_LIBRARIES)
+ @SystemApi(client = MODULE_LIBRARIES)
@WorkerThread
public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime,
long endTime) throws SecurityException {
+ Objects.requireNonNull(template);
try {
NetworkStats result =
new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
@@ -418,10 +439,11 @@
* @hide
*/
@NonNull
- // @SystemApi(client = MODULE_LIBRARIES)
+ @SystemApi(client = MODULE_LIBRARIES)
@WorkerThread
public NetworkStats queryTaggedSummary(@NonNull NetworkTemplate template, long startTime,
long endTime) throws SecurityException {
+ Objects.requireNonNull(template);
try {
NetworkStats result =
new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
@@ -453,10 +475,11 @@
* @hide
*/
@NonNull
- // @SystemApi(client = MODULE_LIBRARIES)
+ @SystemApi(client = MODULE_LIBRARIES)
@WorkerThread
public NetworkStats queryDetailsForDevice(@NonNull NetworkTemplate template,
long startTime, long endTime) {
+ Objects.requireNonNull(template);
try {
final NetworkStats result =
new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
@@ -580,10 +603,11 @@
* @hide
*/
@NonNull
- // @SystemApi(client = MODULE_LIBRARIES)
+ @SystemApi(client = MODULE_LIBRARIES)
@WorkerThread
public NetworkStats queryDetailsForUidTagState(@NonNull NetworkTemplate template,
long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
+ Objects.requireNonNull(template);
try {
final NetworkStats result = new NetworkStats(
mContext, template, mFlags, startTime, endTime, mService);
@@ -652,26 +676,49 @@
}
/**
- * 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}.
+ * Query realtime mobile network usage statistics.
*
- * @param requiredIfaces A list of interfaces the stats should be restricted to, or
- * {@link NetworkStats#INTERFACES_ALL}.
+ * Return a snapshot of current UID network statistics, as it applies
+ * to the mobile radios of the device. The snapshot will include any
+ * tethering traffic, video calling data usage and count of
+ * network operations set by {@link TrafficStats#incrementOperationCount}
+ * made over a mobile radio.
+ * The snapshot will not include any statistics that cannot be seen by
+ * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
*
* @hide
*/
- //@SystemApi
+ @SystemApi
@RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
- @NonNull public android.net.NetworkStats getDetailedUidStats(
- @NonNull Set<String> requiredIfaces) {
- Objects.requireNonNull(requiredIfaces, "requiredIfaces cannot be null");
+ @NonNull public android.net.NetworkStats getMobileUidStats() {
try {
- return mService.getDetailedUidStats(requiredIfaces.toArray(new String[0]));
+ return mService.getUidStatsForTransport(TRANSPORT_CELLULAR);
} catch (RemoteException e) {
- if (DBG) Log.d(TAG, "Remote exception when get detailed uid stats");
+ if (DBG) Log.d(TAG, "Remote exception when get Mobile uid stats");
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Query realtime Wi-Fi network usage statistics.
+ *
+ * Return a snapshot of current UID network statistics, as it applies
+ * to the Wi-Fi radios of the device. The snapshot will include any
+ * tethering traffic, video calling data usage and count of
+ * network operations set by {@link TrafficStats#incrementOperationCount}
+ * made over a Wi-Fi radio.
+ * The snapshot will not include any statistics that cannot be seen by
+ * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+ @NonNull public android.net.NetworkStats getWifiUidStats() {
+ try {
+ return mService.getUidStatsForTransport(TRANSPORT_WIFI);
+ } catch (RemoteException e) {
+ if (DBG) Log.d(TAG, "Remote exception when get WiFi uid stats");
throw e.rethrowFromSystemServer();
}
}
diff --git a/framework-t/src/android/net/INetworkStatsService.aidl b/framework-t/src/android/net/INetworkStatsService.aidl
index a4babb5..da0aa99 100644
--- a/framework-t/src/android/net/INetworkStatsService.aidl
+++ b/framework-t/src/android/net/INetworkStatsService.aidl
@@ -49,14 +49,8 @@
@UnsupportedAppUsage
NetworkStats getDataLayerSnapshotForUid(int uid);
- /** Get a detailed snapshot of stats since boot for all UIDs.
- *
- * <p>Results will not always be limited to stats on requiredIfaces when specified: stats for
- * interfaces stacked on the specified interfaces, or for interfaces on which the specified
- * interfaces are stacked on, will also be included.
- * @param requiredIfaces Interface names to get data for, or {@link NetworkStats#INTERFACES_ALL}.
- */
- NetworkStats getDetailedUidStats(in String[] requiredIfaces);
+ /** Get the transport NetworkStats for all UIDs since boot. */
+ NetworkStats getUidStatsForTransport(int transport);
/** Return set of any ifaces associated with mobile networks since boot. */
@UnsupportedAppUsage
diff --git a/core/java/android/net/InternalNetworkManagementException.aidl b/framework-t/src/android/net/InternalNetworkManagementException.aidl
similarity index 100%
rename from core/java/android/net/InternalNetworkManagementException.aidl
rename to framework-t/src/android/net/InternalNetworkManagementException.aidl
diff --git a/core/java/android/net/InternalNetworkManagementException.java b/framework-t/src/android/net/InternalNetworkManagementException.java
similarity index 100%
rename from core/java/android/net/InternalNetworkManagementException.java
rename to framework-t/src/android/net/InternalNetworkManagementException.java
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.aidl b/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl
similarity index 100%
rename from core/java/android/net/InternalNetworkUpdateRequest.aidl
rename to framework-t/src/android/net/InternalNetworkUpdateRequest.aidl
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/framework-t/src/android/net/InternalNetworkUpdateRequest.java
similarity index 100%
rename from core/java/android/net/InternalNetworkUpdateRequest.java
rename to framework-t/src/android/net/InternalNetworkUpdateRequest.java
diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java
index 04d1d68..d3d5a08 100644
--- a/framework-t/src/android/net/NetworkIdentity.java
+++ b/framework-t/src/android/net/NetworkIdentity.java
@@ -16,18 +16,29 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.service.NetworkIdentityProto;
-import android.telephony.Annotation.NetworkType;
+import android.telephony.Annotation;
+import android.telephony.TelephonyManager;
import android.util.proto.ProtoOutputStream;
+import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.NetworkIdentityUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Objects;
@@ -37,11 +48,24 @@
*
* @hide
*/
-public class NetworkIdentity implements Comparable<NetworkIdentity> {
+@SystemApi(client = MODULE_LIBRARIES)
+public class NetworkIdentity {
private static final String TAG = "NetworkIdentity";
+ /** @hide */
+ // TODO: Remove this after migrating all callers to use
+ // {@link NetworkTemplate#NETWORK_TYPE_ALL} instead.
public static final int SUBTYPE_COMBINED = -1;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "OEM_MANAGED_" }, flag = true, value = {
+ NetworkTemplate.OEM_MANAGED_NO,
+ NetworkTemplate.OEM_MANAGED_PAID,
+ NetworkTemplate.OEM_MANAGED_PRIVATE
+ })
+ public @interface OemManaged{}
+
/**
* Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}.
* @hide
@@ -51,29 +75,32 @@
* Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
* @hide
*/
- public static final int OEM_PAID = 0x1;
+ public static final int OEM_PAID = 1 << 0;
/**
* Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
* @hide
*/
- public static final int OEM_PRIVATE = 0x2;
+ public static final int OEM_PRIVATE = 1 << 1;
+
+ private static final long SUPPORTED_OEM_MANAGED_TYPES = OEM_PAID | OEM_PRIVATE;
final int mType;
- final int mSubType;
+ final int mRatType;
final String mSubscriberId;
- final String mNetworkId;
+ final String mWifiNetworkKey;
final boolean mRoaming;
final boolean mMetered;
final boolean mDefaultNetwork;
final int mOemManaged;
+ /** @hide */
public NetworkIdentity(
- int type, int subType, String subscriberId, String networkId, boolean roaming,
- boolean metered, boolean defaultNetwork, int oemManaged) {
+ int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey,
+ boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged) {
mType = type;
- mSubType = subType;
+ mRatType = ratType;
mSubscriberId = subscriberId;
- mNetworkId = networkId;
+ mWifiNetworkKey = wifiNetworkKey;
mRoaming = roaming;
mMetered = metered;
mDefaultNetwork = defaultNetwork;
@@ -82,7 +109,7 @@
@Override
public int hashCode() {
- return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered,
+ return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered,
mDefaultNetwork, mOemManaged);
}
@@ -90,9 +117,9 @@
public boolean equals(@Nullable Object obj) {
if (obj instanceof NetworkIdentity) {
final NetworkIdentity ident = (NetworkIdentity) obj;
- return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
+ return mType == ident.mType && mRatType == ident.mRatType && mRoaming == ident.mRoaming
&& Objects.equals(mSubscriberId, ident.mSubscriberId)
- && Objects.equals(mNetworkId, ident.mNetworkId)
+ && Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey)
&& mMetered == ident.mMetered
&& mDefaultNetwork == ident.mDefaultNetwork
&& mOemManaged == ident.mOemManaged;
@@ -104,18 +131,18 @@
public String toString() {
final StringBuilder builder = new StringBuilder("{");
builder.append("type=").append(mType);
- builder.append(", subType=");
- if (mSubType == SUBTYPE_COMBINED) {
+ builder.append(", ratType=");
+ if (mRatType == NETWORK_TYPE_ALL) {
builder.append("COMBINED");
} else {
- builder.append(mSubType);
+ builder.append(mRatType);
}
if (mSubscriberId != null) {
builder.append(", subscriberId=")
.append(NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
}
- if (mNetworkId != null) {
- builder.append(", networkId=").append(mNetworkId);
+ if (mWifiNetworkKey != null) {
+ builder.append(", wifiNetworkKey=").append(mWifiNetworkKey);
}
if (mRoaming) {
builder.append(", ROAMING");
@@ -153,12 +180,13 @@
}
}
+ /** @hide */
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
proto.write(NetworkIdentityProto.TYPE, mType);
- // Not dumping mSubType, subtypes are no longer supported.
+ // TODO: dump mRatType as well.
proto.write(NetworkIdentityProto.ROAMING, mRoaming);
proto.write(NetworkIdentityProto.METERED, mMetered);
@@ -168,77 +196,99 @@
proto.end(start);
}
+ /** Get the network type of this instance. */
public int getType() {
return mType;
}
- public int getSubType() {
- return mSubType;
+ /** Get the Radio Access Technology(RAT) type of this instance. */
+ public int getRatType() {
+ return mRatType;
}
+ /** Get the Subscriber Id of this instance. */
+ @Nullable
public String getSubscriberId() {
return mSubscriberId;
}
- public String getNetworkId() {
- return mNetworkId;
+ /** Get the Wifi Network Key of this instance. See {@link WifiInfo#getNetworkKey()}. */
+ @Nullable
+ public String getWifiNetworkKey() {
+ return mWifiNetworkKey;
}
+ /** @hide */
+ // TODO: Remove this function after all callers are removed.
public boolean getRoaming() {
return mRoaming;
}
+ /** Return whether this network is roaming. */
+ public boolean isRoaming() {
+ return mRoaming;
+ }
+
+ /** @hide */
+ // TODO: Remove this function after all callers are removed.
public boolean getMetered() {
return mMetered;
}
+ /** Return whether this network is metered. */
+ public boolean isMetered() {
+ return mMetered;
+ }
+
+ /** @hide */
+ // TODO: Remove this function after all callers are removed.
public boolean getDefaultNetwork() {
return mDefaultNetwork;
}
+ /** Return whether this network is the default network. */
+ public boolean isDefaultNetwork() {
+ return mDefaultNetwork;
+ }
+
+ /** Get the OEM managed type of this instance. */
public int getOemManaged() {
return mOemManaged;
}
/**
- * Build a {@link NetworkIdentity} from the given {@link NetworkStateSnapshot} and
- * {@code subType}, assuming that any mobile networks are using the current IMSI.
- * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_*
- * constants, or {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not.
+ * Assemble a {@link NetworkIdentity} from the passed arguments.
+ *
+ * This methods builds an identity based on the capabilities of the network in the
+ * snapshot and other passed arguments. The identity is used as a key to record data usage.
+ *
+ * @param snapshot the snapshot of network state. See {@link NetworkStateSnapshot}.
+ * @param defaultNetwork whether the network is a default network.
+ * @param ratType the Radio Access Technology(RAT) type of the network. Or
+ * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable.
+ * See {@code TelephonyManager.NETWORK_TYPE_*}.
+ * @hide
+ * @deprecated See {@link NetworkIdentity.Builder}.
*/
+ // TODO: Remove this after all callers are migrated to use new Api.
+ @Deprecated
+ @NonNull
public static NetworkIdentity buildNetworkIdentity(Context context,
- NetworkStateSnapshot snapshot, boolean defaultNetwork, @NetworkType int subType) {
- final int legacyType = snapshot.getLegacyType();
-
- final String subscriberId = snapshot.getSubscriberId();
- String networkId = null;
- boolean roaming = !snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
- boolean metered = !(snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
- || snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
-
- final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities());
-
- if (legacyType == TYPE_WIFI) {
- final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
- .getTransportInfo();
- if (transportInfo instanceof WifiInfo) {
- final WifiInfo info = (WifiInfo) transportInfo;
- networkId = info != null ? info.getCurrentNetworkKey() : null;
- }
+ @NonNull NetworkStateSnapshot snapshot,
+ boolean defaultNetwork, @Annotation.NetworkType int ratType) {
+ final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
+ .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork);
+ if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) {
+ builder.setRatType(ratType);
}
-
- return new NetworkIdentity(legacyType, subType, subscriberId, networkId, roaming, metered,
- defaultNetwork, oemManaged);
+ return builder.build();
}
/**
* Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}.
* @hide
*/
- public static int getOemBitfield(NetworkCapabilities nc) {
+ public static int getOemBitfield(@NonNull NetworkCapabilities nc) {
int oemManaged = OEM_NONE;
if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) {
@@ -251,30 +301,265 @@
return oemManaged;
}
- @Override
- public int compareTo(NetworkIdentity another) {
- int res = Integer.compare(mType, another.mType);
+ /** @hide */
+ public static int compare(@NonNull NetworkIdentity left, @NonNull NetworkIdentity right) {
+ Objects.requireNonNull(right);
+ int res = Integer.compare(left.mType, right.mType);
if (res == 0) {
- res = Integer.compare(mSubType, another.mSubType);
+ res = Integer.compare(left.mRatType, right.mRatType);
}
- if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) {
- res = mSubscriberId.compareTo(another.mSubscriberId);
+ if (res == 0 && left.mSubscriberId != null && right.mSubscriberId != null) {
+ res = left.mSubscriberId.compareTo(right.mSubscriberId);
}
- if (res == 0 && mNetworkId != null && another.mNetworkId != null) {
- res = mNetworkId.compareTo(another.mNetworkId);
+ if (res == 0 && left.mWifiNetworkKey != null && right.mWifiNetworkKey != null) {
+ res = left.mWifiNetworkKey.compareTo(right.mWifiNetworkKey);
}
if (res == 0) {
- res = Boolean.compare(mRoaming, another.mRoaming);
+ res = Boolean.compare(left.mRoaming, right.mRoaming);
}
if (res == 0) {
- res = Boolean.compare(mMetered, another.mMetered);
+ res = Boolean.compare(left.mMetered, right.mMetered);
}
if (res == 0) {
- res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork);
+ res = Boolean.compare(left.mDefaultNetwork, right.mDefaultNetwork);
}
if (res == 0) {
- res = Integer.compare(mOemManaged, another.mOemManaged);
+ res = Integer.compare(left.mOemManaged, right.mOemManaged);
}
return res;
}
+
+ /**
+ * Builder class for {@link NetworkIdentity}.
+ */
+ public static final class Builder {
+ // Need to be synchronized with ConnectivityManager.
+ // TODO: Use {@link ConnectivityManager#MAX_NETWORK_TYPE} when this file is in the module.
+ private static final int MAX_NETWORK_TYPE = 18; // TYPE_TEST
+ private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
+
+ private int mType;
+ private int mRatType;
+ private String mSubscriberId;
+ private String mWifiNetworkKey;
+ private boolean mRoaming;
+ private boolean mMetered;
+ private boolean mDefaultNetwork;
+ private int mOemManaged;
+
+ /**
+ * Creates a new Builder.
+ */
+ public Builder() {
+ // Initialize with default values. Will be overwritten by setters.
+ mType = ConnectivityManager.TYPE_NONE;
+ mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
+ mSubscriberId = null;
+ mWifiNetworkKey = null;
+ mRoaming = false;
+ mMetered = false;
+ mDefaultNetwork = false;
+ mOemManaged = NetworkTemplate.OEM_MANAGED_NO;
+ }
+
+ /**
+ * Add an {@link NetworkStateSnapshot} into the {@link NetworkIdentity} instance.
+ * This is a useful shorthand that will read from the snapshot and set the
+ * following fields, if they are set in the snapshot :
+ * - type
+ * - subscriberId
+ * - roaming
+ * - metered
+ * - oemManaged
+ * - wifiNetworkKey
+ *
+ * @param snapshot The target {@link NetworkStateSnapshot} object.
+ * @return The builder object.
+ */
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @NonNull
+ public Builder setNetworkStateSnapshot(@NonNull NetworkStateSnapshot snapshot) {
+ setType(snapshot.getLegacyType());
+
+ setSubscriberId(snapshot.getSubscriberId());
+ setRoaming(!snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING));
+ setMetered(!(snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+ || snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED)));
+
+ setOemManaged(getOemBitfield(snapshot.getNetworkCapabilities()));
+
+ if (mType == TYPE_WIFI) {
+ final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
+ .getTransportInfo();
+ if (transportInfo instanceof WifiInfo) {
+ final WifiInfo info = (WifiInfo) transportInfo;
+ setWifiNetworkKey(info.getNetworkKey());
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Set the network type of the network.
+ *
+ * @param type the network type. See {@link ConnectivityManager#TYPE_*}.
+ *
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setType(int type) {
+ // Include TYPE_NONE for compatibility, type field might not be filled by some
+ // networks such as test networks.
+ if ((type < MIN_NETWORK_TYPE || MAX_NETWORK_TYPE < type)
+ && type != ConnectivityManager.TYPE_NONE) {
+ throw new IllegalArgumentException("Invalid network type: " + type);
+ }
+ mType = type;
+ return this;
+ }
+
+ /**
+ * Set the Radio Access Technology(RAT) type of the network.
+ *
+ * No RAT type is specified by default. Call clearRatType to reset.
+ *
+ * @param ratType the Radio Access Technology(RAT) type if applicable. See
+ * {@code TelephonyManager.NETWORK_TYPE_*}.
+ *
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setRatType(@Annotation.NetworkType int ratType) {
+ if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType)
+ && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
+ throw new IllegalArgumentException("Invalid ratType " + ratType);
+ }
+ mRatType = ratType;
+ return this;
+ }
+
+ /**
+ * Clear the Radio Access Technology(RAT) type of the network.
+ *
+ * @return this builder.
+ */
+ @NonNull
+ public Builder clearRatType() {
+ mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
+ return this;
+ }
+
+ /**
+ * Set the Subscriber Id.
+ *
+ * @param subscriberId the Subscriber Id of the network. Or null if not applicable.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setSubscriberId(@Nullable String subscriberId) {
+ mSubscriberId = subscriberId;
+ return this;
+ }
+
+ /**
+ * Set the Wifi Network Key.
+ *
+ * @param wifiNetworkKey Wifi Network Key of the network,
+ * see {@link WifiInfo#getNetworkKey()}.
+ * Or null if not applicable.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) {
+ mWifiNetworkKey = wifiNetworkKey;
+ return this;
+ }
+
+ /**
+ * Set whether this network is roaming.
+ *
+ * This field is false by default. Call with false to reset.
+ *
+ * @param roaming the roaming status of the network.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setRoaming(boolean roaming) {
+ mRoaming = roaming;
+ return this;
+ }
+
+ /**
+ * Set whether this network is metered.
+ *
+ * This field is false by default. Call with false to reset.
+ *
+ * @param metered the meteredness of the network.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setMetered(boolean metered) {
+ mMetered = metered;
+ return this;
+ }
+
+ /**
+ * Set whether this network is the default network.
+ *
+ * This field is false by default. Call with false to reset.
+ *
+ * @param defaultNetwork the default network status of the network.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setDefaultNetwork(boolean defaultNetwork) {
+ mDefaultNetwork = defaultNetwork;
+ return this;
+ }
+
+ /**
+ * Set the OEM managed type.
+ *
+ * @param oemManaged Type of OEM managed network or unmanaged networks.
+ * See {@code NetworkTemplate#OEM_MANAGED_*}.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setOemManaged(@OemManaged int oemManaged) {
+ // Assert input does not contain illegal oemManage bits.
+ if ((~SUPPORTED_OEM_MANAGED_TYPES & oemManaged) != 0) {
+ throw new IllegalArgumentException("Invalid value for OemManaged : " + oemManaged);
+ }
+ mOemManaged = oemManaged;
+ return this;
+ }
+
+ private void ensureValidParameters() {
+ // Assert non-mobile network cannot have a ratType.
+ if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) {
+ throw new IllegalArgumentException(
+ "Invalid ratType " + mRatType + " for type " + mType);
+ }
+
+ // Assert non-wifi network cannot have a wifi network key.
+ if (mType != TYPE_WIFI && mWifiNetworkKey != null) {
+ throw new IllegalArgumentException("Invalid wifi network key for type " + mType);
+ }
+ }
+
+ /**
+ * Builds the instance of the {@link NetworkIdentity}.
+ *
+ * @return the built instance of {@link NetworkIdentity}.
+ */
+ @NonNull
+ public NetworkIdentity build() {
+ ensureValidParameters();
+ return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey,
+ mRoaming, mMetered, mDefaultNetwork, mOemManaged);
+ }
+ }
}
diff --git a/framework-t/src/android/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java
index abbebef..dfa347f 100644
--- a/framework-t/src/android/net/NetworkIdentitySet.java
+++ b/framework-t/src/android/net/NetworkIdentitySet.java
@@ -18,6 +18,7 @@
import static android.net.ConnectivityManager.TYPE_MOBILE;
+import android.annotation.NonNull;
import android.service.NetworkIdentitySetProto;
import android.util.proto.ProtoOutputStream;
@@ -25,6 +26,8 @@
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
/**
* Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
@@ -32,8 +35,7 @@
*
* @hide
*/
-public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements
- Comparable<NetworkIdentitySet> {
+public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_ROAMING = 2;
private static final int VERSION_ADD_NETWORK_ID = 3;
@@ -41,9 +43,19 @@
private static final int VERSION_ADD_DEFAULT_NETWORK = 5;
private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
+ /**
+ * Construct a {@link NetworkIdentitySet} object.
+ */
public NetworkIdentitySet() {
+ super();
}
+ /** @hide */
+ public NetworkIdentitySet(@NonNull Set<NetworkIdentity> ident) {
+ super(ident);
+ }
+
+ /** @hide */
public NetworkIdentitySet(DataInput in) throws IOException {
final int version = in.readInt();
final int size = in.readInt();
@@ -52,7 +64,7 @@
final int ignored = in.readInt();
}
final int type = in.readInt();
- final int subType = in.readInt();
+ final int ratType = in.readInt();
final String subscriberId = readOptionalString(in);
final String networkId;
if (version >= VERSION_ADD_NETWORK_ID) {
@@ -91,63 +103,73 @@
oemNetCapabilities = NetworkIdentity.OEM_NONE;
}
- add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered,
+ add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered,
defaultNetwork, oemNetCapabilities));
}
}
/**
* Method to serialize this object into a {@code DataOutput}.
+ * @hide
*/
public void writeToStream(DataOutput out) throws IOException {
out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK);
out.writeInt(size());
for (NetworkIdentity ident : this) {
out.writeInt(ident.getType());
- out.writeInt(ident.getSubType());
+ out.writeInt(ident.getRatType());
writeOptionalString(out, ident.getSubscriberId());
- writeOptionalString(out, ident.getNetworkId());
- out.writeBoolean(ident.getRoaming());
- out.writeBoolean(ident.getMetered());
- out.writeBoolean(ident.getDefaultNetwork());
+ writeOptionalString(out, ident.getWifiNetworkKey());
+ out.writeBoolean(ident.isRoaming());
+ out.writeBoolean(ident.isMetered());
+ out.writeBoolean(ident.isDefaultNetwork());
out.writeInt(ident.getOemManaged());
}
}
- /** @return whether any {@link NetworkIdentity} in this set is considered metered. */
+ /**
+ * @return whether any {@link NetworkIdentity} in this set is considered metered.
+ * @hide
+ */
public boolean isAnyMemberMetered() {
if (isEmpty()) {
return false;
}
for (NetworkIdentity ident : this) {
- if (ident.getMetered()) {
+ if (ident.isMetered()) {
return true;
}
}
return false;
}
- /** @return whether any {@link NetworkIdentity} in this set is considered roaming. */
+ /**
+ * @return whether any {@link NetworkIdentity} in this set is considered roaming.
+ * @hide
+ */
public boolean isAnyMemberRoaming() {
if (isEmpty()) {
return false;
}
for (NetworkIdentity ident : this) {
- if (ident.getRoaming()) {
+ if (ident.isRoaming()) {
return true;
}
}
return false;
}
- /** @return whether any {@link NetworkIdentity} in this set is considered on the default
- network. */
+ /**
+ * @return whether any {@link NetworkIdentity} in this set is considered on the default
+ * network.
+ * @hide
+ */
public boolean areAllMembersOnDefaultNetwork() {
if (isEmpty()) {
return true;
}
for (NetworkIdentity ident : this) {
- if (!ident.getDefaultNetwork()) {
+ if (!ident.isDefaultNetwork()) {
return false;
}
}
@@ -171,18 +193,20 @@
}
}
- @Override
- public int compareTo(NetworkIdentitySet another) {
- if (isEmpty()) return -1;
- if (another.isEmpty()) return 1;
+ public static int compare(@NonNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right) {
+ Objects.requireNonNull(left);
+ Objects.requireNonNull(right);
+ if (left.isEmpty()) return -1;
+ if (right.isEmpty()) return 1;
- final NetworkIdentity ident = iterator().next();
- final NetworkIdentity anotherIdent = another.iterator().next();
- return ident.compareTo(anotherIdent);
+ final NetworkIdentity leftIdent = left.iterator().next();
+ final NetworkIdentity rightIdent = right.iterator().next();
+ return NetworkIdentity.compare(leftIdent, rightIdent);
}
/**
* Method to dump this object into proto debug file.
+ * @hide
*/
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java
index 9f9d73f..58ca21f 100644
--- a/framework-t/src/android/net/NetworkStatsCollection.java
+++ b/framework-t/src/android/net/NetworkStatsCollection.java
@@ -32,6 +32,8 @@
import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.os.Binder;
import android.service.NetworkStatsCollectionKeyProto;
import android.service.NetworkStatsCollectionProto;
@@ -70,6 +72,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.Objects;
+import java.util.Set;
/**
* Collection of {@link NetworkStatsHistory}, stored based on combined key of
@@ -77,6 +80,7 @@
*
* @hide
*/
+// @SystemApi(client = MODULE_LIBRARIES)
public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer {
private static final String TAG = NetworkStatsCollection.class.getSimpleName();
/** File header magic number: "ANET" */
@@ -100,15 +104,23 @@
private long mTotalBytes;
private boolean mDirty;
+ /**
+ * Construct a {@link NetworkStatsCollection} object.
+ *
+ * @param bucketDuration duration of the buckets in this object, in milliseconds.
+ * @hide
+ */
public NetworkStatsCollection(long bucketDuration) {
mBucketDuration = bucketDuration;
reset();
}
+ /** @hide */
public void clear() {
reset();
}
+ /** @hide */
public void reset() {
mStats.clear();
mStartMillis = Long.MAX_VALUE;
@@ -117,6 +129,7 @@
mDirty = false;
}
+ /** @hide */
public long getStartMillis() {
return mStartMillis;
}
@@ -124,6 +137,7 @@
/**
* Return first atomic bucket in this collection, which is more conservative
* than {@link #mStartMillis}.
+ * @hide
*/
public long getFirstAtomicBucketMillis() {
if (mStartMillis == Long.MAX_VALUE) {
@@ -133,26 +147,32 @@
}
}
+ /** @hide */
public long getEndMillis() {
return mEndMillis;
}
+ /** @hide */
public long getTotalBytes() {
return mTotalBytes;
}
+ /** @hide */
public boolean isDirty() {
return mDirty;
}
+ /** @hide */
public void clearDirty() {
mDirty = false;
}
+ /** @hide */
public boolean isEmpty() {
return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE;
}
+ /** @hide */
@VisibleForTesting
public long roundUp(long time) {
if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
@@ -168,6 +188,7 @@
}
}
+ /** @hide */
@VisibleForTesting
public long roundDown(long time) {
if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
@@ -182,10 +203,12 @@
}
}
+ /** @hide */
public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) {
return getRelevantUids(accessLevel, Binder.getCallingUid());
}
+ /** @hide */
public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel,
final int callerUid) {
final ArrayList<Integer> uids = new ArrayList<>();
@@ -206,6 +229,7 @@
/**
* Combine all {@link NetworkStatsHistory} in this collection which match
* the requested parameters.
+ * @hide
*/
public NetworkStatsHistory getHistory(NetworkTemplate template, SubscriptionPlan augmentPlan,
int uid, int set, int tag, int fields, long start, long end,
@@ -331,6 +355,7 @@
* @param end - end of the range, timestamp in milliseconds since the epoch.
* @param accessLevel - caller access level.
* @param callerUid - caller UID.
+ * @hide
*/
public NetworkStats getSummary(NetworkTemplate template, long start, long end,
@NetworkStatsAccess.Level int accessLevel, int callerUid) {
@@ -377,6 +402,7 @@
/**
* Record given {@link android.net.NetworkStats.Entry} into this collection.
+ * @hide
*/
public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start,
long end, NetworkStats.Entry entry) {
@@ -387,8 +413,12 @@
/**
* Record given {@link NetworkStatsHistory} into this collection.
+ *
+ * @hide
*/
- private void recordHistory(Key key, NetworkStatsHistory history) {
+ public void recordHistory(@NonNull Key key, @NonNull NetworkStatsHistory history) {
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(history);
if (history.size() == 0) return;
noteRecordedHistory(history.getStart(), history.getEnd(), history.getTotalBytes());
@@ -403,8 +433,11 @@
/**
* Record all {@link NetworkStatsHistory} contained in the given collection
* into this collection.
+ *
+ * @hide
*/
- public void recordCollection(NetworkStatsCollection another) {
+ public void recordCollection(@NonNull NetworkStatsCollection another) {
+ Objects.requireNonNull(another);
for (int i = 0; i < another.mStats.size(); i++) {
final Key key = another.mStats.keyAt(i);
final NetworkStatsHistory value = another.mStats.valueAt(i);
@@ -433,6 +466,7 @@
}
}
+ /** @hide */
@Override
public void read(InputStream in) throws IOException {
read((DataInput) new DataInputStream(in));
@@ -472,6 +506,7 @@
}
}
+ /** @hide */
@Override
public void write(OutputStream out) throws IOException {
write((DataOutput) new DataOutputStream(out));
@@ -514,6 +549,7 @@
* See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
*
* @deprecated
+ * @hide
*/
@Deprecated
public void readLegacyNetwork(File file) throws IOException {
@@ -559,6 +595,7 @@
* See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
*
* @deprecated
+ * @hide
*/
@Deprecated
public void readLegacyUid(File file, boolean onlyTags) throws IOException {
@@ -629,6 +666,7 @@
* Remove any {@link NetworkStatsHistory} attributed to the requested UID,
* moving any {@link NetworkStats#TAG_NONE} series to
* {@link TrafficStats#UID_REMOVED}.
+ * @hide
*/
public void removeUids(int[] uids) {
final ArrayList<Key> knownKeys = new ArrayList<>();
@@ -665,10 +703,11 @@
private ArrayList<Key> getSortedKeys() {
final ArrayList<Key> keys = new ArrayList<>();
keys.addAll(mStats.keySet());
- Collections.sort(keys);
+ Collections.sort(keys, (left, right) -> Key.compare(left, right));
return keys;
}
+ /** @hide */
public void dump(IndentingPrintWriter pw) {
for (Key key : getSortedKeys()) {
pw.print("ident="); pw.print(key.ident.toString());
@@ -683,6 +722,7 @@
}
}
+ /** @hide */
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
@@ -706,6 +746,7 @@
proto.end(start);
}
+ /** @hide */
public void dumpCheckin(PrintWriter pw, long start, long end) {
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell");
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi");
@@ -768,16 +809,37 @@
return false;
}
- private static class Key implements Comparable<Key> {
+ /**
+ * the identifier that associate with the {@link NetworkStatsHistory} object to identify
+ * a certain record in the {@link NetworkStatsCollection} object.
+ */
+ public static class Key {
+ /** @hide */
public final NetworkIdentitySet ident;
+ /** @hide */
public final int uid;
+ /** @hide */
public final int set;
+ /** @hide */
public final int tag;
private final int mHashCode;
- Key(NetworkIdentitySet ident, int uid, int set, int tag) {
- this.ident = ident;
+ /**
+ * Construct a {@link Key} object.
+ *
+ * @param ident a Set of {@link NetworkIdentity} that associated with the record.
+ * @param uid Uid of the record.
+ * @param set Set of the record, see {@code NetworkStats#SET_*}.
+ * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}.
+ */
+ public Key(@NonNull Set<NetworkIdentity> ident, int uid, int set, int tag) {
+ this(new NetworkIdentitySet(Objects.requireNonNull(ident)), uid, set, tag);
+ }
+
+ /** @hide */
+ public Key(@NonNull NetworkIdentitySet ident, int uid, int set, int tag) {
+ this.ident = Objects.requireNonNull(ident);
this.uid = uid;
this.set = set;
this.tag = tag;
@@ -790,7 +852,7 @@
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof Key) {
final Key key = (Key) obj;
return uid == key.uid && set == key.set && tag == key.tag
@@ -799,20 +861,22 @@
return false;
}
- @Override
- public int compareTo(Key another) {
+ /** @hide */
+ public static int compare(@NonNull Key left, @NonNull Key right) {
+ Objects.requireNonNull(left);
+ Objects.requireNonNull(right);
int res = 0;
- if (ident != null && another.ident != null) {
- res = ident.compareTo(another.ident);
+ if (left.ident != null && right.ident != null) {
+ res = NetworkIdentitySet.compare(left.ident, right.ident);
}
if (res == 0) {
- res = Integer.compare(uid, another.uid);
+ res = Integer.compare(left.uid, right.uid);
}
if (res == 0) {
- res = Integer.compare(set, another.set);
+ res = Integer.compare(left.set, right.set);
}
if (res == 0) {
- res = Integer.compare(tag, another.tag);
+ res = Integer.compare(left.tag, right.tag);
}
return res;
}
diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java
index 428bc6d..78c1370 100644
--- a/framework-t/src/android/net/NetworkStatsHistory.java
+++ b/framework-t/src/android/net/NetworkStatsHistory.java
@@ -16,6 +16,7 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
@@ -30,6 +31,8 @@
import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
@@ -50,7 +53,9 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ProtocolException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Random;
/**
@@ -64,18 +69,25 @@
*
* @hide
*/
-public class NetworkStatsHistory implements Parcelable {
+@SystemApi(client = MODULE_LIBRARIES)
+public final class NetworkStatsHistory implements Parcelable {
private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_PACKETS = 2;
private static final int VERSION_ADD_ACTIVE = 3;
+ /** @hide */
public static final int FIELD_ACTIVE_TIME = 0x01;
+ /** @hide */
public static final int FIELD_RX_BYTES = 0x02;
+ /** @hide */
public static final int FIELD_RX_PACKETS = 0x04;
+ /** @hide */
public static final int FIELD_TX_BYTES = 0x08;
+ /** @hide */
public static final int FIELD_TX_PACKETS = 0x10;
+ /** @hide */
public static final int FIELD_OPERATIONS = 0x20;
-
+ /** @hide */
public static final int FIELD_ALL = 0xFFFFFFFF;
private long bucketDuration;
@@ -89,34 +101,171 @@
private long[] operations;
private long totalBytes;
- public static class Entry {
- public static final long UNKNOWN = -1;
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long bucketDuration;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long bucketStart;
- public long activeTime;
- @UnsupportedAppUsage
- public long rxBytes;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long rxPackets;
- @UnsupportedAppUsage
- public long txBytes;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long txPackets;
- public long operations;
+ /** @hide */
+ public NetworkStatsHistory(long bucketDuration, long[] bucketStart, long[] activeTime,
+ long[] rxBytes, long[] rxPackets, long[] txBytes, long[] txPackets,
+ long[] operations, int bucketCount, long totalBytes) {
+ this.bucketDuration = bucketDuration;
+ this.bucketStart = bucketStart;
+ this.activeTime = activeTime;
+ this.rxBytes = rxBytes;
+ this.rxPackets = rxPackets;
+ this.txBytes = txBytes;
+ this.txPackets = txPackets;
+ this.operations = operations;
+ this.bucketCount = bucketCount;
+ this.totalBytes = totalBytes;
}
+ /**
+ * An instance to represent a single record in a {@link NetworkStatsHistory} object.
+ */
+ public static final class Entry {
+ /** @hide */
+ public static final long UNKNOWN = -1;
+
+ /** @hide */
+ // TODO: Migrate all callers to get duration from the history object and remove this field.
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public long bucketDuration;
+ /** @hide */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public long bucketStart;
+ /** @hide */
+ public long activeTime;
+ /** @hide */
+ @UnsupportedAppUsage
+ public long rxBytes;
+ /** @hide */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public long rxPackets;
+ /** @hide */
+ @UnsupportedAppUsage
+ public long txBytes;
+ /** @hide */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public long txPackets;
+ /** @hide */
+ public long operations;
+ /** @hide */
+ Entry() {}
+
+ /**
+ * Construct a {@link Entry} instance to represent a single record in a
+ * {@link NetworkStatsHistory} object.
+ *
+ * @param bucketStart Start of period for this {@link Entry}, in milliseconds since the
+ * Unix epoch, see {@link java.lang.System#currentTimeMillis}.
+ * @param activeTime Active time for this {@link Entry}, in milliseconds.
+ * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param rxPackets Number of packets received for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param operations count of network operations performed for this {@link Entry}. This can
+ * be used to derive bytes-per-operation.
+ */
+ public Entry(long bucketStart, long activeTime, long rxBytes,
+ long rxPackets, long txBytes, long txPackets, long operations) {
+ this.bucketStart = bucketStart;
+ this.activeTime = activeTime;
+ this.rxBytes = rxBytes;
+ this.rxPackets = rxPackets;
+ this.txBytes = txBytes;
+ this.txPackets = txPackets;
+ this.operations = operations;
+ }
+
+ /**
+ * Get start timestamp of the bucket's time interval, in milliseconds since the Unix epoch.
+ */
+ public long getBucketStart() {
+ return bucketStart;
+ }
+
+ /**
+ * Get active time of the bucket's time interval, in milliseconds.
+ */
+ public long getActiveTime() {
+ return activeTime;
+ }
+
+ /** Get number of bytes received for this {@link Entry}. */
+ public long getRxBytes() {
+ return rxBytes;
+ }
+
+ /** Get number of packets received for this {@link Entry}. */
+ public long getRxPackets() {
+ return rxPackets;
+ }
+
+ /** Get number of bytes transmitted for this {@link Entry}. */
+ public long getTxBytes() {
+ return txBytes;
+ }
+
+ /** Get number of packets transmitted for this {@link Entry}. */
+ public long getTxPackets() {
+ return txPackets;
+ }
+
+ /** Get count of network operations performed for this {@link Entry}. */
+ public long getOperations() {
+ return operations;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o.getClass() != getClass()) return false;
+ Entry entry = (Entry) o;
+ return bucketStart == entry.bucketStart
+ && activeTime == entry.activeTime && rxBytes == entry.rxBytes
+ && rxPackets == entry.rxPackets && txBytes == entry.txBytes
+ && txPackets == entry.txPackets && operations == entry.operations;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (bucketStart * 2
+ + activeTime * 3
+ + rxBytes * 5
+ + rxPackets * 7
+ + txBytes * 11
+ + txPackets * 13
+ + operations * 17);
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{"
+ + "bucketStart=" + bucketStart
+ + ", activeTime=" + activeTime
+ + ", rxBytes=" + rxBytes
+ + ", rxPackets=" + rxPackets
+ + ", txBytes=" + txBytes
+ + ", txPackets=" + txPackets
+ + ", operations=" + operations
+ + "}";
+ }
+ }
+
+ /** @hide */
@UnsupportedAppUsage
public NetworkStatsHistory(long bucketDuration) {
this(bucketDuration, 10, FIELD_ALL);
}
+ /** @hide */
public NetworkStatsHistory(long bucketDuration, int initialSize) {
this(bucketDuration, initialSize, FIELD_ALL);
}
+ /** @hide */
public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
this.bucketDuration = bucketDuration;
bucketStart = new long[initialSize];
@@ -130,11 +279,13 @@
totalBytes = 0;
}
+ /** @hide */
public NetworkStatsHistory(NetworkStatsHistory existing, long bucketDuration) {
this(bucketDuration, existing.estimateResizeBuckets(bucketDuration));
recordEntireHistory(existing);
}
+ /** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public NetworkStatsHistory(Parcel in) {
bucketDuration = in.readLong();
@@ -150,7 +301,7 @@
}
@Override
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeLong(bucketDuration);
writeLongArray(out, bucketStart, bucketCount);
writeLongArray(out, activeTime, bucketCount);
@@ -162,6 +313,7 @@
out.writeLong(totalBytes);
}
+ /** @hide */
public NetworkStatsHistory(DataInput in) throws IOException {
final int version = in.readInt();
switch (version) {
@@ -204,6 +356,7 @@
}
}
+ /** @hide */
public void writeToStream(DataOutput out) throws IOException {
out.writeInt(VERSION_ADD_ACTIVE);
out.writeLong(bucketDuration);
@@ -221,15 +374,18 @@
return 0;
}
+ /** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int size() {
return bucketCount;
}
+ /** @hide */
public long getBucketDuration() {
return bucketDuration;
}
+ /** @hide */
@UnsupportedAppUsage
public long getStart() {
if (bucketCount > 0) {
@@ -239,6 +395,7 @@
}
}
+ /** @hide */
@UnsupportedAppUsage
public long getEnd() {
if (bucketCount > 0) {
@@ -250,6 +407,7 @@
/**
* Return total bytes represented by this history.
+ * @hide
*/
public long getTotalBytes() {
return totalBytes;
@@ -258,6 +416,7 @@
/**
* Return index of bucket that contains or is immediately before the
* requested time.
+ * @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int getIndexBefore(long time) {
@@ -273,6 +432,7 @@
/**
* Return index of bucket that contains or is immediately after the
* requested time.
+ * @hide
*/
public int getIndexAfter(long time) {
int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
@@ -286,6 +446,7 @@
/**
* Return specific stats entry.
+ * @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public Entry getValues(int i, Entry recycle) {
@@ -301,6 +462,23 @@
return entry;
}
+ /**
+ * Get List of {@link Entry} of the {@link NetworkStatsHistory} instance.
+ *
+ * @return
+ */
+ @NonNull
+ public List<Entry> getEntries() {
+ // TODO: Return a wrapper that uses this list instead, to prevent the returned result
+ // from being changed.
+ final ArrayList<Entry> ret = new ArrayList<>(size());
+ for (int i = 0; i < size(); i++) {
+ ret.add(getValues(i, null /* recycle */));
+ }
+ return ret;
+ }
+
+ /** @hide */
public void setValues(int i, Entry entry) {
// Unwind old values
if (rxBytes != null) totalBytes -= rxBytes[i];
@@ -322,6 +500,7 @@
/**
* Record that data traffic occurred in the given time range. Will
* distribute across internal buckets, creating new buckets as needed.
+ * @hide
*/
@Deprecated
public void recordData(long start, long end, long rxBytes, long txBytes) {
@@ -332,6 +511,7 @@
/**
* Record that data traffic occurred in the given time range. Will
* distribute across internal buckets, creating new buckets as needed.
+ * @hide
*/
public void recordData(long start, long end, NetworkStats.Entry entry) {
long rxBytes = entry.rxBytes;
@@ -392,6 +572,7 @@
/**
* Record an entire {@link NetworkStatsHistory} into this history. Usually
* for combining together stats for external reporting.
+ * @hide
*/
@UnsupportedAppUsage
public void recordEntireHistory(NetworkStatsHistory input) {
@@ -402,6 +583,7 @@
* Record given {@link NetworkStatsHistory} into this history, copying only
* buckets that atomically occur in the inclusive time range. Doesn't
* interpolate across partial buckets.
+ * @hide
*/
public void recordHistory(NetworkStatsHistory input, long start, long end) {
final NetworkStats.Entry entry = new NetworkStats.Entry(
@@ -483,6 +665,7 @@
/**
* Clear all data stored in this object.
+ * @hide
*/
public void clear() {
bucketStart = EmptyArray.LONG;
@@ -498,9 +681,10 @@
/**
* Remove buckets older than requested cutoff.
+ * @hide
*/
- @Deprecated
public void removeBucketsBefore(long cutoff) {
+ // TODO: Consider use getIndexBefore.
int i;
for (i = 0; i < bucketCount; i++) {
final long curStart = bucketStart[i];
@@ -522,7 +706,9 @@
if (operations != null) operations = Arrays.copyOfRange(operations, i, length);
bucketCount -= i;
- // TODO: subtract removed values from totalBytes
+ totalBytes = 0;
+ if (rxBytes != null) totalBytes += CollectionUtils.total(rxBytes);
+ if (txBytes != null) totalBytes += CollectionUtils.total(txBytes);
}
}
@@ -536,6 +722,7 @@
* @param start - start of the range, timestamp in milliseconds since the epoch.
* @param end - end of the range, timestamp in milliseconds since the epoch.
* @param recycle - entry instance for performance, could be null.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getValues(long start, long end, Entry recycle) {
@@ -550,6 +737,7 @@
* @param end - end of the range, timestamp in milliseconds since the epoch.
* @param now - current timestamp in milliseconds since the epoch (wall clock).
* @param recycle - entry instance for performance, could be null.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getValues(long start, long end, long now, Entry recycle) {
@@ -613,6 +801,7 @@
/**
* @deprecated only for temporary testing
+ * @hide
*/
@Deprecated
public void generateRandom(long start, long end, long bytes) {
@@ -631,6 +820,7 @@
/**
* @deprecated only for temporary testing
+ * @hide
*/
@Deprecated
public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes,
@@ -660,12 +850,14 @@
}
}
+ /** @hide */
public static long randomLong(Random r, long start, long end) {
return (long) (start + (r.nextFloat() * (end - start)));
}
/**
* Quickly determine if this history intersects with given window.
+ * @hide
*/
public boolean intersects(long start, long end) {
final long dataStart = getStart();
@@ -677,6 +869,7 @@
return false;
}
+ /** @hide */
public void dump(IndentingPrintWriter pw, boolean fullHistory) {
pw.print("NetworkStatsHistory: bucketDuration=");
pw.println(bucketDuration / SECOND_IN_MILLIS);
@@ -700,6 +893,7 @@
pw.decreaseIndent();
}
+ /** @hide */
public void dumpCheckin(PrintWriter pw) {
pw.print("d,");
pw.print(bucketDuration / SECOND_IN_MILLIS);
@@ -717,6 +911,7 @@
}
}
+ /** @hide */
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
@@ -776,6 +971,7 @@
if (array != null) array[i] += value;
}
+ /** @hide */
public int estimateResizeBuckets(long newBucketDuration) {
return (int) (size() * getBucketDuration() / newBucketDuration);
}
@@ -783,6 +979,7 @@
/**
* Utility methods for interacting with {@link DataInputStream} and
* {@link DataOutputStream}, mostly dealing with writing partial arrays.
+ * @hide
*/
public static class DataStreamUtils {
@Deprecated
@@ -857,6 +1054,7 @@
/**
* Utility methods for interacting with {@link Parcel} structures, mostly
* dealing with writing partial arrays.
+ * @hide
*/
public static class ParcelUtils {
public static long[] readLongArray(Parcel in) {
@@ -884,4 +1082,80 @@
}
}
+ /**
+ * Builder class for {@link NetworkStatsHistory}.
+ */
+ public static final class Builder {
+ private final long mBucketDuration;
+ private final List<Long> mBucketStart;
+ private final List<Long> mActiveTime;
+ private final List<Long> mRxBytes;
+ private final List<Long> mRxPackets;
+ private final List<Long> mTxBytes;
+ private final List<Long> mTxPackets;
+ private final List<Long> mOperations;
+
+ /**
+ * Creates a new Builder with given bucket duration and initial capacity to construct
+ * {@link NetworkStatsHistory} objects.
+ *
+ * @param bucketDuration Duration of the buckets of the object, in milliseconds.
+ * @param initialCapacity Estimated number of records.
+ */
+ public Builder(long bucketDuration, int initialCapacity) {
+ mBucketDuration = bucketDuration;
+ mBucketStart = new ArrayList<>(initialCapacity);
+ mActiveTime = new ArrayList<>(initialCapacity);
+ mRxBytes = new ArrayList<>(initialCapacity);
+ mRxPackets = new ArrayList<>(initialCapacity);
+ mTxBytes = new ArrayList<>(initialCapacity);
+ mTxPackets = new ArrayList<>(initialCapacity);
+ mOperations = new ArrayList<>(initialCapacity);
+ }
+
+ /**
+ * Add an {@link Entry} into the {@link NetworkStatsHistory} instance.
+ *
+ * @param entry The target {@link Entry} object.
+ * @return The builder object.
+ */
+ @NonNull
+ public Builder addEntry(@NonNull Entry entry) {
+ mBucketStart.add(entry.bucketStart);
+ mActiveTime.add(entry.activeTime);
+ mRxBytes.add(entry.rxBytes);
+ mRxPackets.add(entry.rxPackets);
+ mTxBytes.add(entry.txBytes);
+ mTxPackets.add(entry.txPackets);
+ mOperations.add(entry.operations);
+ return this;
+ }
+
+ private static long sum(@NonNull List<Long> list) {
+ long sum = 0;
+ for (long entry : list) {
+ sum += entry;
+ }
+ return sum;
+ }
+
+ /**
+ * Builds the instance of the {@link NetworkStatsHistory}.
+ *
+ * @return the built instance of {@link NetworkStatsHistory}.
+ */
+ @NonNull
+ public NetworkStatsHistory build() {
+ return new NetworkStatsHistory(mBucketDuration,
+ CollectionUtils.toLongArray(mBucketStart),
+ CollectionUtils.toLongArray(mActiveTime),
+ CollectionUtils.toLongArray(mRxBytes),
+ CollectionUtils.toLongArray(mRxPackets),
+ CollectionUtils.toLongArray(mTxBytes),
+ CollectionUtils.toLongArray(mTxPackets),
+ CollectionUtils.toLongArray(mOperations),
+ mBucketStart.size(),
+ sum(mRxBytes) + sum(mTxBytes));
+ }
+ }
}
diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
index e9084b0..cad8075 100644
--- a/framework-t/src/android/net/NetworkTemplate.java
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -263,7 +263,7 @@
* Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
* given key of the wifi network.
*
- * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
* to know details about the key.
* @hide
*/
@@ -283,7 +283,7 @@
* 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()}
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
* to know details about the key.
* @param subscriberId the IMSI associated to this wifi network.
*
@@ -364,7 +364,7 @@
private final int mMetered;
private final int mRoaming;
private final int mDefaultNetwork;
- private final int mSubType;
+ private final int mRatType;
/**
* The subscriber Id match rule defines how the template should match networks with
* specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail.
@@ -413,18 +413,18 @@
/** @hide */
// TODO: Remove it after updating all of the caller.
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int subType,
+ String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int ratType,
int oemManaged) {
this(matchRule, subscriberId, matchSubscriberIds,
wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
- metered, roaming, defaultNetwork, subType, oemManaged,
+ metered, roaming, defaultNetwork, ratType, oemManaged,
NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
/** @hide */
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String[] matchWifiNetworkKeys, int metered, int roaming,
- int defaultNetwork, int subType, int oemManaged, int subscriberIdMatchRule) {
+ int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule) {
Objects.requireNonNull(matchWifiNetworkKeys);
mMatchRule = matchRule;
mSubscriberId = subscriberId;
@@ -435,7 +435,7 @@
mMetered = metered;
mRoaming = roaming;
mDefaultNetwork = defaultNetwork;
- mSubType = subType;
+ mRatType = ratType;
mOemManaged = oemManaged;
mSubscriberIdMatchRule = subscriberIdMatchRule;
checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule);
@@ -453,7 +453,7 @@
mMetered = in.readInt();
mRoaming = in.readInt();
mDefaultNetwork = in.readInt();
- mSubType = in.readInt();
+ mRatType = in.readInt();
mOemManaged = in.readInt();
mSubscriberIdMatchRule = in.readInt();
}
@@ -467,7 +467,7 @@
dest.writeInt(mMetered);
dest.writeInt(mRoaming);
dest.writeInt(mDefaultNetwork);
- dest.writeInt(mSubType);
+ dest.writeInt(mRatType);
dest.writeInt(mOemManaged);
dest.writeInt(mSubscriberIdMatchRule);
}
@@ -500,8 +500,8 @@
builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString(
mDefaultNetwork));
}
- if (mSubType != NETWORK_TYPE_ALL) {
- builder.append(", subType=").append(mSubType);
+ if (mRatType != NETWORK_TYPE_ALL) {
+ builder.append(", ratType=").append(mRatType);
}
if (mOemManaged != OEM_MANAGED_ALL) {
builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
@@ -514,7 +514,7 @@
@Override
public int hashCode() {
return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys),
- mMetered, mRoaming, mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule);
+ mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, mSubscriberIdMatchRule);
}
@Override
@@ -526,7 +526,7 @@
&& mMetered == other.mMetered
&& mRoaming == other.mRoaming
&& mDefaultNetwork == other.mDefaultNetwork
- && mSubType == other.mSubType
+ && mRatType == other.mRatType
&& mOemManaged == other.mOemManaged
&& mSubscriberIdMatchRule == other.mSubscriberIdMatchRule
&& Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys);
@@ -593,7 +593,7 @@
/**
* Get the set of Wifi Network Keys of the template.
- * See {@link WifiInfo#getCurrentNetworkKey()}.
+ * See {@link WifiInfo#getNetworkKey()}.
*/
@NonNull
public Set<String> getWifiNetworkKeys() {
@@ -635,7 +635,7 @@
* Get the Radio Access Technology(RAT) type filter of the template.
*/
public int getRatType() {
- return mSubType;
+ return mRatType;
}
/**
@@ -708,8 +708,8 @@
}
private boolean matchesCollapsedRatType(NetworkIdentity ident) {
- return mSubType == NETWORK_TYPE_ALL
- || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
+ return mRatType == NETWORK_TYPE_ALL
+ || getCollapsedRatType(mRatType) == getCollapsedRatType(ident.mRatType);
}
/**
@@ -729,7 +729,7 @@
* Returns true when the key matches, or when {@code mMatchWifiNetworkKeys} is
* empty.
*
- * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
* to know details about the key.
*/
private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) {
@@ -837,7 +837,7 @@
switch (ident.mType) {
case TYPE_WIFI:
return matchesSubscriberId(ident.mSubscriberId)
- && matchesWifiNetworkKey(ident.mNetworkId);
+ && matchesWifiNetworkKey(ident.mWifiNetworkKey);
default:
return false;
}
@@ -1059,9 +1059,9 @@
* the intention of matching any Wifi Network Key.
*
* @param wifiNetworkKeys the list of Wifi Network Key,
- * see {@link WifiInfo#getCurrentNetworkKey()}.
+ * see {@link WifiInfo#getNetworkKey()}.
* Or an empty list to match all networks.
- * Note that {@code getCurrentNetworkKey()} might get null key
+ * Note that {@code getNetworkKey()} 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.
diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java
index 1af32bf..c803a72 100644
--- a/framework-t/src/android/net/TrafficStats.java
+++ b/framework-t/src/android/net/TrafficStats.java
@@ -17,7 +17,6 @@
package android.net;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -27,8 +26,8 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.MediaPlayer;
+import android.os.Binder;
import android.os.Build;
-import android.os.IBinder;
import android.os.RemoteException;
import com.android.server.NetworkManagementSocketTagger;
@@ -37,8 +36,6 @@
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;
@@ -177,25 +174,12 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
private synchronized static INetworkStatsService getStatsService() {
if (sStatsService == null) {
- sStatsService = getStatsBinder();
+ throw new IllegalStateException("TrafficStats not initialized, uid="
+ + Binder.getCallingUid());
}
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.
@@ -210,6 +194,26 @@
private static final String LOOPBACK_IFACE = "lo";
/**
+ * Initialization {@link TrafficStats} with the context, to
+ * allow {@link TrafficStats} to fetch the needed binder.
+ *
+ * @param context a long-lived context, such as the application context or system
+ * server context.
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("VisiblySynchronized")
+ public static synchronized void init(@NonNull final Context context) {
+ if (sStatsService != null) {
+ throw new IllegalStateException("TrafficStats is already initialized, uid="
+ + Binder.getCallingUid());
+ }
+ final NetworkStatsManager statsManager =
+ context.getSystemService(NetworkStatsManager.class);
+ sStatsService = statsManager.getBinder();
+ }
+
+ /**
* Set active tag to use when accounting {@link Socket} traffic originating
* from the current thread. Only one active tag per thread is supported.
* <p>
diff --git a/service-t/Sources.bp b/service-t/Sources.bp
index 3fd3d8c..24bc91d 100644
--- a/service-t/Sources.bp
+++ b/service-t/Sources.bp
@@ -68,6 +68,7 @@
filegroup {
name: "services.connectivity-ethernet-sources",
srcs: [
+ "src/com/android/server/net/DelayedDiskWrite.java",
"src/com/android/server/net/IpConfigStore.java",
],
path: "src",
diff --git a/services/core/java/com/android/server/net/DelayedDiskWrite.java b/service-t/src/com/android/server/net/DelayedDiskWrite.java
similarity index 82%
rename from services/core/java/com/android/server/net/DelayedDiskWrite.java
rename to service-t/src/com/android/server/net/DelayedDiskWrite.java
index 8f09eb7..35dc455 100644
--- a/services/core/java/com/android/server/net/DelayedDiskWrite.java
+++ b/service-t/src/com/android/server/net/DelayedDiskWrite.java
@@ -26,21 +26,37 @@
import java.io.FileOutputStream;
import java.io.IOException;
+/**
+ * This class provides APIs to do a delayed data write to a given {@link OutputStream}.
+ */
public class DelayedDiskWrite {
+ private static final String TAG = "DelayedDiskWrite";
+
private HandlerThread mDiskWriteHandlerThread;
private Handler mDiskWriteHandler;
/* Tracks multiple writes on the same thread */
private int mWriteSequence = 0;
- private final String TAG = "DelayedDiskWrite";
+ /**
+ * Used to do a delayed data write to a given {@link OutputStream}.
+ */
public interface Writer {
- public void onWriteCalled(DataOutputStream out) throws IOException;
+ /**
+ * write data to a given {@link OutputStream}.
+ */
+ void onWriteCalled(DataOutputStream out) throws IOException;
}
+ /**
+ * Do a delayed data write to a given output stream opened from filePath.
+ */
public void write(final String filePath, final Writer w) {
write(filePath, w, true);
}
+ /**
+ * Do a delayed data write to a given output stream opened from filePath.
+ */
public void write(final String filePath, final Writer w, final boolean open) {
if (TextUtils.isEmpty(filePath)) {
throw new IllegalArgumentException("empty file path");
@@ -77,7 +93,7 @@
if (out != null) {
try {
out.close();
- } catch (Exception e) {}
+ } catch (Exception e) { }
}
// Quit if no more writes sent
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index ad15c3c..4c78dcb 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -19,12 +19,16 @@
import static android.Manifest.permission.NETWORK_STATS_PROVIDER;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
+import static android.app.usage.NetworkStatsManager.PREFIX_DEV;
+import static android.app.usage.NetworkStatsManager.PREFIX_UID;
+import static android.app.usage.NetworkStatsManager.PREFIX_UID_TAG;
+import static android.app.usage.NetworkStatsManager.PREFIX_XT;
import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.ACTION_USER_REMOVED;
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.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.IFACE_VT;
@@ -102,7 +106,6 @@
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
@@ -230,11 +233,6 @@
private PendingIntent mPollIntent;
- private static final String PREFIX_DEV = "dev";
- private static final String PREFIX_XT = "xt";
- private static final String PREFIX_UID = "uid";
- private static final String PREFIX_UID_TAG = "uid_tag";
-
/**
* Settings that can be changed externally.
*/
@@ -244,9 +242,9 @@
boolean getSampleEnabled();
boolean getAugmentEnabled();
/**
- * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}.
- * When disabled, mobile data is broken down by a granular subtype representative of the
- * actual subtype. {@see NetworkTemplate#getCollapsedRatType}.
+ * When enabled, all mobile data is reported under {@link NetworkTemplate#NETWORK_TYPE_ALL}.
+ * When disabled, mobile data is broken down by a granular ratType representative of the
+ * actual ratType. {@see NetworkTemplate#getCollapsedRatType}.
* Enabling this decreases the level of detail but saves performance, disk space and
* amount of data logged.
*/
@@ -293,6 +291,9 @@
/** Set of any ifaces associated with mobile networks since boot. */
private volatile String[] mMobileIfaces = new String[0];
+ /** Set of any ifaces associated with wifi networks since boot. */
+ private volatile String[] mWifiIfaces = new String[0];
+
/** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */
@GuardedBy("mStatsLock")
private Network[] mDefaultNetworks = new Network[0];
@@ -451,7 +452,7 @@
handlerThread.start();
mHandler = new NetworkStatsHandler(handlerThread.getLooper());
mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
- new HandlerExecutor(mHandler), this);
+ (command) -> mHandler.post(command) , this);
mContentResolver = mContext.getContentResolver();
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
mNetworkStatsSubscriptionsMonitor);
@@ -567,7 +568,7 @@
// watch for tethering changes
final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
tetheringManager.registerTetheringEventCallback(
- new HandlerExecutor(mHandler), mTetherListener);
+ (command) -> mHandler.post(command), mTetherListener);
// listen for periodic polling events
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
@@ -1019,11 +1020,15 @@
}
@Override
- public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
+ public NetworkStats getUidStatsForTransport(int transport) {
enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
try {
+ final String[] relevantIfaces =
+ transport == TRANSPORT_WIFI ? mWifiIfaces : mMobileIfaces;
+ // TODO(b/215633405) : mMobileIfaces and mWifiIfaces already contain the stacked
+ // interfaces, so this is not useful, remove it.
final String[] ifacesToQuery =
- mStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
+ mStatsFactory.augmentWithStackedInterfaces(relevantIfaces);
return getNetworkStatsUidDetail(ifacesToQuery);
} catch (RemoteException e) {
Log.wtf(TAG, "Error compiling UID stats", e);
@@ -1382,16 +1387,18 @@
final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled();
final ArraySet<String> mobileIfaces = new ArraySet<>();
+ final ArraySet<String> wifiIfaces = new ArraySet<>();
for (NetworkStateSnapshot snapshot : snapshots) {
final int displayTransport =
getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes());
final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport);
+ final boolean isWifi = (NetworkCapabilities.TRANSPORT_WIFI == displayTransport);
final boolean isDefault = CollectionUtils.contains(
mDefaultNetworks, snapshot.getNetwork());
- final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED
- : getSubTypeForStateSnapshot(snapshot);
+ final int ratType = combineSubtypeEnabled ? NetworkTemplate.NETWORK_TYPE_ALL
+ : getRatTypeForStateSnapshot(snapshot);
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
- isDefault, subType);
+ isDefault, ratType);
// Traffic occurring on the base interface is always counted for
// both total usage and UID details.
@@ -1406,12 +1413,12 @@
// VT is considered always metered in framework's layer. If VT is not metered
// per carrier's policy, modem will report 0 usage for VT calls.
if (snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) {
+ NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.isMetered()) {
// Copy the identify from IMS one but mark it as metered.
NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(),
- ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
- ident.getRoaming(), true /* metered */,
+ ident.getRatType(), ident.getSubscriberId(), ident.getWifiNetworkKey(),
+ ident.isRoaming(), true /* metered */,
true /* onDefaultNetwork */, ident.getOemManaged());
final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
@@ -1421,6 +1428,9 @@
if (isMobile) {
mobileIfaces.add(baseIface);
}
+ if (isWifi) {
+ wifiIfaces.add(baseIface);
+ }
}
// Traffic occurring on stacked interfaces is usually clatd.
@@ -1462,6 +1472,9 @@
if (isMobile) {
mobileIfaces.add(iface);
}
+ if (isWifi) {
+ wifiIfaces.add(iface);
+ }
mStatsFactory.noteStackedIface(iface, baseIface);
}
@@ -1469,11 +1482,16 @@
}
mMobileIfaces = mobileIfaces.toArray(new String[0]);
+ mWifiIfaces = wifiIfaces.toArray(new String[0]);
// TODO (b/192758557): Remove debug log.
if (CollectionUtils.contains(mMobileIfaces, null)) {
throw new NullPointerException(
"null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
}
+ if (CollectionUtils.contains(mWifiIfaces, null)) {
+ throw new NullPointerException(
+ "null element in mWifiIfaces: " + Arrays.toString(mWifiIfaces));
+ }
}
private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {
@@ -1491,11 +1509,11 @@
}
/**
- * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through
+ * For networks with {@code TRANSPORT_CELLULAR}, get ratType that was obtained through
* {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
* transport types do not actually fill this value.
*/
- private int getSubTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
+ private int getRatTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return 0;
}