Add tether offload traffic to interface stats as well.
Currently, we only count add tethering traffic to per-UID
stats, but not to total data usage (i.e., dev and XT stats). This
is correct for software tethering, because all software forwarded
packets are already included in interface counters, but it is
incorrect for hardware offload, because such packets do not
increment interface counters.
To fix this:
1. Add an argument to ITetheringStatsProvider#getTetherStats to
indicate whether per-UID stats are requested. For clarity,
define integer constants STATS_PER_IFACE and STATS_PER_UID
to represent these operations.
2. Make NetdTetheringStatsProvider return stats only if per-UID
stats are requested. (Otherwise tethering traffic would be
double-counted).
3. Make OffloadController's stats provider return the same
stats regardless of whether per-UID stats were requested or
not.
4. Make NetworkStatsService add non-per-UID tethering stats to
the dev and XT snapshots. The per-UID snapshots were already
correctly adding in per-UID stats.
(cherry picked from commit 5356a35c3bcfcdf2d184c620af6bfbf9bddf35c5)
Bug: 29337859
Bug: 32163131
Test: runtest frameworks-net
Test: runtest frameworks-telephony
Change-Id: I325b13d50e88841dfb0db4c35e7e27f163ee72fe
Merged-In: I4e8e923d68dce1a4a68608dbd6c75a91165aa4ee
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 54addb1..360e5f6 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -17,7 +17,10 @@
package com.android.server.connectivity.tethering;
import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.STATS_PER_IFACE;
+import static android.net.NetworkStats.STATS_PER_UID;
import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_TETHERING;
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
@@ -377,7 +380,6 @@
assertEquals(stats.txBytes, entry.txBytes);
assertEquals(SET_DEFAULT, entry.set);
assertEquals(TAG_NONE, entry.tag);
- assertEquals(UID_TETHERING, entry.uid);
}
@Test
@@ -416,20 +418,33 @@
ethernetStats.txBytes = 100000;
offload.setUpstreamLinkProperties(null);
- NetworkStats stats = mTetherStatsProviderCaptor.getValue().getTetherStats();
+ ITetheringStatsProvider provider = mTetherStatsProviderCaptor.getValue();
+ NetworkStats stats = provider.getTetherStats(STATS_PER_IFACE);
+ NetworkStats perUidStats = provider.getTetherStats(STATS_PER_UID);
+
assertEquals(2, stats.size());
+ assertEquals(2, perUidStats.size());
NetworkStats.Entry entry = null;
+ for (int i = 0; i < stats.size(); i++) {
+ assertEquals(UID_ALL, stats.getValues(i, entry).uid);
+ assertEquals(UID_TETHERING, perUidStats.getValues(i, entry).uid);
+ }
+
int ethernetPosition = ethernetIface.equals(stats.getValues(0, entry).iface) ? 0 : 1;
int mobilePosition = 1 - ethernetPosition;
entry = stats.getValues(mobilePosition, entry);
assertNetworkStats(mobileIface, mobileStats, entry);
+ entry = perUidStats.getValues(mobilePosition, entry);
+ assertNetworkStats(mobileIface, mobileStats, entry);
ethernetStats.rxBytes = 12345 + 100000;
ethernetStats.txBytes = 54321 + 100000;
entry = stats.getValues(ethernetPosition, entry);
assertNetworkStats(ethernetIface, ethernetStats, entry);
+ entry = perUidStats.getValues(ethernetPosition, entry);
+ assertNetworkStats(ethernetIface, ethernetStats, entry);
}
@Test
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index feb46d3..fa99795 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -31,6 +31,8 @@
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.SET_FOREGROUND;
+import static android.net.NetworkStats.STATS_PER_IFACE;
+import static android.net.NetworkStats.STATS_PER_UID;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
@@ -823,17 +825,24 @@
incrementCurrentTime(HOUR_IN_MILLIS);
expectCurrentTime();
expectDefaultSettings();
- expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
+ // Traffic seen by kernel counters (includes software tethering).
+ final NetworkStats ifaceStats = new NetworkStats(getElapsedRealtime(), 1)
+ .addIfaceValues(TEST_IFACE, 1536L, 12L, 384L, 3L);
+ // Hardware tethering traffic, not seen by kernel counters.
+ final NetworkStats tetherStatsHardware = new NetworkStats(getElapsedRealtime(), 1)
+ .addIfaceValues(TEST_IFACE, 512L, 4L, 128L, 1L);
+
+ // Traffic for UID_RED.
final NetworkStats uidStats = new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
- final String[] tetherIfacePairs = new String[] { TEST_IFACE, "wlan0" };
+ // All tethering traffic, both hardware and software.
final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
0L);
- expectNetworkStatsUidDetail(uidStats, tetherIfacePairs, tetherStats);
+ expectNetworkStatsSummary(ifaceStats, tetherStatsHardware);
+ expectNetworkStatsUidDetail(uidStats, tetherStats);
forcePollAndWaitForIdle();
// verify service recorded history
@@ -1013,10 +1022,16 @@
}
private void expectNetworkStatsSummary(NetworkStats summary) throws Exception {
+ expectNetworkStatsSummary(summary, new NetworkStats(0L, 0));
+ }
+
+ private void expectNetworkStatsSummary(NetworkStats summary, NetworkStats tetherStats)
+ throws Exception {
when(mConnManager.getAllVpnInfo()).thenReturn(new VpnInfo[0]);
- expectNetworkStatsSummaryDev(summary);
- expectNetworkStatsSummaryXt(summary);
+ expectNetworkStatsTethering(STATS_PER_IFACE, tetherStats);
+ expectNetworkStatsSummaryDev(summary.clone());
+ expectNetworkStatsSummaryXt(summary.clone());
}
private void expectNetworkStatsSummaryDev(NetworkStats summary) throws Exception {
@@ -1027,17 +1042,21 @@
when(mNetManager.getNetworkStatsSummaryXt()).thenReturn(summary);
}
- private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception {
- expectNetworkStatsUidDetail(detail, new String[0], new NetworkStats(0L, 0));
+ private void expectNetworkStatsTethering(int how, NetworkStats stats)
+ throws Exception {
+ when(mNetManager.getNetworkStatsTethering(how)).thenReturn(stats);
}
- private void expectNetworkStatsUidDetail(
- NetworkStats detail, String[] tetherIfacePairs, NetworkStats tetherStats)
+ private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception {
+ expectNetworkStatsUidDetail(detail, new NetworkStats(0L, 0));
+ }
+
+ private void expectNetworkStatsUidDetail(NetworkStats detail, NetworkStats tetherStats)
throws Exception {
when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail);
// also include tethering details, since they are folded into UID
- when(mNetManager.getNetworkStatsTethering()).thenReturn(tetherStats);
+ when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)).thenReturn(tetherStats);
}
private void expectDefaultSettings() throws Exception {