From d8ed268aca4c5fde0b9503a9f179955b9539c782 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 22 Apr 2022 17:23:21 +0000 Subject: [PATCH] Have NetworkPolicyManagerService listen onLinkPropertiesChanged callback In current design, NPMS listens onThresholdReached() callback to call updateNetworkRulesNL(), however, this callback will not be called if data usage is not updated. Thus, it will cause to no iptables rule for new metered interfaces. Have NPMS listen onLinkProperitesChanged() callback and call updateNetworkRulesNL() if interfaces has changed to add iptables rules for new metered interfaces. Bug: 225971066 Test: HostsideRestrictBackgroundNetworkTests HostsideRestrictBackgroundNetworkTests# \ testDataAndBatterySaverModes_meteredNetwork \ --iterations 100 Change-Id: I49f999efc3fbe0a6a325ec138a3f060c7285e6ad Merged-In: I49f999efc3fbe0a6a325ec138a3f060c7285e6ad (cherry picked from commit 7fe4e5d9206ce50a4571ee4f42df786d75341ce7) --- .../net/NetworkPolicyManagerService.java | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 549b566eeac2d..1ea949ede03d5 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -174,6 +174,7 @@ import android.net.ConnectivityManager.NetworkCallback; import android.net.INetworkManagementEventObserver; import android.net.INetworkPolicyListener; import android.net.INetworkPolicyManager; +import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; @@ -236,6 +237,7 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.SparseLongArray; +import android.util.SparseSetArray; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; import android.util.Xml; @@ -624,6 +626,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** Map from network ID to last observed roaming state */ @GuardedBy("mNetworkPoliciesSecondLock") private final SparseBooleanArray mNetworkRoaming = new SparseBooleanArray(); + /** Map from network ID to the last ifaces on it */ + @GuardedBy("mNetworkPoliciesSecondLock") + private SparseSetArray mNetworkToIfaces = new SparseSetArray<>(); /** Map from netId to subId as of last update */ @GuardedBy("mNetworkPoliciesSecondLock") @@ -1328,11 +1333,28 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return changed; } + @GuardedBy("mNetworkPoliciesSecondLock") + private boolean updateNetworkToIfacesNL(int netId, @NonNull ArraySet newIfaces) { + // TODO: Add a facility SparseSetArray.contains(key) to return whether the key exists. + final ArraySet lastIfaces = mNetworkToIfaces.get(netId); + final boolean changed = lastIfaces == null ? true : !lastIfaces.equals(newIfaces); + + if (changed) { + // Changed on the same network should remove last ifaces and add new ifaces. + // TODO: Add a facility SparseSetArray.put(key, value) for replacing the + // value for a given key. + mNetworkToIfaces.remove(netId); + for (String iface : newIfaces) { + mNetworkToIfaces.add(netId, iface); + } + } + return changed; + } + private final NetworkCallback mNetworkCallback = new NetworkCallback() { @Override - public void onCapabilitiesChanged(Network network, - NetworkCapabilities networkCapabilities) { - if (network == null || networkCapabilities == null) return; + public void onCapabilitiesChanged(@NonNull Network network, + @NonNull NetworkCapabilities networkCapabilities) { synchronized (mNetworkPoliciesSecondLock) { final boolean newMetered = !networkCapabilities @@ -1351,6 +1373,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } } + + @Override + public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties lp) { + synchronized (mNetworkPoliciesSecondLock) { + final ArraySet newIfaces = new ArraySet<>(lp.getAllInterfaceNames()); + final boolean ifacesChanged = updateNetworkToIfacesNL(network.getNetId(), + newIfaces); + if (ifacesChanged) { + updateNetworkRulesNL(); + } + } + } + + @Override + public void onLost(@NonNull Network network) { + synchronized (mNetworkPoliciesSecondLock) { + mNetworkToIfaces.remove(network.getNetId()); + } + } }; /**