From 2e45e16ca58ad568f1bce9b1fbb8d07b02a36ee8 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 15 Apr 2022 01:03:14 +0800 Subject: [PATCH] Have NetworkPolicyManagerService listen onLinkPropertiesChanged callback In current design, NPMS listens onThresholdReached() callback to call updateNetworkRulesNL(), however, this callback mwill 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 --- .../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 ea851ba9669f8..1787459460f14 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -168,6 +168,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; @@ -230,6 +231,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; @@ -607,6 +609,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") @@ -1324,11 +1329,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 @@ -1347,6 +1369,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()); + } + } }; /**