NetworkStatsService: Fix getDetailedUidStats to take VPNs into account.

This API is similar to one provided by NetworkStatsFactory with the
difference that NSS also migrates traffic from VPN UID to other apps.

Since traffic can only be migrated over NetworkStats delta, NSS
therefore maintains NetworkStats snapshot across all UIDs/ifaces/tags.

This snapshot gets updated whenever NSS records a new snapshot
(based on various hooks such as VPN updating its underlying networks,
network getting lost, etc.), or getDetailedUidStats API is invoked by
one of its callers.

Bug: 113122541
Bug: 120145746
Test: atest FrameworksNetTests
Test: manually verified that battery stats are migrating traffic off of
TUN (after patching above CL where we point BatteryStats to use this
API).
Change-Id: Ib0f0c2d4d41ee1d7a027ea9da457baaf198d649e
This commit is contained in:
Varun Anand
2019-01-18 19:22:48 -08:00
parent c8dbdf35de
commit 720133f79d
3 changed files with 94 additions and 10 deletions

View File

@@ -34,6 +34,7 @@ import libcore.util.EmptyArray;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.function.Predicate;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@@ -994,23 +995,33 @@ public class NetworkStats implements Parcelable {
if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
return;
}
filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
&& (limitTag == TAG_ALL || limitTag == e.tag)
&& (limitIfaces == INTERFACES_ALL
|| ArrayUtils.contains(limitIfaces, e.iface)));
}
/**
* Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}.
*
* <p>This mutates the original structure in place.
*/
public void filterDebugEntries() {
filter(e -> e.set < SET_DEBUG_START);
}
private void filter(Predicate<Entry> predicate) {
Entry entry = new Entry();
int nextOutputEntry = 0;
for (int i = 0; i < size; i++) {
entry = getValues(i, entry);
final boolean matches =
(limitUid == UID_ALL || limitUid == entry.uid)
&& (limitTag == TAG_ALL || limitTag == entry.tag)
&& (limitIfaces == INTERFACES_ALL
|| ArrayUtils.contains(limitIfaces, entry.iface));
if (matches) {
setValues(nextOutputEntry, entry);
if (predicate.test(entry)) {
if (nextOutputEntry != i) {
setValues(nextOutputEntry, entry);
}
nextOutputEntry++;
}
}
size = nextOutputEntry;
}