Loading core/java/android/net/NetworkStats.java +38 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -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); } } Loading Loading @@ -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]; Loading Loading @@ -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 Loading services/core/java/com/android/server/connectivity/Vpn.java +5 −0 Original line number Diff line number Diff line Loading @@ -2525,6 +2525,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 Loading @@ -2535,6 +2537,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 Loading Loading
core/java/android/net/NetworkStats.java +38 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -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); } } Loading Loading @@ -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]; Loading Loading @@ -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 Loading
services/core/java/com/android/server/connectivity/Vpn.java +5 −0 Original line number Diff line number Diff line Loading @@ -2525,6 +2525,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 Loading @@ -2535,6 +2537,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 Loading