Merge "Track constructor changes in libcore/"
am: f94eb29500
Change-Id: I344d9210bd173f78651318366c852f65afe969d6
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index 6ca2349..216a4a0 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -68,6 +68,11 @@
private int mTag = android.net.NetworkStats.TAG_NONE;
/**
+ * State in case it was not specified in the query.
+ */
+ private int mState = Bucket.STATE_ALL;
+
+ /**
* The session while the query requires it, null if all the stats have been collected or close()
* has been called.
*/
@@ -127,7 +132,11 @@
*/
public static class Bucket {
/** @hide */
- @IntDef({STATE_ALL, STATE_DEFAULT, STATE_FOREGROUND})
+ @IntDef(prefix = { "STATE_" }, value = {
+ STATE_ALL,
+ STATE_DEFAULT,
+ STATE_FOREGROUND
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface State {}
@@ -162,7 +171,11 @@
public static final int UID_TETHERING = TrafficStats.UID_TETHERING;
/** @hide */
- @IntDef({METERED_ALL, METERED_NO, METERED_YES})
+ @IntDef(prefix = { "METERED_" }, value = {
+ METERED_ALL,
+ METERED_NO,
+ METERED_YES
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface Metered {}
@@ -185,7 +198,11 @@
public static final int METERED_YES = 0x2;
/** @hide */
- @IntDef({ROAMING_ALL, ROAMING_NO, ROAMING_YES})
+ @IntDef(prefix = { "ROAMING_" }, value = {
+ ROAMING_ALL,
+ ROAMING_NO,
+ ROAMING_YES
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface Roaming {}
@@ -220,20 +237,26 @@
DEFAULT_NETWORK_YES
})
@Retention(RetentionPolicy.SOURCE)
- public @interface DefaultNetwork {}
+ public @interface DefaultNetworkStatus {}
/**
- * Combined usage for this network regardless of whether it was the active default network.
+ * Combined usage for this network regardless of default network status.
*/
public static final int DEFAULT_NETWORK_ALL = -1;
/**
- * Usage that occurs while this network is not the active default network.
+ * Usage that occurs while this network is not a default network.
+ *
+ * <p>This implies that the app responsible for this usage requested that it occur on a
+ * specific network different from the one(s) the system would have selected for it.
*/
public static final int DEFAULT_NETWORK_NO = 0x1;
/**
- * Usage that occurs while this network is the active default network.
+ * Usage that occurs while this network is a default network.
+ *
+ * <p>This implies that the app either did not select a specific network for this usage,
+ * or it selected a network that the system could have selected for app traffic.
*/
public static final int DEFAULT_NETWORK_YES = 0x2;
@@ -245,7 +268,7 @@
private int mUid;
private int mTag;
private int mState;
- private int mDefaultNetwork;
+ private int mDefaultNetworkStatus;
private int mMetered;
private int mRoaming;
private long mBeginTimeStamp;
@@ -255,6 +278,15 @@
private long mTxBytes;
private long mTxPackets;
+ private static int convertSet(@State int state) {
+ switch (state) {
+ case STATE_ALL: return android.net.NetworkStats.SET_ALL;
+ case STATE_DEFAULT: return android.net.NetworkStats.SET_DEFAULT;
+ case STATE_FOREGROUND: return android.net.NetworkStats.SET_FOREGROUND;
+ }
+ return 0;
+ }
+
private static @State int convertState(int networkStatsSet) {
switch (networkStatsSet) {
case android.net.NetworkStats.SET_ALL : return STATE_ALL;
@@ -297,8 +329,9 @@
return 0;
}
- private static @DefaultNetwork int convertDefaultNetwork(int defaultNetwork) {
- switch (defaultNetwork) {
+ private static @DefaultNetworkStatus int convertDefaultNetworkStatus(
+ int defaultNetworkStatus) {
+ switch (defaultNetworkStatus) {
case android.net.NetworkStats.DEFAULT_NETWORK_ALL : return DEFAULT_NETWORK_ALL;
case android.net.NetworkStats.DEFAULT_NETWORK_NO: return DEFAULT_NETWORK_NO;
case android.net.NetworkStats.DEFAULT_NETWORK_YES: return DEFAULT_NETWORK_YES;
@@ -371,18 +404,15 @@
}
/**
- * Default network state. One of the following values:<p/>
+ * Default network status. One of the following values:<p/>
* <ul>
* <li>{@link #DEFAULT_NETWORK_ALL}</li>
* <li>{@link #DEFAULT_NETWORK_NO}</li>
* <li>{@link #DEFAULT_NETWORK_YES}</li>
* </ul>
- * <p>Indicates whether the network usage occurred on the system default network for this
- * type of traffic, or whether the application chose to send this traffic on a network that
- * was not the one selected by the system.
*/
- public @DefaultNetwork int getDefaultNetwork() {
- return mDefaultNetwork;
+ public @DefaultNetworkStatus int getDefaultNetworkStatus() {
+ return mDefaultNetworkStatus;
}
/**
@@ -515,20 +545,13 @@
/**
* Collects history results for uid and resets history enumeration index.
*/
- void startHistoryEnumeration(int uid) {
- startHistoryEnumeration(uid, android.net.NetworkStats.TAG_NONE);
- }
-
- /**
- * Collects history results for uid and resets history enumeration index.
- */
- void startHistoryEnumeration(int uid, int tag) {
+ void startHistoryEnumeration(int uid, int tag, int state) {
mHistory = null;
try {
mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
- android.net.NetworkStats.SET_ALL, tag,
- NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
- setSingleUidTag(uid, tag);
+ Bucket.convertSet(state), tag, NetworkStatsHistory.FIELD_ALL,
+ mStartTimeStamp, mEndTimeStamp);
+ setSingleUidTagState(uid, tag, state);
} catch (RemoteException e) {
Log.w(TAG, e);
// Leaving mHistory null
@@ -586,7 +609,7 @@
bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag);
bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
- bucketOut.mDefaultNetwork = Bucket.convertDefaultNetwork(
+ bucketOut.mDefaultNetworkStatus = Bucket.convertDefaultNetworkStatus(
mRecycledSummaryEntry.defaultNetwork);
bucketOut.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered);
bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
@@ -624,6 +647,7 @@
fillBucketFromSummaryEntry(bucket);
return bucket;
}
+
/**
* Getting the next item in a history enumeration.
* @param bucketOut Next item will be set here.
@@ -636,8 +660,8 @@
mRecycledHistoryEntry);
bucketOut.mUid = Bucket.convertUid(getUid());
bucketOut.mTag = Bucket.convertTag(mTag);
- bucketOut.mState = Bucket.STATE_ALL;
- bucketOut.mDefaultNetwork = Bucket.DEFAULT_NETWORK_ALL;
+ bucketOut.mState = mState;
+ bucketOut.mDefaultNetworkStatus = Bucket.DEFAULT_NETWORK_ALL;
bucketOut.mMetered = Bucket.METERED_ALL;
bucketOut.mRoaming = Bucket.ROAMING_ALL;
bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
@@ -679,9 +703,10 @@
return mUidOrUidIndex;
}
- private void setSingleUidTag(int uid, int tag) {
+ private void setSingleUidTagState(int uid, int tag, int state) {
mUidOrUidIndex = uid;
mTag = tag;
+ mState = state;
}
private void stepUid() {
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 2357637..9f46f20 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.usage.NetworkStats.Bucket;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -35,6 +36,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
+import android.util.DataUnit;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -95,13 +97,24 @@
/** @hide */
public static final int CALLBACK_RELEASED = 1;
+ /**
+ * Minimum data usage threshold for registering usage callbacks.
+ *
+ * Requests registered with a threshold lower than this will only be triggered once this minimum
+ * is reached.
+ * @hide
+ */
+ public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2);
+
private final Context mContext;
private final INetworkStatsService mService;
/** @hide */
public static final int FLAG_POLL_ON_OPEN = 1 << 0;
/** @hide */
- public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 1;
+ public static final int FLAG_POLL_FORCE = 1 << 1;
+ /** @hide */
+ public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2;
private int mFlags;
@@ -131,6 +144,16 @@
}
/** @hide */
+ @TestApi
+ public void setPollForce(boolean pollForce) {
+ if (pollForce) {
+ mFlags |= FLAG_POLL_FORCE;
+ } else {
+ mFlags &= ~FLAG_POLL_FORCE;
+ }
+ }
+
+ /** @hide */
public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) {
if (augmentWithSubscriptionPlan) {
mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
@@ -263,20 +286,31 @@
/**
* Query network usage statistics details for a given uid.
*
- * #see queryDetailsForUidTag(int, String, long, long, int, int)
+ * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
*/
public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
- long startTime, long endTime, int uid) throws SecurityException, RemoteException {
- return queryDetailsForUidTag(networkType, subscriberId, startTime, endTime, uid,
- NetworkStats.Bucket.TAG_NONE);
+ long startTime, long endTime, int uid) throws SecurityException {
+ return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
+ NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
}
/**
- * Query network usage statistics details for a given uid and tag. Only usable for uids
- * belonging to calling user. Result is aggregated over state but not aggregated over time.
- * This means buckets' start and end timestamps are going to be between 'startTime' and
- * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the
- * same as the 'uid' parameter and tag the same as 'tag' parameter.
+ * Query network usage statistics details for a given uid and tag.
+ *
+ * #see queryDetailsForUidTagState(int, String, long, long, int, int, int)
+ */
+ public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
+ long startTime, long endTime, int uid, int tag) throws SecurityException {
+ return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
+ tag, NetworkStats.Bucket.STATE_ALL);
+ }
+
+ /**
+ * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
+ * belonging to calling user. Result is not aggregated over time. This means buckets' start and
+ * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
+ * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
+ * the same as the 'state' parameter.
* defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
* metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
* roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
@@ -294,20 +328,23 @@
* {@link java.lang.System#currentTimeMillis}.
* @param uid UID of app
* @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
+ * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
+ * traffic from all states.
* @return Statistics object or null if an error happened during statistics collection.
* @throws SecurityException if permissions are insufficient to read network statistics.
*/
- public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
- long startTime, long endTime, int uid, int tag) throws SecurityException {
+ public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
+ long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
NetworkTemplate template;
template = createTemplate(networkType, subscriberId);
NetworkStats result;
try {
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
- result.startHistoryEnumeration(uid, tag);
+ result.startHistoryEnumeration(uid, tag, state);
} catch (RemoteException e) {
- Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e);
+ Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
+ + " state=" + state, e);
return null;
}
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index eab7041..8e6f272 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -39,9 +39,6 @@
*/
INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage);
- /** Return network layer usage total for traffic that matches template. */
- long getNetworkTotalBytes(in NetworkTemplate template, long start, long end);
-
/** Return data layer snapshot of UID network usage. */
NetworkStats getDataLayerSnapshotForUid(int uid);
@@ -60,17 +57,11 @@
/** Increment data layer count of operations performed for UID and tag. */
void incrementOperationCount(int uid, int tag, int operationCount);
- /** Mark given UID as being in foreground for stats purposes. */
- void setUidForeground(int uid, boolean uidForeground);
-
/** Force update of ifaces. */
void forceUpdateIfaces(in Network[] defaultNetworks);
/** Force update of statistics. */
void forceUpdate();
- /** Advise persistance threshold; may be overridden internally. */
- void advisePersistThreshold(long thresholdBytes);
-
/** Registers a callback on data usage. */
DataUsageRequest registerUsageCallback(String callingPackage,
in DataUsageRequest request, in Messenger messenger, in IBinder binder);
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 1145d5b..d4c3edc 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -20,7 +20,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
@@ -721,7 +720,6 @@
* to create Network objects which are accessible to the Android system.
* @hide
*/
- @SystemApi
public static final class IpSecTunnelInterface implements AutoCloseable {
private final String mOpPackageName;
private final IIpSecService mService;
@@ -748,7 +746,6 @@
* @param prefixLen length of the InetAddress prefix
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
try {
@@ -770,7 +767,6 @@
* @param prefixLen length of the InetAddress prefix
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
try {
@@ -884,7 +880,6 @@
* @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
* @hide
*/
- @SystemApi
@NonNull
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
@@ -915,7 +910,6 @@
* layer failure.
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel,
@PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 23c8aa3..a12df28 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -22,7 +22,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
import android.content.Context;
import android.os.Binder;
import android.os.Handler;
@@ -257,7 +256,6 @@
*
* @hide
*/
- @SystemApi
public static class NattKeepaliveCallback {
/** The specified {@code Network} is not connected. */
public static final int ERROR_INVALID_NETWORK = 1;
@@ -288,7 +286,6 @@
*
* @hide
*/
- @SystemApi
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_IPSEC_TUNNELS,
android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD
@@ -331,7 +328,6 @@
*
* @hide
*/
- @SystemApi
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_IPSEC_TUNNELS,
android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD
@@ -484,7 +480,6 @@
* @throws IOException indicating other errors
* @hide
*/
- @SystemApi
@NonNull
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public IpSecTransform buildTunnelModeTransform(
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index d6cbc88..edf9bc1 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -243,7 +243,7 @@
public NetworkStats(long elapsedRealtime, int initialSize) {
this.elapsedRealtime = elapsedRealtime;
this.size = 0;
- if (initialSize >= 0) {
+ if (initialSize > 0) {
this.capacity = initialSize;
this.iface = new String[initialSize];
this.uid = new int[initialSize];
@@ -259,19 +259,7 @@
this.operations = new long[initialSize];
} else {
// Special case for use by NetworkStatsFactory to start out *really* empty.
- this.capacity = 0;
- this.iface = EmptyArray.STRING;
- this.uid = EmptyArray.INT;
- this.set = EmptyArray.INT;
- this.tag = EmptyArray.INT;
- this.metered = EmptyArray.INT;
- this.roaming = EmptyArray.INT;
- this.defaultNetwork = EmptyArray.INT;
- this.rxBytes = EmptyArray.LONG;
- this.rxPackets = EmptyArray.LONG;
- this.txBytes = EmptyArray.LONG;
- this.txPackets = EmptyArray.LONG;
- this.operations = EmptyArray.LONG;
+ clear();
}
}
@@ -323,6 +311,25 @@
return clone;
}
+ /**
+ * Clear all data stored in this object.
+ */
+ public void clear() {
+ this.capacity = 0;
+ this.iface = EmptyArray.STRING;
+ this.uid = EmptyArray.INT;
+ this.set = EmptyArray.INT;
+ this.tag = EmptyArray.INT;
+ this.metered = EmptyArray.INT;
+ this.roaming = EmptyArray.INT;
+ this.defaultNetwork = EmptyArray.INT;
+ this.rxBytes = EmptyArray.LONG;
+ this.rxPackets = EmptyArray.LONG;
+ this.txBytes = EmptyArray.LONG;
+ this.txPackets = EmptyArray.LONG;
+ this.operations = EmptyArray.LONG;
+ }
+
@VisibleForTesting
public NetworkStats addIfaceValues(
String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
@@ -1093,6 +1100,8 @@
public interface NonMonotonicObserver<C> {
public void foundNonMonotonic(
NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, C cookie);
+ public void foundNonMonotonic(
+ NetworkStats stats, int statsIndex, C cookie);
}
/**
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index 433f941..a13ad65 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -39,6 +39,8 @@
import com.android.internal.util.IndentingPrintWriter;
+import libcore.util.EmptyArray;
+
import java.io.CharArrayWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -459,6 +461,21 @@
}
/**
+ * Clear all data stored in this object.
+ */
+ public void clear() {
+ bucketStart = EmptyArray.LONG;
+ if (activeTime != null) activeTime = EmptyArray.LONG;
+ if (rxBytes != null) rxBytes = EmptyArray.LONG;
+ if (rxPackets != null) rxPackets = EmptyArray.LONG;
+ if (txBytes != null) txBytes = EmptyArray.LONG;
+ if (txPackets != null) txPackets = EmptyArray.LONG;
+ if (operations != null) operations = EmptyArray.LONG;
+ bucketCount = 0;
+ totalBytes = 0;
+ }
+
+ /**
* Remove buckets older than requested cutoff.
*/
@Deprecated
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 8efd39a..74233fd 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -23,7 +23,6 @@
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.ConnectivityManager.TYPE_WIMAX;
-import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
@@ -34,11 +33,6 @@
import static android.net.NetworkStats.ROAMING_NO;
import static android.net.NetworkStats.ROAMING_YES;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
-import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
-import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
-import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
-import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
-import static android.telephony.TelephonyManager.getNetworkClass;
import android.os.Parcel;
import android.os.Parcelable;
@@ -55,8 +49,8 @@
import java.util.Objects;
/**
- * Template definition used to generically match {@link NetworkIdentity},
- * usually when collecting statistics.
+ * Predicate used to match {@link NetworkIdentity}, usually when collecting
+ * statistics. (It should probably have been named {@code NetworkPredicate}.)
*
* @hide
*/
@@ -68,13 +62,7 @@
*/
private static final int BACKUP_VERSION = 1;
- public static final int MATCH_MOBILE_ALL = 1;
- /** @deprecated don't use this any more */
- @Deprecated
- public static final int MATCH_MOBILE_3G_LOWER = 2;
- /** @deprecated don't use this any more */
- @Deprecated
- public static final int MATCH_MOBILE_4G = 3;
+ public static final int MATCH_MOBILE = 1;
public static final int MATCH_WIFI = 4;
public static final int MATCH_ETHERNET = 5;
public static final int MATCH_MOBILE_WILDCARD = 6;
@@ -84,9 +72,7 @@
private static boolean isKnownMatchRule(final int rule) {
switch (rule) {
- case MATCH_MOBILE_ALL:
- case MATCH_MOBILE_3G_LOWER:
- case MATCH_MOBILE_4G:
+ case MATCH_MOBILE:
case MATCH_WIFI:
case MATCH_ETHERNET:
case MATCH_MOBILE_WILDCARD:
@@ -111,25 +97,7 @@
* the given IMSI.
*/
public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
- return new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId, null);
- }
-
- /**
- * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
- * the given IMSI that roughly meet a "3G" definition, or lower.
- */
- @Deprecated
- public static NetworkTemplate buildTemplateMobile3gLower(String subscriberId) {
- return new NetworkTemplate(MATCH_MOBILE_3G_LOWER, subscriberId, null);
- }
-
- /**
- * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
- * the given IMSI that roughly meet a "4G" definition.
- */
- @Deprecated
- public static NetworkTemplate buildTemplateMobile4g(String subscriberId) {
- return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId, null);
+ return new NetworkTemplate(MATCH_MOBILE, subscriberId, null);
}
/**
@@ -307,9 +275,7 @@
public boolean isMatchRuleMobile() {
switch (mMatchRule) {
- case MATCH_MOBILE_3G_LOWER:
- case MATCH_MOBILE_4G:
- case MATCH_MOBILE_ALL:
+ case MATCH_MOBILE:
case MATCH_MOBILE_WILDCARD:
return true;
default:
@@ -348,12 +314,8 @@
if (!matchesDefaultNetwork(ident)) return false;
switch (mMatchRule) {
- case MATCH_MOBILE_ALL:
+ case MATCH_MOBILE:
return matchesMobile(ident);
- case MATCH_MOBILE_3G_LOWER:
- return matchesMobile3gLower(ident);
- case MATCH_MOBILE_4G:
- return matchesMobile4g(ident);
case MATCH_WIFI:
return matchesWifi(ident);
case MATCH_ETHERNET:
@@ -410,43 +372,6 @@
}
/**
- * Check if mobile network classified 3G or lower with matching IMSI.
- */
- @Deprecated
- private boolean matchesMobile3gLower(NetworkIdentity ident) {
- ensureSubtypeAvailable();
- if (ident.mType == TYPE_WIMAX) {
- return false;
- } else if (matchesMobile(ident)) {
- switch (getNetworkClass(ident.mSubType)) {
- case NETWORK_CLASS_UNKNOWN:
- case NETWORK_CLASS_2_G:
- case NETWORK_CLASS_3_G:
- return true;
- }
- }
- return false;
- }
-
- /**
- * Check if mobile network classified 4G with matching IMSI.
- */
- @Deprecated
- private boolean matchesMobile4g(NetworkIdentity ident) {
- ensureSubtypeAvailable();
- if (ident.mType == TYPE_WIMAX) {
- // TODO: consider matching against WiMAX subscriber identity
- return true;
- } else if (matchesMobile(ident)) {
- switch (getNetworkClass(ident.mSubType)) {
- case NETWORK_CLASS_4_G:
- return true;
- }
- }
- return false;
- }
-
- /**
* Check if matches Wi-Fi network template.
*/
private boolean matchesWifi(NetworkIdentity ident) {
@@ -506,12 +431,8 @@
private static String getMatchRuleName(int matchRule) {
switch (matchRule) {
- case MATCH_MOBILE_3G_LOWER:
- return "MOBILE_3G_LOWER";
- case MATCH_MOBILE_4G:
- return "MOBILE_4G";
- case MATCH_MOBILE_ALL:
- return "MOBILE_ALL";
+ case MATCH_MOBILE:
+ return "MOBILE";
case MATCH_WIFI:
return "WIFI";
case MATCH_ETHERNET:
@@ -529,13 +450,6 @@
}
}
- private static void ensureSubtypeAvailable() {
- if (COMBINE_SUBTYPE_ENABLED) {
- throw new IllegalArgumentException(
- "Unable to enforce 3G_LOWER template on combined data.");
- }
- }
-
/**
* Examine the given template and normalize if it refers to a "merged"
* mobile subscriber. We pick the "lowest" merged subscriber as the primary
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index fa4624e..40d53b7 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -16,7 +16,6 @@
package android.net;
-import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -27,6 +26,7 @@
import android.media.MediaPlayer;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.DataUnit;
import com.android.server.NetworkManagementSocketTagger;
@@ -56,15 +56,20 @@
*/
public final static int UNSUPPORTED = -1;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long KB_IN_BYTES = 1024;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
- /** @hide */
+ /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+ @Deprecated
public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
/**
@@ -253,30 +258,47 @@
/**
* Set specific UID to use when accounting {@link Socket} traffic
* originating from the current thread. Designed for use when performing an
- * operation on behalf of another application.
+ * operation on behalf of another application, or when another application
+ * is performing operations on your behalf.
+ * <p>
+ * Any app can <em>accept</em> blame for traffic performed on a socket
+ * originally created by another app by calling this method with the
+ * {@link android.system.Os#getuid()} value. However, only apps holding the
+ * {@code android.Manifest.permission#UPDATE_DEVICE_STATS} permission may
+ * <em>assign</em> blame to another UIDs.
* <p>
* Changes only take effect during subsequent calls to
* {@link #tagSocket(Socket)}.
- * <p>
- * To take effect, caller must hold
- * {@link android.Manifest.permission#UPDATE_DEVICE_STATS} permission.
- *
- * @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
+ @SuppressLint("Doclava125")
public static void setThreadStatsUid(int uid) {
NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
}
/**
+ * Get the active UID used when accounting {@link Socket} traffic originating
+ * from the current thread. Only one active tag per thread is supported.
+ * {@link #tagSocket(Socket)}.
+ *
+ * @see #setThreadStatsUid(int)
+ */
+ public static int getThreadStatsUid() {
+ return NetworkManagementSocketTagger.getThreadSocketStatsUid();
+ }
+
+ /**
* Set specific UID to use when accounting {@link Socket} traffic
* originating from the current thread as the calling UID. Designed for use
* when another application is performing operations on your behalf.
* <p>
* Changes only take effect during subsequent calls to
* {@link #tagSocket(Socket)}.
+ *
+ * @removed
+ * @deprecated use {@link #setThreadStatsUid(int)} instead.
*/
+ @Deprecated
public static void setThreadStatsUidSelf() {
setThreadStatsUid(android.os.Process.myUid());
}
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index fb54e69..d1c2799 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -47,6 +47,8 @@
/**
* Creates {@link NetworkStats} instances by parsing various {@code /proc/}
* files as needed.
+ *
+ * @hide
*/
public class NetworkStatsFactory {
private static final String TAG = "NetworkStatsFactory";
diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java
index 98fe770..cebc472 100644
--- a/services/core/java/com/android/server/net/NetworkStatsAccess.java
+++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java
@@ -174,7 +174,7 @@
AppOpsManager appOps = (AppOpsManager) context.getSystemService(
Context.APP_OPS_SERVICE);
- final int mode = appOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
+ final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
callingUid, callingPackage);
if (mode == AppOpsManager.MODE_DEFAULT) {
// The default behavior here is to check if PackageManager has given the app
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 961a451..ab52523 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -16,9 +16,9 @@
package com.android.server.net;
-import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
+import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.METERED_YES;
import static android.net.NetworkStats.ROAMING_NO;
@@ -42,10 +42,12 @@
import android.service.NetworkStatsCollectionProto;
import android.service.NetworkStatsCollectionStatsProto;
import android.telephony.SubscriptionPlan;
+import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.IntArray;
-import android.util.Pair;
+import android.util.MathUtils;
+import android.util.Range;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -106,6 +108,10 @@
reset();
}
+ public void clear() {
+ reset();
+ }
+
public void reset() {
mStats.clear();
mStartMillis = Long.MAX_VALUE;
@@ -187,6 +193,7 @@
*/
@VisibleForTesting
public static long multiplySafe(long value, long num, long den) {
+ if (den == 0) den = 1;
long x = value;
long y = num;
@@ -240,7 +247,10 @@
+ " is forbidden for caller " + callerUid);
}
- final int bucketEstimate = (int) ((end - start) / mBucketDuration);
+ // 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,
+ (180 * DateUtils.DAY_IN_MILLIS) / mBucketDuration);
final NetworkStatsHistory combined = new NetworkStatsHistory(
mBucketDuration, bucketEstimate, fields);
@@ -256,11 +266,11 @@
long collectEnd = end;
if (augmentEnd != SubscriptionPlan.TIME_UNKNOWN) {
- final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = augmentPlan.cycleIterator();
+ final Iterator<Range<ZonedDateTime>> it = augmentPlan.cycleIterator();
while (it.hasNext()) {
- final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next();
- final long cycleStart = cycle.first.toInstant().toEpochMilli();
- final long cycleEnd = cycle.second.toInstant().toEpochMilli();
+ final Range<ZonedDateTime> cycle = it.next();
+ final long cycleStart = cycle.getLower().toInstant().toEpochMilli();
+ final long cycleEnd = cycle.getUpper().toInstant().toEpochMilli();
if (cycleStart <= augmentEnd && augmentEnd < cycleEnd) {
augmentStart = cycleStart;
collectStart = Long.min(collectStart, augmentStart);
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index 741c206..d840873 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java
@@ -16,7 +16,7 @@
package com.android.server.net;
-import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
import static com.android.internal.util.Preconditions.checkArgument;
@@ -52,8 +52,6 @@
private static final String TAG = "NetworkStatsObservers";
private static final boolean LOGV = false;
- private static final long MIN_THRESHOLD_BYTES = 2 * MB_IN_BYTES;
-
private static final int MSG_REGISTER = 1;
private static final int MSG_UNREGISTER = 2;
private static final int MSG_UPDATE_STATS = 3;
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 4bee55e..a16dcf3 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -241,6 +241,20 @@
NetworkStats.Entry entry = null;
for (int i = 0; i < delta.size(); i++) {
entry = delta.getValues(i, entry);
+
+ // As a last-ditch sanity check, report any negative values and
+ // clamp them so recording below doesn't croak.
+ if (entry.isNegative()) {
+ if (mObserver != null) {
+ mObserver.foundNonMonotonic(delta, i, mCookie);
+ }
+ entry.rxBytes = Math.max(entry.rxBytes, 0);
+ entry.rxPackets = Math.max(entry.rxPackets, 0);
+ entry.txBytes = Math.max(entry.txBytes, 0);
+ entry.txPackets = Math.max(entry.txPackets, 0);
+ entry.operations = Math.max(entry.operations, 0);
+ }
+
final NetworkIdentitySet ident = ifaceIdent.get(entry.iface);
if (ident == null) {
unknownIfaces.add(entry.iface);
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index e5cf394..aba75dd 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -43,6 +43,7 @@
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.TrafficStats.KB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.os.Trace.TRACE_TAG_NETWORK;
import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
@@ -51,7 +52,6 @@
import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
-import static android.provider.Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE;
import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
@@ -70,6 +70,7 @@
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
+import android.annotation.NonNull;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.usage.NetworkStatsManager;
@@ -96,6 +97,7 @@
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TrafficStats;
+import android.os.BestClock;
import android.os.Binder;
import android.os.DropBoxManager;
import android.os.Environment;
@@ -108,12 +110,12 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.NetworkInterfaceProto;
import android.service.NetworkStatsServiceDumpProto;
-import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
@@ -122,10 +124,8 @@
import android.util.EventLog;
import android.util.Log;
import android.util.MathUtils;
-import android.util.NtpTrustedTime;
import android.util.Slog;
import android.util.SparseIntArray;
-import android.util.TrustedTime;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -137,12 +137,15 @@
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
import com.android.server.connectivity.Tethering;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.time.Clock;
+import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -153,7 +156,8 @@
*/
public class NetworkStatsService extends INetworkStatsService.Stub {
static final String TAG = "NetworkStats";
- static final boolean LOGV = false;
+ static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
+ static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
private static final int MSG_PERFORM_POLL = 1;
private static final int MSG_REGISTER_GLOBAL_ALERT = 2;
@@ -169,7 +173,7 @@
private final Context mContext;
private final INetworkManagementService mNetworkManager;
private final AlarmManager mAlarmManager;
- private final TrustedTime mTime;
+ private final Clock mClock;
private final TelephonyManager mTeleManager;
private final NetworkStatsSettings mSettings;
private final NetworkStatsObservers mStatsObservers;
@@ -206,7 +210,6 @@
*/
public interface NetworkStatsSettings {
public long getPollInterval();
- public long getTimeCacheMaxAge();
public boolean getSampleEnabled();
public boolean getAugmentEnabled();
@@ -281,20 +284,35 @@
private Handler mHandler;
private Handler.Callback mHandlerCallback;
- private boolean mSystemReady;
+ private volatile boolean mSystemReady;
private long mPersistThreshold = 2 * MB_IN_BYTES;
private long mGlobalAlertBytes;
- private static File getDefaultSystemDir() {
+ private static final long POLL_RATE_LIMIT_MS = 15_000;
+
+ private long mLastStatsSessionPoll;
+
+ /** Map from UID to number of opened sessions */
+ @GuardedBy("mOpenSessionCallsPerUid")
+ private final SparseIntArray mOpenSessionCallsPerUid = new SparseIntArray();
+
+ private final static int DUMP_STATS_SESSION_COUNT = 20;
+
+ private static @NonNull File getDefaultSystemDir() {
return new File(Environment.getDataDirectory(), "system");
}
- private static File getDefaultBaseDir() {
+ private static @NonNull File getDefaultBaseDir() {
File baseDir = new File(getDefaultSystemDir(), "netstats");
baseDir.mkdirs();
return baseDir;
}
+ private static @NonNull Clock getDefaultClock() {
+ return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
+ Clock.systemUTC());
+ }
+
public static NetworkStatsService create(Context context,
INetworkManagementService networkManager) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -303,7 +321,7 @@
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager,
- wakeLock, NtpTrustedTime.getInstance(context), TelephonyManager.getDefault(),
+ wakeLock, getDefaultClock(), TelephonyManager.getDefault(),
new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(),
getDefaultSystemDir(), getDefaultBaseDir());
@@ -317,13 +335,13 @@
@VisibleForTesting
NetworkStatsService(Context context, INetworkManagementService networkManager,
- AlarmManager alarmManager, PowerManager.WakeLock wakeLock, TrustedTime time,
+ AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
TelephonyManager teleManager, NetworkStatsSettings settings,
NetworkStatsObservers statsObservers, File systemDir, File baseDir) {
mContext = checkNotNull(context, "missing Context");
mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager");
- mTime = checkNotNull(time, "missing TrustedTime");
+ mClock = checkNotNull(clock, "missing Clock");
mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
mTeleManager = checkNotNull(teleManager, "missing TelephonyManager");
mWakeLock = checkNotNull(wakeLock, "missing WakeLock");
@@ -331,6 +349,9 @@
mSystemDir = checkNotNull(systemDir, "missing systemDir");
mBaseDir = checkNotNull(baseDir, "missing baseDir");
mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists();
+
+ LocalServices.addService(NetworkStatsManagerInternal.class,
+ new NetworkStatsManagerInternalImpl());
}
@VisibleForTesting
@@ -410,6 +431,7 @@
mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
}
+ @GuardedBy("mStatsLock")
private void shutdownLocked() {
mContext.unregisterReceiver(mTetherReceiver);
mContext.unregisterReceiver(mPollReceiver);
@@ -417,8 +439,7 @@
mContext.unregisterReceiver(mUserReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
- final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
- : System.currentTimeMillis();
+ final long currentTime = mClock.millis();
// persist any pending stats
mDevRecorder.forcePersistLocked(currentTime);
@@ -426,16 +447,10 @@
mUidRecorder.forcePersistLocked(currentTime);
mUidTagRecorder.forcePersistLocked(currentTime);
- mDevRecorder = null;
- mXtRecorder = null;
- mUidRecorder = null;
- mUidTagRecorder = null;
-
- mXtStatsCached = null;
-
mSystemReady = false;
}
+ @GuardedBy("mStatsLock")
private void maybeUpgradeLegacyStatsLocked() {
File file;
try {
@@ -507,10 +522,32 @@
return openSessionInternal(flags, callingPackage);
}
+ private boolean isRateLimitedForPoll(int callingUid) {
+ if (callingUid == android.os.Process.SYSTEM_UID) {
+ return false;
+ }
+
+ final long lastCallTime;
+ final long now = SystemClock.elapsedRealtime();
+ synchronized (mOpenSessionCallsPerUid) {
+ int calls = mOpenSessionCallsPerUid.get(callingUid, 0);
+ mOpenSessionCallsPerUid.put(callingUid, calls + 1);
+ lastCallTime = mLastStatsSessionPoll;
+ mLastStatsSessionPoll = now;
+ }
+
+ return now - lastCallTime < POLL_RATE_LIMIT_MS;
+ }
+
private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
assertBandwidthControlEnabled();
- if ((flags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) {
+ final int callingUid = Binder.getCallingUid();
+ final int usedFlags = isRateLimitedForPoll(callingUid)
+ ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
+ : flags;
+ if ((usedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
+ | NetworkStatsManager.FLAG_POLL_FORCE)) != 0) {
final long ident = Binder.clearCallingIdentity();
try {
performPoll(FLAG_PERSIST_ALL);
@@ -523,7 +560,7 @@
// for its lifetime; when caller closes only weak references remain.
return new INetworkStatsSession.Stub() {
- private final int mCallingUid = Binder.getCallingUid();
+ private final int mCallingUid = callingUid;
private final String mCallingPackage = callingPackage;
private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
callingPackage);
@@ -557,20 +594,20 @@
@Override
public NetworkStats getDeviceSummaryForNetwork(
NetworkTemplate template, long start, long end) {
- return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel,
+ return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
mCallingUid);
}
@Override
public NetworkStats getSummaryForNetwork(
NetworkTemplate template, long start, long end) {
- return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel,
+ return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
mCallingUid);
}
@Override
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
- return internalGetHistoryForNetwork(template, flags, fields, mAccessLevel,
+ return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel,
mCallingUid);
}
@@ -644,26 +681,16 @@
private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) {
SubscriptionPlan plan = null;
if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0
- && (template.getMatchRule() == NetworkTemplate.MATCH_MOBILE_ALL)
&& mSettings.getAugmentEnabled()) {
- Slog.d(TAG, "Resolving plan for " + template);
+ if (LOGD) Slog.d(TAG, "Resolving plan for " + template);
final long token = Binder.clearCallingIdentity();
try {
- final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class);
- final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- for (int subId : sm.getActiveSubscriptionIdList()) {
- if (template.matchesSubscriberId(tm.getSubscriberId(subId))) {
- Slog.d(TAG, "Found active matching subId " + subId);
- final List<SubscriptionPlan> plans = sm.getSubscriptionPlans(subId);
- if (!plans.isEmpty()) {
- plan = plans.get(0);
- }
- }
- }
+ plan = LocalServices.getService(NetworkPolicyManagerInternal.class)
+ .getSubscriptionPlan(template);
} finally {
Binder.restoreCallingIdentity(token);
}
- Slog.d(TAG, "Resolved to plan " + plan);
+ if (LOGD) Slog.d(TAG, "Resolved to plan " + plan);
}
return plan;
}
@@ -705,12 +732,8 @@
}
}
- @Override
- public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
- // Special case - since this is for internal use only, don't worry about
- // a full access level check and just require the signature/privileged
- // permission.
- mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+ private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
+ assertSystemReady();
assertBandwidthControlEnabled();
// NOTE: if callers want to get non-augmented data, they should go
@@ -720,6 +743,18 @@
NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes();
}
+ private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
+ assertSystemReady();
+ assertBandwidthControlEnabled();
+
+ final NetworkStatsCollection uidComplete;
+ synchronized (mStatsLock) {
+ uidComplete = mUidRecorder.getOrLoadCompleteLocked();
+ }
+ return uidComplete.getSummary(template, start, end, NetworkStatsAccess.Level.DEVICE,
+ android.os.Process.SYSTEM_UID);
+ }
+
@Override
public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
if (Binder.getCallingUid() != uid) {
@@ -794,10 +829,8 @@
}
}
- @Override
- public void setUidForeground(int uid, boolean uidForeground) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
+ @VisibleForTesting
+ void setUidForeground(int uid, boolean uidForeground) {
synchronized (mStatsLock) {
final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
@@ -834,9 +867,7 @@
}
}
- @Override
- public void advisePersistThreshold(long thresholdBytes) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ private void advisePersistThreshold(long thresholdBytes) {
assertBandwidthControlEnabled();
// clamp threshold into safe range
@@ -847,8 +878,7 @@
}
// update and persist if beyond new thresholds
- final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
- : System.currentTimeMillis();
+ final long currentTime = mClock.millis();
synchronized (mStatsLock) {
if (!mSystemReady) return;
@@ -927,6 +957,7 @@
* reflect current {@link #mPersistThreshold} value. Always defers to
* {@link Global} values when defined.
*/
+ @GuardedBy("mStatsLock")
private void updatePersistThresholdsLocked() {
mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
@@ -1047,6 +1078,7 @@
* are active on a single {@code iface}, they are combined under a single
* {@link NetworkIdentitySet}.
*/
+ @GuardedBy("mStatsLock")
private void updateIfacesLocked(Network[] defaultNetworks) {
if (!mSystemReady) return;
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
@@ -1148,30 +1180,47 @@
return ident;
}
+ @GuardedBy("mStatsLock")
private void recordSnapshotLocked(long currentTime) throws RemoteException {
// snapshot and record current counters; read UID stats first to
// avoid over counting dev stats.
+ Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotUid");
final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL);
+ Trace.traceEnd(TRACE_TAG_NETWORK);
+ Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt");
final NetworkStats xtSnapshot = getNetworkStatsXt();
+ Trace.traceEnd(TRACE_TAG_NETWORK);
+ Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev");
final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
+ Trace.traceEnd(TRACE_TAG_NETWORK);
// Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats
// providers that isn't already counted by dev and XT stats.
+ Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotTether");
final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE);
+ Trace.traceEnd(TRACE_TAG_NETWORK);
xtSnapshot.combineAllValues(tetherSnapshot);
devSnapshot.combineAllValues(tetherSnapshot);
// For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
// can't be reattributed to responsible apps.
+ Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev");
mDevRecorder.recordSnapshotLocked(
devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+ Trace.traceEnd(TRACE_TAG_NETWORK);
+ Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt");
mXtRecorder.recordSnapshotLocked(
xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+ Trace.traceEnd(TRACE_TAG_NETWORK);
// For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
VpnInfo[] vpnArray = mConnManager.getAllVpnInfo();
+ Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid");
mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
+ Trace.traceEnd(TRACE_TAG_NETWORK);
+ Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag");
mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
+ Trace.traceEnd(TRACE_TAG_NETWORK);
// We need to make copies of member fields that are sent to the observer to avoid
// a race condition between the service handler thread and the observer's
@@ -1183,9 +1232,9 @@
* Bootstrap initial stats snapshot, usually during {@link #systemReady()}
* so we have baseline values without double-counting.
*/
+ @GuardedBy("mStatsLock")
private void bootstrapStatsLocked() {
- final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
- : System.currentTimeMillis();
+ final long currentTime = mClock.millis();
try {
recordSnapshotLocked(currentTime);
@@ -1197,11 +1246,6 @@
}
private void performPoll(int flags) {
- // try refreshing time source when stale
- if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
- mTime.forceRefresh();
- }
-
synchronized (mStatsLock) {
mWakeLock.acquire();
@@ -1217,19 +1261,18 @@
* Periodic poll operation, reading current statistics and recording into
* {@link NetworkStatsHistory}.
*/
+ @GuardedBy("mStatsLock")
private void performPollLocked(int flags) {
if (!mSystemReady) return;
if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
-
- final long startRealtime = SystemClock.elapsedRealtime();
+ Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked");
final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
// TODO: consider marking "untrusted" times in historical stats
- final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
- : System.currentTimeMillis();
+ final long currentTime = mClock.millis();
try {
recordSnapshotLocked(currentTime);
@@ -1242,6 +1285,7 @@
}
// persist any pending data depending on requested flags
+ Trace.traceBegin(TRACE_TAG_NETWORK, "[persisting]");
if (persistForce) {
mDevRecorder.forcePersistLocked(currentTime);
mXtRecorder.forcePersistLocked(currentTime);
@@ -1257,11 +1301,7 @@
mUidTagRecorder.maybePersistLocked(currentTime);
}
}
-
- if (LOGV) {
- final long duration = SystemClock.elapsedRealtime() - startRealtime;
- Slog.v(TAG, "performPollLocked() took " + duration + "ms");
- }
+ Trace.traceEnd(TRACE_TAG_NETWORK);
if (mSettings.getSampleEnabled()) {
// sample stats after each full poll
@@ -1273,14 +1313,17 @@
updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
READ_NETWORK_USAGE_HISTORY);
+
+ Trace.traceEnd(TRACE_TAG_NETWORK);
}
/**
* Sample recent statistics summary into {@link EventLog}.
*/
+ @GuardedBy("mStatsLock")
private void performSampleLocked() {
// TODO: migrate trustedtime fixes to separate binary log events
- final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
+ final long currentTime = mClock.millis();
NetworkTemplate template;
NetworkStats.Entry devTotal;
@@ -1297,7 +1340,7 @@
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- trustedTime);
+ currentTime);
// collect wifi sample
template = buildTemplateWifiWildcard();
@@ -1309,12 +1352,13 @@
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- trustedTime);
+ currentTime);
}
/**
* Clean up {@link #mUidRecorder} after UID is removed.
*/
+ @GuardedBy("mStatsLock")
private void removeUidsLocked(int... uids) {
if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
@@ -1333,6 +1377,7 @@
/**
* Clean up {@link #mUidRecorder} after user is removed.
*/
+ @GuardedBy("mStatsLock")
private void removeUserLocked(int userId) {
if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
@@ -1349,6 +1394,43 @@
removeUidsLocked(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);
+ }
+ }
+
+ @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
protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
@@ -1428,6 +1510,30 @@
}
pw.decreaseIndent();
+ // Get the top openSession callers
+ final SparseIntArray calls;
+ synchronized (mOpenSessionCallsPerUid) {
+ calls = mOpenSessionCallsPerUid.clone();
+ }
+
+ final int N = calls.size();
+ final long[] values = new long[N];
+ for (int j = 0; j < N; j++) {
+ values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j);
+ }
+ Arrays.sort(values);
+
+ pw.println("Top openSession callers (uid=count):");
+ pw.increaseIndent();
+ final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT);
+ for (int j = N - 1; j >= end; j--) {
+ final int uid = (int) (values[j] & 0xffffffff);
+ final int count = (int) (values[j] >> 32);
+ pw.print(uid); pw.print("="); pw.println(count);
+ }
+ pw.decreaseIndent();
+ pw.println();
+
pw.println("Dev stats:");
pw.increaseIndent();
mDevRecorder.dumpLocked(pw, fullHistory);
@@ -1454,6 +1560,7 @@
}
}
+ @GuardedBy("mStatsLock")
private void dumpProtoLocked(FileDescriptor fd) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
@@ -1576,6 +1683,12 @@
}
}
+ private void assertSystemReady() {
+ if (!mSystemReady) {
+ throw new IllegalStateException("System not ready");
+ }
+ }
+
private void assertBandwidthControlEnabled() {
if (!isBandwidthControlEnabled()) {
throw new IllegalStateException("Bandwidth module disabled");
@@ -1598,7 +1711,7 @@
@Override
public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
int rightIndex, String cookie) {
- Log.w(TAG, "found non-monotonic values; saving to dropbox");
+ Log.w(TAG, "Found non-monotonic values; saving to dropbox");
// record error for debugging
final StringBuilder builder = new StringBuilder();
@@ -1607,9 +1720,21 @@
builder.append("left=").append(left).append('\n');
builder.append("right=").append(right).append('\n');
- final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
- Context.DROPBOX_SERVICE);
- dropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
+ mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
+ builder.toString());
+ }
+
+ @Override
+ public void foundNonMonotonic(
+ NetworkStats stats, int statsIndex, String cookie) {
+ Log.w(TAG, "Found non-monotonic values; saving to dropbox");
+
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Found non-monotonic " + cookie + " values at [" + statsIndex + "]\n");
+ builder.append("stats=").append(stats).append('\n');
+
+ mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
+ builder.toString());
}
}
@@ -1638,10 +1763,6 @@
return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
}
@Override
- public long getTimeCacheMaxAge() {
- return getGlobalLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
- }
- @Override
public long getGlobalAlertBytes(long def) {
return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
}