summaryrefslogtreecommitdiffstats
path: root/services/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com')
-rw-r--r--services/java/com/android/server/NetworkManagementService.java115
-rw-r--r--services/java/com/android/server/ThrottleService.java3
-rw-r--r--services/java/com/android/server/net/NetworkIdentity.java227
-rw-r--r--services/java/com/android/server/net/NetworkIdentitySet.java (renamed from services/java/com/android/server/net/InterfaceIdentity.java)49
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java60
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java333
6 files changed, 356 insertions, 431 deletions
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index bb0c671..d5bdd21 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -16,6 +16,10 @@
package com.android.server;
+import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.INetworkManagementEventObserver;
@@ -37,6 +41,7 @@ import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Inet4Address;
@@ -59,8 +64,9 @@ class NetworkManagementService extends INetworkManagementService.Stub {
private static final int ADD = 1;
private static final int REMOVE = 2;
- /** Base path to UID-granularity network statistics. */
- private static final File PATH_PROC_UID_STAT = new File("/proc/uid_stat");
+ @Deprecated
+ private static final File STATS_UIDSTAT = new File("/proc/uid_stat");
+ private static final File STATS_NETFILTER = new File("/proc/net/xt_qtaguid/stats");
class NetdResponseCode {
public static final int InterfaceListResult = 110;
@@ -899,7 +905,7 @@ class NetworkManagementService extends INetworkManagementService.Stub {
for (String iface : ifaces) {
final long rx = getInterfaceCounter(iface, true);
final long tx = getInterfaceCounter(iface, false);
- stats.addEntry(iface, NetworkStats.UID_ALL, rx, tx);
+ stats.addEntry(iface, UID_ALL, TAG_NONE, rx, tx);
}
return stats;
@@ -910,16 +916,11 @@ class NetworkManagementService extends INetworkManagementService.Stub {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
- final String[] knownUids = PATH_PROC_UID_STAT.list();
- final NetworkStats stats = new NetworkStats(
- SystemClock.elapsedRealtime(), knownUids.length);
-
- for (String uid : knownUids) {
- final int uidInt = Integer.parseInt(uid);
- collectNetworkStatsDetail(stats, uidInt);
+ if (STATS_NETFILTER.exists()) {
+ return getNetworkStatsDetailNetfilter(UID_ALL);
+ } else {
+ return getNetworkStatsDetailUidstat(UID_ALL);
}
-
- return stats;
}
@Override
@@ -929,19 +930,89 @@ class NetworkManagementService extends INetworkManagementService.Stub {
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
}
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- collectNetworkStatsDetail(stats, uid);
+ if (STATS_NETFILTER.exists()) {
+ return getNetworkStatsDetailNetfilter(uid);
+ } else {
+ return getNetworkStatsDetailUidstat(uid);
+ }
+ }
+
+ /**
+ * Build {@link NetworkStats} with detailed UID statistics.
+ */
+ private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) {
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(STATS_NETFILTER));
+
+ // assumes format from kernel:
+ // idx iface acct_tag_hex uid_tag_int rx_bytes tx_bytes
+
+ // skip first line, which is legend
+ String line = reader.readLine();
+ while ((line = reader.readLine()) != null) {
+ final StringTokenizer t = new StringTokenizer(line);
+
+ final String idx = t.nextToken();
+ final String iface = t.nextToken();
+
+ try {
+ // TODO: kernel currently emits tag in upper half of long;
+ // eventually switch to directly using int.
+ final int tag = (int) (Long.parseLong(t.nextToken().substring(2), 16) >> 32);
+ final int uid = Integer.parseInt(t.nextToken());
+ final long rx = Long.parseLong(t.nextToken());
+ final long tx = Long.parseLong(t.nextToken());
+
+ if (limitUid == UID_ALL || limitUid == uid) {
+ stats.addEntry(iface, uid, tag, rx, tx);
+ if (tag != TAG_NONE) {
+ // proc also counts tagged data in generic tag, so
+ // we subtract it here to avoid double-counting.
+ stats.combineEntry(iface, uid, TAG_NONE, -rx, -tx);
+ }
+ }
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "problem parsing stats for idx " + idx + ": " + e);
+ }
+ }
+ } catch (IOException e) {
+ Slog.w(TAG, "problem parsing stats: " + e);
+ } finally {
+ IoUtils.closeQuietly(reader);
+ }
+
return stats;
}
- private void collectNetworkStatsDetail(NetworkStats stats, int uid) {
- // TODO: kernel module will provide interface-level stats in future
- // TODO: migrate these stats to come across netd in bulk, instead of all
- // these individual file reads.
- final File uidPath = new File(PATH_PROC_UID_STAT, Integer.toString(uid));
- final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
- final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
- stats.addEntry(NetworkStats.IFACE_ALL, uid, rx, tx);
+ /**
+ * Build {@link NetworkStats} with detailed UID statistics.
+ *
+ * @deprecated since this uses older "uid_stat" data, and doesn't provide
+ * tag-level granularity or additional variables.
+ */
+ @Deprecated
+ private NetworkStats getNetworkStatsDetailUidstat(int limitUid) {
+ final String[] knownUids;
+ if (limitUid == UID_ALL) {
+ knownUids = STATS_UIDSTAT.list();
+ } else {
+ knownUids = new String[] { String.valueOf(limitUid) };
+ }
+
+ final NetworkStats stats = new NetworkStats(
+ SystemClock.elapsedRealtime(), knownUids.length);
+ for (String uid : knownUids) {
+ final int uidInt = Integer.parseInt(uid);
+ final File uidPath = new File(STATS_UIDSTAT, uid);
+ final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
+ final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
+ stats.addEntry(IFACE_ALL, uidInt, TAG_NONE, rx, tx);
+ }
+
+ return stats;
}
public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 510ff62..7266d7d 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -533,7 +533,8 @@ public class ThrottleService extends IThrottleManager.Stub {
long incWrite = 0;
try {
final NetworkStats stats = mNMService.getNetworkStatsSummary();
- final int index = stats.findIndex(mIface, NetworkStats.UID_ALL);
+ final int index = stats.findIndex(
+ mIface, NetworkStats.UID_ALL, NetworkStats.TAG_NONE);
if (index != -1) {
incRead = stats.rx[index] - mLastRead;
diff --git a/services/java/com/android/server/net/NetworkIdentity.java b/services/java/com/android/server/net/NetworkIdentity.java
deleted file mode 100644
index 4a207f7..0000000
--- a/services/java/com/android/server/net/NetworkIdentity.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.ConnectivityManager.TYPE_WIMAX;
-import static android.net.ConnectivityManager.isNetworkTypeMobile;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_3G_LOWER;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_4G;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL;
-import static android.net.TrafficStats.TEMPLATE_WIFI;
-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.content.Context;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.NetworkState;
-import android.telephony.TelephonyManager;
-
-import com.android.internal.util.Objects;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.net.ProtocolException;
-
-/**
- * Identity of a {@link NetworkInfo}, defined by network type and billing
- * relationship (such as IMSI).
- *
- * @hide
- */
-public class NetworkIdentity {
- private static final int VERSION_CURRENT = 1;
-
- public final int type;
- public final int subType;
- public final String subscriberId;
-
- public NetworkIdentity(int type, int subType, String subscriberId) {
- this.type = type;
- this.subType = subType;
- this.subscriberId = subscriberId;
- }
-
- public NetworkIdentity(DataInputStream in) throws IOException {
- final int version = in.readInt();
- switch (version) {
- case VERSION_CURRENT: {
- type = in.readInt();
- subType = in.readInt();
- subscriberId = readOptionalString(in);
- break;
- }
- default: {
- throw new ProtocolException("unexpected version: " + version);
- }
- }
- }
-
- public void writeToStream(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_CURRENT);
- out.writeInt(type);
- out.writeInt(subType);
- writeOptionalString(out, subscriberId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(type, subType, subscriberId);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof NetworkIdentity) {
- final NetworkIdentity ident = (NetworkIdentity) obj;
- return type == ident.type && subType == ident.subType
- && Objects.equal(subscriberId, ident.subscriberId);
- }
- return false;
- }
-
- @Override
- public String toString() {
- final String typeName = ConnectivityManager.getNetworkTypeName(type);
- final String subTypeName;
- if (ConnectivityManager.isNetworkTypeMobile(type)) {
- subTypeName = TelephonyManager.getNetworkTypeName(subType);
- } else {
- subTypeName = Integer.toString(subType);
- }
-
- return "[type=" + typeName + ", subType=" + subTypeName + ", subId=" + subscriberId + "]";
- }
-
- /**
- * Test if this network matches the given template and IMEI.
- */
- public boolean matchesTemplate(int networkTemplate, String subscriberId) {
- switch (networkTemplate) {
- case TEMPLATE_MOBILE_ALL:
- return matchesMobile(subscriberId);
- case TEMPLATE_MOBILE_3G_LOWER:
- return matchesMobile3gLower(subscriberId);
- case TEMPLATE_MOBILE_4G:
- return matchesMobile4g(subscriberId);
- case TEMPLATE_WIFI:
- return matchesWifi();
- default:
- throw new IllegalArgumentException("unknown network template");
- }
- }
-
- /**
- * Check if mobile network with matching IMEI. Also matches
- * {@link #TYPE_WIMAX}.
- */
- private boolean matchesMobile(String subscriberId) {
- if (isNetworkTypeMobile(type) && Objects.equal(this.subscriberId, subscriberId)) {
- return true;
- } else if (type == TYPE_WIMAX) {
- return true;
- }
- return false;
- }
-
- /**
- * Check if mobile network classified 3G or lower with matching IMEI.
- */
- private boolean matchesMobile3gLower(String subscriberId) {
- if (isNetworkTypeMobile(type)
- && Objects.equal(this.subscriberId, subscriberId)) {
- switch (getNetworkClass(subType)) {
- 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 IMEI. Also matches
- * {@link #TYPE_WIMAX}.
- */
- private boolean matchesMobile4g(String subscriberId) {
- if (isNetworkTypeMobile(type)
- && Objects.equal(this.subscriberId, subscriberId)) {
- switch (getNetworkClass(subType)) {
- case NETWORK_CLASS_4_G:
- return true;
- }
- } else if (type == TYPE_WIMAX) {
- return true;
- }
- return false;
- }
-
- /**
- * Check if matches Wi-Fi network template.
- */
- private boolean matchesWifi() {
- if (type == TYPE_WIFI) {
- return true;
- }
- return false;
- }
-
- /**
- * Build a {@link NetworkIdentity} from the given {@link NetworkState},
- * assuming that any mobile networks are using the current IMSI.
- */
- public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
- final int type = state.networkInfo.getType();
- final int subType = state.networkInfo.getSubtype();
-
- // TODO: consider moving subscriberId over to LinkCapabilities, so it
- // comes from an authoritative source.
-
- final String subscriberId;
- if (isNetworkTypeMobile(type)) {
- final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE);
- subscriberId = telephony.getSubscriberId();
- } else {
- subscriberId = null;
- }
- return new NetworkIdentity(type, subType, subscriberId);
- }
-
- private static void writeOptionalString(DataOutputStream out, String value) throws IOException {
- if (value != null) {
- out.writeByte(1);
- out.writeUTF(value);
- } else {
- out.writeByte(0);
- }
- }
-
- private static String readOptionalString(DataInputStream in) throws IOException {
- if (in.readByte() != 0) {
- return in.readUTF();
- } else {
- return null;
- }
- }
-
-}
diff --git a/services/java/com/android/server/net/InterfaceIdentity.java b/services/java/com/android/server/net/NetworkIdentitySet.java
index ff86581..757d3bc 100644
--- a/services/java/com/android/server/net/InterfaceIdentity.java
+++ b/services/java/com/android/server/net/NetworkIdentitySet.java
@@ -16,6 +16,8 @@
package com.android.server.net;
+import android.net.NetworkIdentity;
+
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -28,19 +30,23 @@ import java.util.HashSet;
*
* @hide
*/
-public class InterfaceIdentity extends HashSet<NetworkIdentity> {
- private static final int VERSION_CURRENT = 1;
+public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
+ private static final int VERSION_INIT = 1;
- public InterfaceIdentity() {
+ public NetworkIdentitySet() {
}
- public InterfaceIdentity(DataInputStream in) throws IOException {
+ public NetworkIdentitySet(DataInputStream in) throws IOException {
final int version = in.readInt();
switch (version) {
- case VERSION_CURRENT: {
+ case VERSION_INIT: {
final int size = in.readInt();
for (int i = 0; i < size; i++) {
- add(new NetworkIdentity(in));
+ final int ignoredVersion = in.readInt();
+ final int type = in.readInt();
+ final int subType = in.readInt();
+ final String subscriberId = readOptionalString(in);
+ add(new NetworkIdentity(type, subType, subscriberId));
}
break;
}
@@ -51,23 +57,30 @@ public class InterfaceIdentity extends HashSet<NetworkIdentity> {
}
public void writeToStream(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_CURRENT);
+ out.writeInt(VERSION_INIT);
out.writeInt(size());
for (NetworkIdentity ident : this) {
- ident.writeToStream(out);
+ out.writeInt(VERSION_INIT);
+ out.writeInt(ident.getType());
+ out.writeInt(ident.getSubType());
+ writeOptionalString(out, ident.getSubscriberId());
}
}
- /**
- * Test if any {@link NetworkIdentity} on this interface matches the given
- * template and IMEI.
- */
- public boolean matchesTemplate(int networkTemplate, String subscriberId) {
- for (NetworkIdentity ident : this) {
- if (ident.matchesTemplate(networkTemplate, subscriberId)) {
- return true;
- }
+ private static void writeOptionalString(DataOutputStream out, String value) throws IOException {
+ if (value != null) {
+ out.writeByte(1);
+ out.writeUTF(value);
+ } else {
+ out.writeByte(0);
+ }
+ }
+
+ private static String readOptionalString(DataInputStream in) throws IOException {
+ if (in.readByte() != 0) {
+ return in.readUTF();
+ } else {
+ return null;
}
- return false;
}
}
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 43f3c63..ada9ba4 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -23,6 +23,7 @@ import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_LIMIT;
@@ -36,10 +37,9 @@ import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.dumpPolicy;
import static android.net.NetworkPolicyManager.dumpRules;
import static android.net.NetworkPolicyManager.isUidValidForPolicy;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_3G_LOWER;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_4G;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL;
-import static android.net.TrafficStats.isNetworkTemplateMobile;
+import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
+import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
+import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
@@ -61,9 +61,11 @@ import android.net.IConnectivityManager;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
+import android.net.NetworkIdentity;
import android.net.NetworkPolicy;
import android.net.NetworkState;
import android.net.NetworkStats;
+import android.net.NetworkTemplate;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
@@ -84,7 +86,6 @@ import android.util.Xml;
import com.android.internal.R;
import com.android.internal.os.AtomicFile;
import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.Objects;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
@@ -353,10 +354,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final long total;
try {
final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
- start, end, policy.networkTemplate, policy.subscriberId);
+ policy.template, start, end);
total = stats.rx[0] + stats.tx[0];
} catch (RemoteException e) {
- Slog.w(TAG, "problem reading summary for template " + policy.networkTemplate);
+ Slog.w(TAG, "problem reading summary for template " + policy.template);
continue;
}
@@ -380,8 +381,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* notification of a specific type, like {@link #TYPE_LIMIT}.
*/
private String buildNotificationTag(NetworkPolicy policy, int type) {
- // TODO: consider splicing subscriberId hash into mix
- return TAG + ":" + policy.networkTemplate + ":" + type;
+ return TAG + ":" + policy.template.hashCode() + ":" + type;
}
/**
@@ -408,7 +408,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final Intent intent = new Intent(ACTION_DATA_USAGE_WARNING);
intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.networkTemplate);
+ intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule());
builder.setContentIntent(PendingIntent.getActivity(
mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
break;
@@ -416,11 +416,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
case TYPE_LIMIT: {
final String title;
final String body = res.getString(R.string.data_usage_limit_body);
- switch (policy.networkTemplate) {
- case TEMPLATE_MOBILE_3G_LOWER:
+ switch (policy.template.getMatchRule()) {
+ case MATCH_MOBILE_3G_LOWER:
title = res.getString(R.string.data_usage_3g_limit_title);
break;
- case TEMPLATE_MOBILE_4G:
+ case MATCH_MOBILE_4G:
title = res.getString(R.string.data_usage_4g_limit_title);
break;
default:
@@ -435,7 +435,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final Intent intent = new Intent(ACTION_DATA_USAGE_LIMIT);
intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.networkTemplate);
+ intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule());
builder.setContentIntent(PendingIntent.getActivity(
mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
break;
@@ -521,7 +521,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// collect all active ifaces that match this template
ifaceList.clear();
for (NetworkIdentity ident : networks.keySet()) {
- if (ident.matchesTemplate(policy.networkTemplate, policy.subscriberId)) {
+ if (policy.template.matches(ident)) {
final String iface = networks.get(ident);
ifaceList.add(iface);
}
@@ -554,11 +554,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final NetworkStats stats;
final long total;
try {
- stats = mNetworkStats.getSummaryForNetwork(
- start, end, policy.networkTemplate, policy.subscriberId);
+ stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end);
total = stats.rx[0] + stats.tx[0];
} catch (RemoteException e) {
- Slog.w(TAG, "problem reading summary for template " + policy.networkTemplate);
+ Slog.w(TAG, "problem reading summary for template " + policy.template);
continue;
}
@@ -603,12 +602,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private void ensureActiveMobilePolicyLocked() {
if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
final String subscriberId = getActiveSubscriberId();
+ final NetworkIdentity probeIdent = new NetworkIdentity(
+ TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId);
// examine to see if any policy is defined for active mobile
boolean mobileDefined = false;
for (NetworkPolicy policy : mNetworkPolicy) {
- if (isNetworkTemplateMobile(policy.networkTemplate)
- && Objects.equal(subscriberId, policy.subscriberId)) {
+ if (policy.template.matches(probeIdent)) {
mobileDefined = true;
}
}
@@ -624,8 +624,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
time.setToNow();
final int cycleDay = time.monthDay;
- mNetworkPolicy.add(new NetworkPolicy(
- TEMPLATE_MOBILE_ALL, subscriberId, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED));
+ final NetworkTemplate template = new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId);
+ mNetworkPolicy.add(
+ new NetworkPolicy(template, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED));
writePolicyLocked();
}
}
@@ -658,8 +659,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
- mNetworkPolicy.add(new NetworkPolicy(
- networkTemplate, subscriberId, cycleDay, warningBytes, limitBytes));
+ final NetworkTemplate template = new NetworkTemplate(
+ networkTemplate, subscriberId);
+ mNetworkPolicy.add(
+ new NetworkPolicy(template, cycleDay, warningBytes, limitBytes));
} else if (TAG_UID_POLICY.equals(tag)) {
final int uid = readIntAttribute(in, ATTR_UID);
@@ -701,10 +704,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// write all known network policies
for (NetworkPolicy policy : mNetworkPolicy) {
+ final NetworkTemplate template = policy.template;
+
out.startTag(null, TAG_NETWORK_POLICY);
- writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, policy.networkTemplate);
- if (policy.subscriberId != null) {
- out.attribute(null, ATTR_SUBSCRIBER_ID, policy.subscriberId);
+ writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
+ final String subscriberId = template.getSubscriberId();
+ if (subscriberId != null) {
+ out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
}
writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 0a84bc7..54a806a 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -22,6 +22,7 @@ import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.SHUTDOWN;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
@@ -45,10 +46,12 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.net.IConnectivityManager;
import android.net.INetworkStatsService;
+import android.net.NetworkIdentity;
import android.net.NetworkInfo;
import android.net.NetworkState;
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
@@ -63,8 +66,8 @@ import android.util.SparseArray;
import android.util.TrustedTime;
import com.android.internal.os.AtomicFile;
-import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -76,9 +79,9 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ProtocolException;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import libcore.io.IoUtils;
@@ -93,7 +96,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/** File header magic number: "ANET" */
private static final int FILE_MAGIC = 0x414E4554;
- private static final int VERSION_CURRENT = 1;
+ private static final int VERSION_NETWORK_INIT = 1;
+ private static final int VERSION_UID_INIT = 1;
+ private static final int VERSION_UID_WITH_IDENT = 2;
private final Context mContext;
private final INetworkManagementService mNetworkManager;
@@ -112,6 +117,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private PendingIntent mPollIntent;
// TODO: listen for kernel push events through netd instead of polling
+ // TODO: watch for UID uninstall, and transfer stats into single bucket
private static final long KB_IN_BYTES = 1024;
private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES;
@@ -132,13 +138,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final Object mStatsLock = new Object();
- /** Set of active ifaces during this boot. */
- private HashMap<String, InterfaceIdentity> mActiveIface = Maps.newHashMap();
-
- /** Set of historical stats for known ifaces. */
- private HashMap<InterfaceIdentity, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
+ /** Set of currently active ifaces. */
+ private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
+ /** Set of historical stats for known networks. */
+ private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
/** Set of historical stats for known UIDs. */
- private SparseArray<NetworkStatsHistory> mUidStats = new SparseArray<NetworkStatsHistory>();
+ private HashMap<NetworkIdentitySet, SparseArray<NetworkStatsHistory>> mUidStats =
+ Maps.newHashMap();
/** Flag if {@link #mUidStats} have been loaded from disk. */
private boolean mUidStatsLoaded = false;
@@ -251,17 +257,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
@Override
- public NetworkStatsHistory getHistoryForNetwork(int networkTemplate) {
+ public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
synchronized (mStatsLock) {
// combine all interfaces that match template
- final String subscriberId = getActiveSubscriberId();
final NetworkStatsHistory combined = new NetworkStatsHistory(
mSettings.getNetworkBucketDuration(), estimateNetworkBuckets());
- for (InterfaceIdentity ident : mNetworkStats.keySet()) {
- final NetworkStatsHistory history = mNetworkStats.get(ident);
- if (ident.matchesTemplate(networkTemplate, subscriberId)) {
+ for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
+ if (templateMatches(template, ident)) {
+ final NetworkStatsHistory history = mNetworkStats.get(ident);
combined.recordEntireHistory(history);
}
}
@@ -270,19 +275,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
@Override
- public NetworkStatsHistory getHistoryForUid(int uid, int networkTemplate) {
+ public NetworkStatsHistory getHistoryForUid(NetworkTemplate template, int uid) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
synchronized (mStatsLock) {
- // TODO: combine based on template, if we store that granularity
ensureUidStatsLoadedLocked();
- return mUidStats.get(uid);
+
+ // combine all interfaces that match template
+ final NetworkStatsHistory combined = new NetworkStatsHistory(
+ mSettings.getUidBucketDuration(), estimateUidBuckets());
+ for (NetworkIdentitySet ident : mUidStats.keySet()) {
+ if (templateMatches(template, ident)) {
+ final NetworkStatsHistory history = mUidStats.get(ident).get(uid);
+ if (history != null) {
+ combined.recordEntireHistory(history);
+ }
+ }
+ }
+ return combined;
}
}
@Override
- public NetworkStats getSummaryForNetwork(
- long start, long end, int networkTemplate, String subscriberId) {
+ public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
synchronized (mStatsLock) {
@@ -291,9 +306,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
long[] networkTotal = new long[2];
// combine total from all interfaces that match template
- for (InterfaceIdentity ident : mNetworkStats.keySet()) {
- final NetworkStatsHistory history = mNetworkStats.get(ident);
- if (ident.matchesTemplate(networkTemplate, subscriberId)) {
+ for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
+ if (templateMatches(template, ident)) {
+ final NetworkStatsHistory history = mNetworkStats.get(ident);
networkTotal = history.getTotalData(start, end, networkTotal);
rx += networkTotal[0];
tx += networkTotal[1];
@@ -301,30 +316,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
final NetworkStats stats = new NetworkStats(end - start, 1);
- stats.addEntry(IFACE_ALL, UID_ALL, rx, tx);
+ stats.addEntry(IFACE_ALL, UID_ALL, TAG_NONE, rx, tx);
return stats;
}
}
@Override
- public NetworkStats getSummaryForAllUid(long start, long end, int networkTemplate) {
+ public NetworkStats getSummaryForAllUid(NetworkTemplate template, long start, long end) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
- // TODO: apply networktemplate once granular uid stats are stored.
-
synchronized (mStatsLock) {
ensureUidStatsLoadedLocked();
- final int size = mUidStats.size();
- final NetworkStats stats = new NetworkStats(end - start, size);
-
+ final NetworkStats stats = new NetworkStats(end - start, 24);
long[] total = new long[2];
- for (int i = 0; i < size; i++) {
- final int uid = mUidStats.keyAt(i);
- final NetworkStatsHistory history = mUidStats.valueAt(i);
- total = history.getTotalData(start, end, total);
- stats.addEntry(IFACE_ALL, uid, total[0], total[1]);
+
+ for (NetworkIdentitySet ident : mUidStats.keySet()) {
+ if (templateMatches(template, ident)) {
+ final SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
+ for (int i = 0; i < uidStats.size(); i++) {
+ final int uid = uidStats.keyAt(i);
+ final NetworkStatsHistory history = uidStats.valueAt(i);
+ total = history.getTotalData(start, end, total);
+ stats.combineEntry(IFACE_ALL, uid, TAG_NONE, total[0], total[1]);
+ }
+ }
}
+
return stats;
}
}
@@ -352,7 +370,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// permission above.
synchronized (mStatsLock) {
// TODO: acquire wakelock while performing poll
- performPollLocked(true);
+ performPollLocked(true, false);
}
}
};
@@ -371,7 +389,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* Inspect all current {@link NetworkState} to derive mapping from {@code
* iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
* are active on a single {@code iface}, they are combined under a single
- * {@link InterfaceIdentity}.
+ * {@link NetworkIdentitySet}.
*/
private void updateIfacesLocked() {
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
@@ -379,7 +397,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// take one last stats snapshot before updating iface mapping. this
// isn't perfect, since the kernel may already be counting traffic from
// the updated network.
- performPollLocked(false);
+ performPollLocked(false, false);
final NetworkState[] states;
try {
@@ -390,13 +408,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
// rebuild active interfaces based on connected networks
- mActiveIface.clear();
+ mActiveIfaces.clear();
for (NetworkState state : states) {
if (state.networkInfo.isConnected()) {
// collect networks under their parent interfaces
final String iface = state.linkProperties.getInterfaceName();
- final InterfaceIdentity ident = findOrCreateInterfaceLocked(iface);
+
+ NetworkIdentitySet ident = mActiveIfaces.get(iface);
+ if (ident == null) {
+ ident = new NetworkIdentitySet();
+ mActiveIfaces.put(iface, ident);
+ }
+
ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
}
}
@@ -409,7 +433,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* @param detailedPoll Indicate if detailed UID stats should be collected
* during this poll operation.
*/
- private void performPollLocked(boolean detailedPoll) {
+ private void performPollLocked(boolean detailedPoll, boolean forcePersist) {
if (LOGV) Slog.v(TAG, "performPollLocked()");
// try refreshing time source when stale
@@ -421,33 +445,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
- final NetworkStats networkStats;
+ final NetworkStats ifaceStats;
final NetworkStats uidStats;
try {
- networkStats = mNetworkManager.getNetworkStatsSummary();
+ ifaceStats = mNetworkManager.getNetworkStatsSummary();
uidStats = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null;
} catch (RemoteException e) {
Slog.w(TAG, "problem reading network stats");
return;
}
- performNetworkPollLocked(networkStats, currentTime);
+ performNetworkPollLocked(ifaceStats, currentTime);
if (detailedPoll) {
performUidPollLocked(uidStats, currentTime);
}
// decide if enough has changed to trigger persist
- final NetworkStats persistDelta = computeStatsDelta(mLastNetworkPersist, networkStats);
+ final NetworkStats persistDelta = computeStatsDelta(mLastNetworkPersist, ifaceStats);
final long persistThreshold = mSettings.getPersistThreshold();
for (String iface : persistDelta.getUniqueIfaces()) {
- final int index = persistDelta.findIndex(iface, UID_ALL);
- if (persistDelta.rx[index] > persistThreshold
+ final int index = persistDelta.findIndex(iface, UID_ALL, TAG_NONE);
+ if (forcePersist || persistDelta.rx[index] > persistThreshold
|| persistDelta.tx[index] > persistThreshold) {
writeNetworkStatsLocked();
if (mUidStatsLoaded) {
writeUidStatsLocked();
}
- mLastNetworkPersist = networkStats;
+ mLastNetworkPersist = ifaceStats;
break;
}
}
@@ -462,23 +486,23 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* Update {@link #mNetworkStats} historical usage.
*/
private void performNetworkPollLocked(NetworkStats networkStats, long currentTime) {
- final ArrayList<String> unknownIface = Lists.newArrayList();
+ final HashSet<String> unknownIface = Sets.newHashSet();
final NetworkStats delta = computeStatsDelta(mLastNetworkPoll, networkStats);
final long timeStart = currentTime - delta.elapsedRealtime;
final long maxHistory = mSettings.getNetworkMaxHistory();
- for (String iface : delta.getUniqueIfaces()) {
- final InterfaceIdentity ident = mActiveIface.get(iface);
+ for (int i = 0; i < delta.size; i++) {
+ final String iface = delta.iface[i];
+ final NetworkIdentitySet ident = mActiveIfaces.get(iface);
if (ident == null) {
unknownIface.add(iface);
continue;
}
- final int index = delta.findIndex(iface, UID_ALL);
- final long rx = delta.rx[index];
- final long tx = delta.tx[index];
+ final long rx = delta.rx[i];
+ final long tx = delta.tx[i];
- final NetworkStatsHistory history = findOrCreateNetworkLocked(ident);
+ final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident);
history.recordData(timeStart, currentTime, rx, tx);
history.removeBucketsBefore(currentTime - maxHistory);
}
@@ -498,22 +522,30 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final NetworkStats delta = computeStatsDelta(mLastUidPoll, uidStats);
final long timeStart = currentTime - delta.elapsedRealtime;
final long maxHistory = mSettings.getUidMaxHistory();
- for (int uid : delta.getUniqueUids()) {
- // TODO: traverse all ifaces once surfaced in stats
- final int index = delta.findIndex(IFACE_ALL, uid);
- if (index != -1) {
- final long rx = delta.rx[index];
- final long tx = delta.tx[index];
-
- final NetworkStatsHistory history = findOrCreateUidLocked(uid);
- history.recordData(timeStart, currentTime, rx, tx);
- history.removeBucketsBefore(currentTime - maxHistory);
+
+ // NOTE: historical UID stats ignore tags, and simply records all stats
+ // entries into a single UID bucket.
+
+ for (int i = 0; i < delta.size; i++) {
+ final String iface = delta.iface[i];
+ final NetworkIdentitySet ident = mActiveIfaces.get(iface);
+ if (ident == null) {
+ continue;
}
+
+ final int uid = delta.uid[i];
+ final long rx = delta.rx[i];
+ final long tx = delta.tx[i];
+
+ final NetworkStatsHistory history = findOrCreateUidStatsLocked(ident, uid);
+ history.recordData(timeStart, currentTime, rx, tx);
+ history.removeBucketsBefore(currentTime - maxHistory);
}
+
mLastUidPoll = uidStats;
}
- private NetworkStatsHistory findOrCreateNetworkLocked(InterfaceIdentity ident) {
+ private NetworkStatsHistory findOrCreateNetworkStatsLocked(NetworkIdentitySet ident) {
final long bucketDuration = mSettings.getNetworkBucketDuration();
final NetworkStatsHistory existing = mNetworkStats.get(ident);
@@ -535,9 +567,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
- private NetworkStatsHistory findOrCreateUidLocked(int uid) {
+ private NetworkStatsHistory findOrCreateUidStatsLocked(NetworkIdentitySet ident, int uid) {
+ // find bucket for identity first, then find uid
+ SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
+ if (uidStats == null) {
+ uidStats = new SparseArray<NetworkStatsHistory>();
+ mUidStats.put(ident, uidStats);
+ }
+
final long bucketDuration = mSettings.getUidBucketDuration();
- final NetworkStatsHistory existing = mUidStats.get(uid);
+ final NetworkStatsHistory existing = uidStats.get(uid);
// update when no existing, or when bucket duration changed
NetworkStatsHistory updated = null;
@@ -550,22 +589,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
if (updated != null) {
- mUidStats.put(uid, updated);
+ uidStats.put(uid, updated);
return updated;
} else {
return existing;
}
}
- private InterfaceIdentity findOrCreateInterfaceLocked(String iface) {
- InterfaceIdentity ident = mActiveIface.get(iface);
- if (ident == null) {
- ident = new InterfaceIdentity();
- mActiveIface.put(iface, ident);
- }
- return ident;
- }
-
private void readNetworkStatsLocked() {
if (LOGV) Slog.v(TAG, "readNetworkStatsLocked()");
@@ -585,15 +615,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final int version = in.readInt();
switch (version) {
- case VERSION_CURRENT: {
- // file format is pairs of interfaces and stats:
- // network := size *(InterfaceIdentity NetworkStatsHistory)
-
+ case VERSION_NETWORK_INIT: {
+ // network := size *(NetworkIdentitySet NetworkStatsHistory)
final int size = in.readInt();
for (int i = 0; i < size; i++) {
- final InterfaceIdentity ident = new InterfaceIdentity(in);
+ final NetworkIdentitySet ident = new NetworkIdentitySet(in);
final NetworkStatsHistory history = new NetworkStatsHistory(in);
-
mNetworkStats.put(ident, history);
}
break;
@@ -637,16 +664,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final int version = in.readInt();
switch (version) {
- case VERSION_CURRENT: {
- // file format is pairs of UIDs and stats:
+ case VERSION_UID_INIT: {
// uid := size *(UID NetworkStatsHistory)
- final int size = in.readInt();
- for (int i = 0; i < size; i++) {
- final int uid = in.readInt();
- final NetworkStatsHistory history = new NetworkStatsHistory(in);
-
- mUidStats.put(uid, history);
+ // drop this data version, since we don't have a good
+ // mapping into NetworkIdentitySet.
+ break;
+ }
+ case VERSION_UID_WITH_IDENT: {
+ // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
+ final int ifaceSize = in.readInt();
+ for (int i = 0; i < ifaceSize; i++) {
+ final NetworkIdentitySet ident = new NetworkIdentitySet(in);
+
+ final int uidSize = in.readInt();
+ final SparseArray<NetworkStatsHistory> uidStats = new SparseArray<
+ NetworkStatsHistory>(uidSize);
+ for (int j = 0; j < uidSize; j++) {
+ final int uid = in.readInt();
+ final NetworkStatsHistory history = new NetworkStatsHistory(in);
+ uidStats.put(uid, history);
+ }
+
+ mUidStats.put(ident, uidStats);
}
break;
}
@@ -674,10 +714,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final DataOutputStream out = new DataOutputStream(fos);
out.writeInt(FILE_MAGIC);
- out.writeInt(VERSION_CURRENT);
+ out.writeInt(VERSION_NETWORK_INIT);
out.writeInt(mNetworkStats.size());
- for (InterfaceIdentity ident : mNetworkStats.keySet()) {
+ for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
final NetworkStatsHistory history = mNetworkStats.get(ident);
ident.writeToStream(out);
history.writeToStream(out);
@@ -702,16 +742,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final DataOutputStream out = new DataOutputStream(fos);
out.writeInt(FILE_MAGIC);
- out.writeInt(VERSION_CURRENT);
+ out.writeInt(VERSION_UID_WITH_IDENT);
- final int size = mUidStats.size();
+ out.writeInt(mUidStats.size());
+ for (NetworkIdentitySet ident : mUidStats.keySet()) {
+ final SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
+ ident.writeToStream(out);
- out.writeInt(size);
- for (int i = 0; i < size; i++) {
- final int uid = mUidStats.keyAt(i);
- final NetworkStatsHistory history = mUidStats.valueAt(i);
- out.writeInt(uid);
- history.writeToStream(out);
+ final int size = uidStats.size();
+ out.writeInt(size);
+ for (int i = 0; i < size; i++) {
+ final int uid = uidStats.keyAt(i);
+ final NetworkStatsHistory history = uidStats.valueAt(i);
+ out.writeInt(uid);
+ history.writeToStream(out);
+ }
}
mUidFile.finishWrite(fos);
@@ -740,35 +785,41 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
if (argSet.contains("poll")) {
- performPollLocked(true);
+ performPollLocked(true, true);
pw.println("Forced poll");
return;
}
pw.println("Active interfaces:");
- for (String iface : mActiveIface.keySet()) {
- final InterfaceIdentity ident = mActiveIface.get(iface);
+ for (String iface : mActiveIfaces.keySet()) {
+ final NetworkIdentitySet ident = mActiveIfaces.get(iface);
pw.print(" iface="); pw.print(iface);
pw.print(" ident="); pw.println(ident.toString());
}
pw.println("Known historical stats:");
- for (InterfaceIdentity ident : mNetworkStats.keySet()) {
- final NetworkStatsHistory stats = mNetworkStats.get(ident);
+ for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
+ final NetworkStatsHistory history = mNetworkStats.get(ident);
pw.print(" ident="); pw.println(ident.toString());
- stats.dump(" ", pw);
+ history.dump(" ", pw);
}
if (argSet.contains("detail")) {
// since explicitly requested with argument, we're okay to load
// from disk if not already in memory.
ensureUidStatsLoadedLocked();
- pw.println("Known UID stats:");
- for (int i = 0; i < mUidStats.size(); i++) {
- final int uid = mUidStats.keyAt(i);
- final NetworkStatsHistory stats = mUidStats.valueAt(i);
- pw.print(" UID="); pw.println(uid);
- stats.dump(" ", pw);
+
+ pw.println("Detailed UID stats:");
+ for (NetworkIdentitySet ident : mUidStats.keySet()) {
+ pw.print(" ident="); pw.println(ident.toString());
+
+ final SparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
+ for (int i = 0; i < uidStats.size(); i++) {
+ final int uid = uidStats.keyAt(i);
+ final NetworkStatsHistory history = uidStats.valueAt(i);
+ pw.print(" UID="); pw.println(uid);
+ history.dump(" ", pw);
+ }
}
}
}
@@ -779,27 +830,30 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
*/
@Deprecated
private void generateRandomLocked() {
- long end = System.currentTimeMillis();
- long start = end - mSettings.getNetworkMaxHistory();
- long rx = 3 * GB_IN_BYTES;
- long tx = 2 * GB_IN_BYTES;
+ long networkEnd = System.currentTimeMillis();
+ long networkStart = networkEnd - mSettings.getNetworkMaxHistory();
+ long networkRx = 3 * GB_IN_BYTES;
+ long networkTx = 2 * GB_IN_BYTES;
- mNetworkStats.clear();
- for (InterfaceIdentity ident : mActiveIface.values()) {
- final NetworkStatsHistory stats = findOrCreateNetworkLocked(ident);
- stats.generateRandom(start, end, rx, tx);
- }
+ long uidEnd = System.currentTimeMillis();
+ long uidStart = uidEnd - mSettings.getUidMaxHistory();
+ long uidRx = 500 * MB_IN_BYTES;
+ long uidTx = 100 * MB_IN_BYTES;
- end = System.currentTimeMillis();
- start = end - mSettings.getUidMaxHistory();
- rx = 500 * MB_IN_BYTES;
- tx = 100 * MB_IN_BYTES;
+ final List<ApplicationInfo> installedApps = mContext
+ .getPackageManager().getInstalledApplications(0);
+ mNetworkStats.clear();
mUidStats.clear();
- for (ApplicationInfo info : mContext.getPackageManager().getInstalledApplications(0)) {
- final int uid = info.uid;
- final NetworkStatsHistory stats = findOrCreateUidLocked(uid);
- stats.generateRandom(start, end, rx, tx);
+ for (NetworkIdentitySet ident : mActiveIfaces.values()) {
+ findOrCreateNetworkStatsLocked(ident).generateRandom(
+ networkStart, networkEnd, networkRx, networkTx);
+
+ for (ApplicationInfo info : installedApps) {
+ final int uid = info.uid;
+ findOrCreateUidStatsLocked(ident, uid).generateRandom(
+ uidStart, uidEnd, uidRx, uidTx);
+ }
}
}
@@ -815,12 +869,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
- private String getActiveSubscriberId() {
- final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
- Context.TELEPHONY_SERVICE);
- return telephony.getSubscriberId();
- }
-
private int estimateNetworkBuckets() {
return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration());
}
@@ -834,6 +882,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
/**
+ * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
+ * in the given {@link NetworkIdentitySet}.
+ */
+ private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) {
+ for (NetworkIdentity ident : identSet) {
+ if (template.matches(ident)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Default external settings that read from {@link Settings.Secure}.
*/
private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {