Add method to NetworkStatsService for UID stats.

Useful for clients such as BatteryStats which currently rely
on NetworkStatsFactory. Data at that stage is incomplete as
it does not account for tethering, VT data and corresponding
464xlat corrections.

Test: runtest frameworks-net, CTS tests pass.
Change-Id: I763b77f601c827fd2963204694fb5b45425cc791
This commit is contained in:
Remi NGUYEN VAN
2018-03-06 12:36:54 +09:00
parent bd12ffffc0
commit 1cb92c713f
4 changed files with 228 additions and 4 deletions

View File

@@ -5268,7 +5268,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) {
final String stackedIface = stacked.getInterfaceName();
bs.noteNetworkInterfaceType(stackedIface, type);
NetworkStatsFactory.noteStackedIface(stackedIface, baseIface);
}
} catch (RemoteException ignored) {
}

View File

@@ -19,6 +19,7 @@ package android.net;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
import static android.net.NetworkStats.INTERFACES_ALL;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.METERED_YES;
@@ -31,6 +32,7 @@ import static android.net.NetworkStats.SET_DBG_VPN_IN;
import static android.net.NetworkStats.SET_DBG_VPN_OUT;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static org.junit.Assert.assertEquals;
@@ -641,6 +643,136 @@ public class NetworkStatsTest {
ROAMING_ALL, DEFAULT_NETWORK_ALL, 50500L, 27L, 100200L, 55, 0);
}
@Test
public void testFilter_NoFilter() {
NetworkStats.Entry entry1 = new NetworkStats.Entry(
"test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry2 = new NetworkStats.Entry(
"test2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry3 = new NetworkStats.Entry(
"test2", 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
.addValues(entry1)
.addValues(entry2)
.addValues(entry3);
stats.filter(UID_ALL, INTERFACES_ALL, TAG_ALL);
assertEquals(3, stats.size());
assertEquals(entry1, stats.getValues(0, null));
assertEquals(entry2, stats.getValues(1, null));
assertEquals(entry3, stats.getValues(2, null));
}
@Test
public void testFilter_UidFilter() {
final int testUid = 10101;
NetworkStats.Entry entry1 = new NetworkStats.Entry(
"test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry2 = new NetworkStats.Entry(
"test2", testUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry3 = new NetworkStats.Entry(
"test2", testUid, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
.addValues(entry1)
.addValues(entry2)
.addValues(entry3);
stats.filter(testUid, INTERFACES_ALL, TAG_ALL);
assertEquals(2, stats.size());
assertEquals(entry2, stats.getValues(0, null));
assertEquals(entry3, stats.getValues(1, null));
}
@Test
public void testFilter_InterfaceFilter() {
final String testIf1 = "testif1";
final String testIf2 = "testif2";
NetworkStats.Entry entry1 = new NetworkStats.Entry(
testIf1, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry2 = new NetworkStats.Entry(
"otherif", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry3 = new NetworkStats.Entry(
testIf1, 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry4 = new NetworkStats.Entry(
testIf2, 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 4)
.addValues(entry1)
.addValues(entry2)
.addValues(entry3)
.addValues(entry4);
stats.filter(UID_ALL, new String[] { testIf1, testIf2 }, TAG_ALL);
assertEquals(3, stats.size());
assertEquals(entry1, stats.getValues(0, null));
assertEquals(entry3, stats.getValues(1, null));
assertEquals(entry4, stats.getValues(2, null));
}
@Test
public void testFilter_EmptyInterfaceFilter() {
NetworkStats.Entry entry1 = new NetworkStats.Entry(
"if1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry2 = new NetworkStats.Entry(
"if2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
.addValues(entry1)
.addValues(entry2);
stats.filter(UID_ALL, new String[] { }, TAG_ALL);
assertEquals(0, stats.size());
}
@Test
public void testFilter_TagFilter() {
final int testTag = 123;
final int otherTag = 456;
NetworkStats.Entry entry1 = new NetworkStats.Entry(
"test1", 10100, SET_DEFAULT, testTag, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry2 = new NetworkStats.Entry(
"test2", 10101, SET_DEFAULT, testTag, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats.Entry entry3 = new NetworkStats.Entry(
"test2", 10101, SET_DEFAULT, otherTag, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
.addValues(entry1)
.addValues(entry2)
.addValues(entry3);
stats.filter(UID_ALL, INTERFACES_ALL, testTag);
assertEquals(2, stats.size());
assertEquals(entry1, stats.getValues(0, null));
assertEquals(entry2, stats.getValues(1, null));
}
private static void assertContains(NetworkStats stats, String iface, int uid, int set,
int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
long txBytes, long txPackets, long operations) {

View File

@@ -184,7 +184,7 @@ public class NetworkStatsFactoryTest {
assertStatsEntry(stats, "dummy0", 0, SET_DEFAULT, 0x0, 0L, 168L);
assertStatsEntry(stats, "lo", 0, SET_DEFAULT, 0x0, 1288L, 1288L);
NetworkStatsFactory.noteStackedIface("v4-wlan0", null);
NetworkStatsFactory.clearStackedIfaces();
}
@Test
@@ -212,7 +212,7 @@ public class NetworkStatsFactoryTest {
assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesAfter, 7867488L);
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytesAfter, 647587L);
NetworkStatsFactory.noteStackedIface("v4-wlan0", null);
NetworkStatsFactory.clearStackedIfaces();
}
/**

View File

@@ -25,6 +25,7 @@ import static android.net.NetworkStats.DEFAULT_NETWORK_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.INTERFACES_ALL;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.METERED_YES;
@@ -58,6 +59,9 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -95,6 +99,7 @@ import android.util.Log;
import android.util.TrustedTime;
import com.android.internal.net.VpnInfo;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
@@ -667,6 +672,94 @@ public class NetworkStatsServiceTest {
DEFAULT_NETWORK_YES, 1024L, 8L, 512L, 4L, 0);
}
@Test
public void testDetailedUidStats() throws Exception {
// pretend that network comes online
expectDefaultSettings();
expectNetworkState(buildWifiState());
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
mService.forceUpdateIfaces(NETWORKS_WIFI);
NetworkStats.Entry entry1 = new NetworkStats.Entry(
TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L);
NetworkStats.Entry entry2 = new NetworkStats.Entry(
TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 50L, 5L, 50L, 5L, 0L);
NetworkStats.Entry entry3 = new NetworkStats.Entry(
TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xBEEF, 1024L, 8L, 512L, 4L, 0L);
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
.addValues(entry1)
.addValues(entry2)
.addValues(entry3));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
NetworkStats stats = mService.getDetailedUidStats(INTERFACES_ALL);
assertEquals(3, stats.size());
entry1.operations = 1;
assertEquals(entry1, stats.getValues(0, null));
entry2.operations = 1;
assertEquals(entry2, stats.getValues(1, null));
assertEquals(entry3, stats.getValues(2, null));
}
@Test
public void testDetailedUidStats_Filtered() throws Exception {
// pretend that network comes online
expectDefaultSettings();
final String stackedIface = "stacked-test0";
final LinkProperties stackedProp = new LinkProperties();
stackedProp.setInterfaceName(stackedIface);
final NetworkState wifiState = buildWifiState();
wifiState.linkProperties.addStackedLink(stackedProp);
expectNetworkState(wifiState);
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
mService.forceUpdateIfaces(NETWORKS_WIFI);
NetworkStats.Entry uidStats = new NetworkStats.Entry(
TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
// Stacked on matching interface
NetworkStats.Entry tetheredStats1 = new NetworkStats.Entry(
stackedIface, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
// Different interface
NetworkStats.Entry tetheredStats2 = new NetworkStats.Entry(
"otherif", UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
final String[] ifaceFilter = new String[] { TEST_IFACE };
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
when(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL), any()))
.thenReturn(new NetworkStats(getElapsedRealtime(), 1)
.addValues(uidStats));
when(mNetManager.getNetworkStatsTethering(STATS_PER_UID))
.thenReturn(new NetworkStats(getElapsedRealtime(), 2)
.addValues(tetheredStats1)
.addValues(tetheredStats2));
NetworkStats stats = mService.getDetailedUidStats(ifaceFilter);
verify(mNetManager, times(1)).getNetworkStatsUidDetail(eq(UID_ALL), argThat(ifaces ->
ifaces != null && ifaces.length == 2
&& ArrayUtils.contains(ifaces, TEST_IFACE)
&& ArrayUtils.contains(ifaces, stackedIface)));
assertEquals(2, stats.size());
assertEquals(uidStats, stats.getValues(0, null));
assertEquals(tetheredStats1, stats.getValues(1, null));
}
@Test
public void testForegroundBackground() throws Exception {
// pretend that network comes online
@@ -1056,7 +1149,7 @@ public class NetworkStatsServiceTest {
private void expectNetworkStatsUidDetail(NetworkStats detail, NetworkStats tetherStats)
throws Exception {
when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail);
when(mNetManager.getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL)).thenReturn(detail);
// also include tethering details, since they are folded into UID
when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)).thenReturn(tetherStats);