Sample network statistics for sanity check.
After detailed poll events, sample high-level network statistics to
sanity check iface totals against UID totals.
Bug: 5248382
Change-Id: I1c1fbb7c094c9ff0c9dde416467c563dda68f478
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index e5f3273..3918cfd 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -320,15 +320,36 @@
* checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
*/
public long getTotalBytes() {
- long totalBytes = 0;
+ final Entry entry = getTotal(null);
+ return entry.rxBytes + entry.txBytes;
+ }
+
+ /**
+ * Return total of all fields represented by this snapshot object.
+ */
+ public Entry getTotal(Entry recycle) {
+ final Entry entry = recycle != null ? recycle : new Entry();
+
+ entry.iface = IFACE_ALL;
+ entry.uid = UID_ALL;
+ entry.set = SET_ALL;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = 0;
+ entry.rxPackets = 0;
+ entry.txBytes = 0;
+ entry.txPackets = 0;
+
for (int i = 0; i < size; i++) {
// skip specific tags, since already counted in TAG_NONE
if (tag[i] != TAG_NONE) continue;
- totalBytes += rxBytes[i];
- totalBytes += txBytes[i];
+ entry.rxBytes += rxBytes[i];
+ entry.rxPackets += rxPackets[i];
+ entry.txBytes += txBytes[i];
+ entry.txPackets += txPackets[i];
+ entry.operations += operations[i];
}
- return totalBytes;
+ return entry;
}
/**
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 5429c0c..f0b5958 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -137,3 +137,10 @@
# [ 8- 3] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
# [ 2- 0] Network type (as defined by ConnectivityManager)
50020 connectivity_state_changed (custom|1|5)
+
+
+# ---------------------------
+# NetworkStatsService.java
+# ---------------------------
+51100 netstats_mobile_sample (iface_rx|2|2),(iface_tx|2|2),(uid_rx|2|2),(uid_tx|2|2)
+51101 netstats_wifi_sample (iface_rx|2|2),(iface_tx|2|2),(uid_rx|2|2),(uid_tx|2|2)
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index e0dc96f..4d54fd4 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -31,6 +31,8 @@
import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
+import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.UID_REMOVED;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
@@ -76,6 +78,7 @@
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.TelephonyManager;
+import android.util.EventLog;
import android.util.NtpTrustedTime;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -83,6 +86,7 @@
import com.android.internal.os.AtomicFile;
import com.android.internal.util.Objects;
+import com.android.server.EventLogTags;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
@@ -387,7 +391,9 @@
entry.uid = UID_ALL;
entry.tag = TAG_NONE;
entry.rxBytes = historyEntry.rxBytes;
+ entry.rxPackets = historyEntry.rxPackets;
entry.txBytes = historyEntry.txBytes;
+ entry.txPackets = historyEntry.txPackets;
stats.combineValues(entry);
}
@@ -716,6 +722,11 @@
Slog.v(TAG, "performPollLocked() took " + duration + "ms");
}
+ // sample stats after detailed poll
+ if (detailedPoll) {
+ performSample();
+ }
+
// finally, dispatch updated event to any listeners
final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -809,6 +820,33 @@
}
/**
+ * Sample recent statistics summary into {@link EventLog}.
+ */
+ private void performSample() {
+ // take sample as total over last 4 hours
+ final long end = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
+ final long start = end - (4 * HOUR_IN_MILLIS);
+
+ NetworkTemplate template = null;
+ NetworkStats.Entry ifaceTotal = null;
+ NetworkStats.Entry uidTotal = null;
+
+ // collect mobile sample
+ template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
+ ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
+ uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
+ EventLogTags.writeNetstatsMobileSample(
+ ifaceTotal.rxBytes, ifaceTotal.txBytes, uidTotal.rxBytes, uidTotal.txBytes);
+
+ // collect wifi sample
+ template = buildTemplateWifi();
+ ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
+ uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
+ EventLogTags.writeNetstatsWifiSample(
+ ifaceTotal.rxBytes, ifaceTotal.txBytes, uidTotal.rxBytes, uidTotal.txBytes);
+ }
+
+ /**
* Clean up {@link #mUidStats} after UID is removed.
*/
private void removeUidLocked(int uid) {
@@ -1249,6 +1287,12 @@
}
};
+ private static String getActiveSubscriberId(Context context) {
+ final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ return telephony.getSubscriberId();
+ }
+
/**
* Key uniquely identifying a {@link NetworkStatsHistory} for a UID.
*/