Loading core/java/android/net/INetworkStatsService.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -67,7 +67,8 @@ interface INetworkStatsService { void forceUpdateIfaces( in Network[] defaultNetworks, in NetworkState[] networkStates, in String activeIface); in String activeIface, in VpnInfo[] vpnInfos); /** Force update of statistics. */ @UnsupportedAppUsage void forceUpdate(); Loading services/core/java/com/android/server/ConnectivityService.java +4 −9 Original line number Diff line number Diff line Loading @@ -193,7 +193,6 @@ import com.android.server.net.BaseNetdEventCallback; import com.android.server.net.BaseNetworkObserver; import com.android.server.net.LockdownVpnTracker; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.net.NetworkStatsFactory; import com.android.server.utils.PriorityDump; import com.google.android.collect.Lists; Loading Loading @@ -6801,8 +6800,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** * Notify NetworkStatsService and NetworkStatsFactory that the set of active ifaces has changed, * or that one of the active iface's trackedproperties has changed. * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the * active iface's tracked properties has changed. */ private void notifyIfacesChangedForNetworkStats() { ensureRunningOnConnectivityServiceThread(); Loading @@ -6812,16 +6811,12 @@ public class ConnectivityService extends IConnectivityManager.Stub activeIface = activeLinkProperties.getInterfaceName(); } // CAUTION: Ordering matters between updateVpnInfos() and forceUpdateIfaces(), which // triggers a new poll. Trigger the poll first to ensure a snapshot is taken before // switching to the new state. This ensures that traffic does not get mis-attributed to // incorrect apps (including VPN app). final VpnInfo[] vpnInfos = getAllVpnInfo(); try { mStatsService.forceUpdateIfaces( getDefaultNetworks(), getAllNetworkState(), activeIface); getDefaultNetworks(), getAllNetworkState(), activeIface, vpnInfos); } catch (Exception ignored) { } NetworkStatsFactory.updateVpnInfos(getAllVpnInfo()); } @Override Loading services/core/java/com/android/server/net/NetworkStatsFactory.java +20 −29 Original line number Diff line number Diff line Loading @@ -78,17 +78,17 @@ public class NetworkStatsFactory { * <p>In order to prevent deadlocks, critical sections protected by this lock SHALL NOT call out * to other code that will acquire other locks within the system server. See b/134244752. */ private static final Object sPersistentDataLock = new Object(); private final Object mPersistentDataLock = new Object(); /** Set containing info about active VPNs and their underlying networks. */ private static volatile VpnInfo[] sVpnInfos = new VpnInfo[0]; private volatile VpnInfo[] mVpnInfos = new VpnInfo[0]; // A persistent snapshot of cumulative stats since device start @GuardedBy("sPersistentDataLock") @GuardedBy("mPersistentDataLock") private NetworkStats mPersistSnapshot; // The persistent snapshot of tun and 464xlat adjusted stats since device start @GuardedBy("sPersistentDataLock") @GuardedBy("mPersistentDataLock") private NetworkStats mTunAnd464xlatAdjustedStats; /** Loading @@ -97,12 +97,13 @@ public class NetworkStatsFactory { * Because counters must never roll backwards, once a given interface is stacked on top of an * underlying interface, the stacked interface can never be stacked on top of * another interface. */ private static final ConcurrentHashMap<String, String> sStackedIfaces private final ConcurrentHashMap<String, String> mStackedIfaces = new ConcurrentHashMap<>(); public static void noteStackedIface(String stackedIface, String baseIface) { /** Informs the factory of a new stacked interface. */ public void noteStackedIface(String stackedIface, String baseIface) { if (stackedIface != null && baseIface != null) { sStackedIfaces.put(stackedIface, baseIface); mStackedIfaces.put(stackedIface, baseIface); } } Loading @@ -115,13 +116,8 @@ public class NetworkStatsFactory { * * @param vpnArray The snapshot of the currently-running VPNs. */ public static void updateVpnInfos(VpnInfo[] vpnArray) { sVpnInfos = vpnArray.clone(); } @VisibleForTesting public static VpnInfo[] getVpnInfos() { return sVpnInfos.clone(); public void updateVpnInfos(VpnInfo[] vpnArray) { mVpnInfos = vpnArray.clone(); } /** Loading @@ -132,7 +128,7 @@ public class NetworkStatsFactory { * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method * is called are guaranteed to be included. */ public static String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) { public String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) { if (requiredIfaces == NetworkStats.INTERFACES_ALL) { return null; } Loading @@ -142,7 +138,7 @@ public class NetworkStatsFactory { // elements as they existed upon construction exactly once, and may // (but are not guaranteed to) reflect any modifications subsequent to construction". // This is enough here. for (Map.Entry<String, String> entry : sStackedIfaces.entrySet()) { for (Map.Entry<String, String> entry : mStackedIfaces.entrySet()) { if (relatedIfaces.contains(entry.getKey())) { relatedIfaces.add(entry.getValue()); } else if (relatedIfaces.contains(entry.getValue())) { Loading @@ -158,17 +154,12 @@ public class NetworkStatsFactory { * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean) */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, public void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic, boolean useBpfStats) { NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces, NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces, useBpfStats); } @VisibleForTesting public static void clearStackedIfaces() { sStackedIfaces.clear(); } public NetworkStatsFactory() { this(new File("/proc/"), new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists()); } Loading @@ -179,7 +170,7 @@ public class NetworkStatsFactory { mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; synchronized (sPersistentDataLock) { synchronized (mPersistentDataLock) { mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } Loading Loading @@ -304,7 +295,7 @@ public class NetworkStatsFactory { return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL); } @GuardedBy("sPersistentDataLock") @GuardedBy("mPersistentDataLock") private void requestSwapActiveStatsMapLocked() throws RemoteException { // Ask netd to do a active map stats swap. When the binder call successfully returns, // the system server should be able to safely read and clean the inactive map Loading @@ -328,9 +319,9 @@ public class NetworkStatsFactory { int limitUid, String[] limitIfaces, int limitTag) throws IOException { // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other // code that will acquire other locks within the system server. See b/134244752. synchronized (sPersistentDataLock) { synchronized (mPersistentDataLock) { // Take a reference. If this gets swapped out, we still have the old reference. final VpnInfo[] vpnArray = sVpnInfos; final VpnInfo[] vpnArray = mVpnInfos; // Take a defensive copy. mPersistSnapshot is mutated in some cases below final NetworkStats prev = mPersistSnapshot.clone(); Loading Loading @@ -379,7 +370,7 @@ public class NetworkStatsFactory { } } @GuardedBy("sPersistentDataLock") @GuardedBy("mPersistentDataLock") private NetworkStats adjustForTunAnd464Xlat( NetworkStats uidDetailStats, NetworkStats previousStats, VpnInfo[] vpnArray) { // Calculate delta from last snapshot Loading @@ -389,7 +380,7 @@ public class NetworkStatsFactory { // network, the overhead is their fault. // No locking here: apply464xlatAdjustments behaves fine with an add-only // ConcurrentHashMap. delta.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); delta.apply464xlatAdjustments(mStackedIfaces, mUseBpfStats); // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { Loading services/core/java/com/android/server/net/NetworkStatsService.java +11 −4 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FileRotator; Loading Loading @@ -784,7 +785,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { final String[] ifacesToQuery = NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); mStatsFactory.augmentWithStackedInterfaces(requiredIfaces); return getNetworkStatsUidDetail(ifacesToQuery); } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); Loading Loading @@ -836,7 +837,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void forceUpdateIfaces( Network[] defaultNetworks, NetworkState[] networkStates, String activeIface) { String activeIface, VpnInfo[] vpnInfos) { checkNetworkStackPermission(mContext); final long token = Binder.clearCallingIdentity(); Loading @@ -845,6 +847,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } finally { Binder.restoreCallingIdentity(token); } // Update the VPN underlying interfaces only after the poll is made and tun data has been // migrated. Otherwise the migration would use the new interfaces instead of the ones that // were current when the polled data was transferred. mStatsFactory.updateVpnInfos(vpnInfos); } @Override Loading Loading @@ -1656,7 +1663,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, mUseBpfTrafficStats); uidSnapshot.combineAllValues(tetherSnapshot); Loading @@ -1667,7 +1674,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { vtStats.filter(UID_ALL, ifaces, TAG_ALL); NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, mStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, mUseBpfTrafficStats); uidSnapshot.combineAllValues(vtStats); } Loading tests/net/java/com/android/server/ConnectivityServiceTest.java +14 −36 Original line number Diff line number Diff line Loading @@ -205,7 +205,6 @@ import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; import com.android.server.net.NetworkPinner; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.net.NetworkStatsFactory; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.ThrowingConsumer; Loading Loading @@ -4882,11 +4881,8 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(cellLp); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Default network switch should update ifaces. Loading @@ -4895,65 +4891,47 @@ public class ConnectivityServiceTest { waitForIdle(); assertEquals(wifiLp, mService.getActiveLinkProperties()); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Disconnect should update ifaces. mWiFiNetworkAgent.disconnect(); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Metered change should update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Captive portal change shouldn't update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL); waitForIdle(); verify(mStatsService, never()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Roaming change should update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); } Loading Loading
core/java/android/net/INetworkStatsService.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -67,7 +67,8 @@ interface INetworkStatsService { void forceUpdateIfaces( in Network[] defaultNetworks, in NetworkState[] networkStates, in String activeIface); in String activeIface, in VpnInfo[] vpnInfos); /** Force update of statistics. */ @UnsupportedAppUsage void forceUpdate(); Loading
services/core/java/com/android/server/ConnectivityService.java +4 −9 Original line number Diff line number Diff line Loading @@ -193,7 +193,6 @@ import com.android.server.net.BaseNetdEventCallback; import com.android.server.net.BaseNetworkObserver; import com.android.server.net.LockdownVpnTracker; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.net.NetworkStatsFactory; import com.android.server.utils.PriorityDump; import com.google.android.collect.Lists; Loading Loading @@ -6801,8 +6800,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** * Notify NetworkStatsService and NetworkStatsFactory that the set of active ifaces has changed, * or that one of the active iface's trackedproperties has changed. * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the * active iface's tracked properties has changed. */ private void notifyIfacesChangedForNetworkStats() { ensureRunningOnConnectivityServiceThread(); Loading @@ -6812,16 +6811,12 @@ public class ConnectivityService extends IConnectivityManager.Stub activeIface = activeLinkProperties.getInterfaceName(); } // CAUTION: Ordering matters between updateVpnInfos() and forceUpdateIfaces(), which // triggers a new poll. Trigger the poll first to ensure a snapshot is taken before // switching to the new state. This ensures that traffic does not get mis-attributed to // incorrect apps (including VPN app). final VpnInfo[] vpnInfos = getAllVpnInfo(); try { mStatsService.forceUpdateIfaces( getDefaultNetworks(), getAllNetworkState(), activeIface); getDefaultNetworks(), getAllNetworkState(), activeIface, vpnInfos); } catch (Exception ignored) { } NetworkStatsFactory.updateVpnInfos(getAllVpnInfo()); } @Override Loading
services/core/java/com/android/server/net/NetworkStatsFactory.java +20 −29 Original line number Diff line number Diff line Loading @@ -78,17 +78,17 @@ public class NetworkStatsFactory { * <p>In order to prevent deadlocks, critical sections protected by this lock SHALL NOT call out * to other code that will acquire other locks within the system server. See b/134244752. */ private static final Object sPersistentDataLock = new Object(); private final Object mPersistentDataLock = new Object(); /** Set containing info about active VPNs and their underlying networks. */ private static volatile VpnInfo[] sVpnInfos = new VpnInfo[0]; private volatile VpnInfo[] mVpnInfos = new VpnInfo[0]; // A persistent snapshot of cumulative stats since device start @GuardedBy("sPersistentDataLock") @GuardedBy("mPersistentDataLock") private NetworkStats mPersistSnapshot; // The persistent snapshot of tun and 464xlat adjusted stats since device start @GuardedBy("sPersistentDataLock") @GuardedBy("mPersistentDataLock") private NetworkStats mTunAnd464xlatAdjustedStats; /** Loading @@ -97,12 +97,13 @@ public class NetworkStatsFactory { * Because counters must never roll backwards, once a given interface is stacked on top of an * underlying interface, the stacked interface can never be stacked on top of * another interface. */ private static final ConcurrentHashMap<String, String> sStackedIfaces private final ConcurrentHashMap<String, String> mStackedIfaces = new ConcurrentHashMap<>(); public static void noteStackedIface(String stackedIface, String baseIface) { /** Informs the factory of a new stacked interface. */ public void noteStackedIface(String stackedIface, String baseIface) { if (stackedIface != null && baseIface != null) { sStackedIfaces.put(stackedIface, baseIface); mStackedIfaces.put(stackedIface, baseIface); } } Loading @@ -115,13 +116,8 @@ public class NetworkStatsFactory { * * @param vpnArray The snapshot of the currently-running VPNs. */ public static void updateVpnInfos(VpnInfo[] vpnArray) { sVpnInfos = vpnArray.clone(); } @VisibleForTesting public static VpnInfo[] getVpnInfos() { return sVpnInfos.clone(); public void updateVpnInfos(VpnInfo[] vpnArray) { mVpnInfos = vpnArray.clone(); } /** Loading @@ -132,7 +128,7 @@ public class NetworkStatsFactory { * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method * is called are guaranteed to be included. */ public static String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) { public String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) { if (requiredIfaces == NetworkStats.INTERFACES_ALL) { return null; } Loading @@ -142,7 +138,7 @@ public class NetworkStatsFactory { // elements as they existed upon construction exactly once, and may // (but are not guaranteed to) reflect any modifications subsequent to construction". // This is enough here. for (Map.Entry<String, String> entry : sStackedIfaces.entrySet()) { for (Map.Entry<String, String> entry : mStackedIfaces.entrySet()) { if (relatedIfaces.contains(entry.getKey())) { relatedIfaces.add(entry.getValue()); } else if (relatedIfaces.contains(entry.getValue())) { Loading @@ -158,17 +154,12 @@ public class NetworkStatsFactory { * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean) */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, public void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic, boolean useBpfStats) { NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces, NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces, useBpfStats); } @VisibleForTesting public static void clearStackedIfaces() { sStackedIfaces.clear(); } public NetworkStatsFactory() { this(new File("/proc/"), new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists()); } Loading @@ -179,7 +170,7 @@ public class NetworkStatsFactory { mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; synchronized (sPersistentDataLock) { synchronized (mPersistentDataLock) { mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } Loading Loading @@ -304,7 +295,7 @@ public class NetworkStatsFactory { return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL); } @GuardedBy("sPersistentDataLock") @GuardedBy("mPersistentDataLock") private void requestSwapActiveStatsMapLocked() throws RemoteException { // Ask netd to do a active map stats swap. When the binder call successfully returns, // the system server should be able to safely read and clean the inactive map Loading @@ -328,9 +319,9 @@ public class NetworkStatsFactory { int limitUid, String[] limitIfaces, int limitTag) throws IOException { // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other // code that will acquire other locks within the system server. See b/134244752. synchronized (sPersistentDataLock) { synchronized (mPersistentDataLock) { // Take a reference. If this gets swapped out, we still have the old reference. final VpnInfo[] vpnArray = sVpnInfos; final VpnInfo[] vpnArray = mVpnInfos; // Take a defensive copy. mPersistSnapshot is mutated in some cases below final NetworkStats prev = mPersistSnapshot.clone(); Loading Loading @@ -379,7 +370,7 @@ public class NetworkStatsFactory { } } @GuardedBy("sPersistentDataLock") @GuardedBy("mPersistentDataLock") private NetworkStats adjustForTunAnd464Xlat( NetworkStats uidDetailStats, NetworkStats previousStats, VpnInfo[] vpnArray) { // Calculate delta from last snapshot Loading @@ -389,7 +380,7 @@ public class NetworkStatsFactory { // network, the overhead is their fault. // No locking here: apply464xlatAdjustments behaves fine with an add-only // ConcurrentHashMap. delta.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); delta.apply464xlatAdjustments(mStackedIfaces, mUseBpfStats); // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { Loading
services/core/java/com/android/server/net/NetworkStatsService.java +11 −4 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FileRotator; Loading Loading @@ -784,7 +785,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { final String[] ifacesToQuery = NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); mStatsFactory.augmentWithStackedInterfaces(requiredIfaces); return getNetworkStatsUidDetail(ifacesToQuery); } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); Loading Loading @@ -836,7 +837,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void forceUpdateIfaces( Network[] defaultNetworks, NetworkState[] networkStates, String activeIface) { String activeIface, VpnInfo[] vpnInfos) { checkNetworkStackPermission(mContext); final long token = Binder.clearCallingIdentity(); Loading @@ -845,6 +847,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } finally { Binder.restoreCallingIdentity(token); } // Update the VPN underlying interfaces only after the poll is made and tun data has been // migrated. Otherwise the migration would use the new interfaces instead of the ones that // were current when the polled data was transferred. mStatsFactory.updateVpnInfos(vpnInfos); } @Override Loading Loading @@ -1656,7 +1663,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, mUseBpfTrafficStats); uidSnapshot.combineAllValues(tetherSnapshot); Loading @@ -1667,7 +1674,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { vtStats.filter(UID_ALL, ifaces, TAG_ALL); NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, mStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, mUseBpfTrafficStats); uidSnapshot.combineAllValues(vtStats); } Loading
tests/net/java/com/android/server/ConnectivityServiceTest.java +14 −36 Original line number Diff line number Diff line Loading @@ -205,7 +205,6 @@ import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; import com.android.server.net.NetworkPinner; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.net.NetworkStatsFactory; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.ThrowingConsumer; Loading Loading @@ -4882,11 +4881,8 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(cellLp); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Default network switch should update ifaces. Loading @@ -4895,65 +4891,47 @@ public class ConnectivityServiceTest { waitForIdle(); assertEquals(wifiLp, mService.getActiveLinkProperties()); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Disconnect should update ifaces. mWiFiNetworkAgent.disconnect(); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Metered change should update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Captive portal change shouldn't update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL); waitForIdle(); verify(mStatsService, never()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); // Roaming change should update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); waitForIdle(); verify(mStatsService, atLeastOnce()) .forceUpdateIfaces( eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME)); assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos()); .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), eq(new VpnInfo[0])); reset(mStatsService); } Loading