diff options
| -rw-r--r-- | core/java/android/net/NetworkStats.java | 42 | ||||
| -rw-r--r-- | services/core/java/com/android/server/connectivity/Vpn.java | 5 |
2 files changed, 43 insertions, 4 deletions
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 6ccbab7ed8ef..288b06ee52c8 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -24,6 +24,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.os.Process; import android.os.SystemClock; import android.util.SparseBooleanArray; @@ -1487,8 +1488,31 @@ public final class NetworkStats implements Parcelable { continue; } - if (recycle.uid == tunUid) { - // Add up traffic through tunUid's underlying interfaces. + if (tunUid == Process.SYSTEM_UID) { + // Kernel-based VPN or VCN, traffic sent by apps on the VPN/VCN network + // + // Since the data is not UID-accounted on underlying networks, just use VPN/VCN + // network usage as ground truth. Encrypted traffic on the underlying networks will + // never be processed here because encrypted traffic on the underlying interfaces + // is not present in UID stats, and this method is only called on UID stats. + if (tunIface.equals(recycle.iface)) { + tunIfaceTotal.add(recycle); + underlyingIfacesTotal.add(recycle); + + // In steady state, there should always be one network, but edge cases may + // result in the network being null (network lost), and thus no underlying + // ifaces is possible. + if (perInterfaceTotal.length > 0) { + // While platform VPNs and VCNs have exactly one underlying network, that + // network may have multiple interfaces (eg for 464xlat). This layer does + // not have the required information to identify which of the interfaces + // were used. Select "any" of the interfaces. Since overhead is already + // lost, this number is an approximation anyways. + perInterfaceTotal[0].add(recycle); + } + } + } else if (recycle.uid == tunUid) { + // VpnService VPN, traffic sent by the VPN app over underlying networks for (int j = 0; j < underlyingIfaces.size(); j++) { if (Objects.equals(underlyingIfaces.get(j), recycle.iface)) { perInterfaceTotal[j].add(recycle); @@ -1497,7 +1521,7 @@ public final class NetworkStats implements Parcelable { } } } else if (tunIface.equals(recycle.iface)) { - // Add up all tunIface traffic excluding traffic from the vpn app itself. + // VpnService VPN; traffic sent by apps on the VPN network tunIfaceTotal.add(recycle); } } @@ -1532,9 +1556,13 @@ public final class NetworkStats implements Parcelable { // Consider only entries that go onto the VPN interface. continue; } - if (uid[i] == tunUid) { + + if (uid[i] == tunUid && tunUid != Process.SYSTEM_UID) { // Exclude VPN app from the redistribution, as it can choose to create packet // streams by writing to itself. + // + // However, for platform VPNs, do not exclude the system's usage of the VPN network, + // since it is never local-only, and never double counted continue; } tmpEntry.uid = uid[i]; @@ -1641,6 +1669,12 @@ public final class NetworkStats implements Parcelable { int tunUid, @NonNull List<String> underlyingIfaces, @NonNull Entry[] moved) { + if (tunUid == Process.SYSTEM_UID) { + // No traffic recorded on a per-UID basis for in-kernel VPN/VCNs over underlying + // networks; thus no traffic to deduct. + return; + } + for (int i = 0; i < underlyingIfaces.size(); i++) { moved[i].uid = tunUid; // Add debug info diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index fd53a1000988..098022006801 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -2523,6 +2523,8 @@ public class Vpn { mConfig.dnsServers.clear(); mConfig.dnsServers.addAll(dnsAddrStrings); + mConfig.underlyingNetworks = new Network[] {network}; + networkAgent = mNetworkAgent; // The below must be done atomically with the mConfig update, otherwise @@ -2533,6 +2535,9 @@ public class Vpn { } agentConnect(); return; // Link properties are already sent. + } else { + // Underlying networks also set in agentConnect() + networkAgent.setUnderlyingNetworks(Collections.singletonList(network)); } lp = makeLinkProperties(); // Accesses VPN instance fields; must be locked |