From 9fc27eab94bda7e0bd59f7bef1ffb7e82e14fdaa Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 2 Dec 2019 15:34:05 +0900 Subject: [PATCH 1/2] [NS A24] Add an object to represent changes in assignment Reupload of I703db6d3f039bd67a90fad0eadffc6cfed9a50ee Test: ConnectivityServiceTest Change-Id: I9ef468a17ebcfa684e5614b25dc06fc67eb71c79 --- .../android/server/ConnectivityService.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 83adec675c..17bfcd694d 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -6241,6 +6241,26 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + // An accumulator class to gather the list of changes that result from a rematch. + // TODO : enrich to represent an entire set of changes to apply. + private static class NetworkReassignment { + static class NetworkBgStatePair { + @NonNull final NetworkAgentInfo mNetwork; + final boolean mOldBackground; + NetworkBgStatePair(@NonNull final NetworkAgentInfo network, + final boolean oldBackground) { + mNetwork = network; + mOldBackground = oldBackground; + } + } + + @NonNull private final Set mRematchedNetworks = new ArraySet<>(); + + void addRematchedNetwork(@NonNull final NetworkBgStatePair network) { + mRematchedNetworks.add(network); + } + } + private ArrayMap computeRequestReassignmentForNetwork( @NonNull final NetworkAgentInfo newNetwork) { final int score = newNetwork.getCurrentScore(); @@ -6286,8 +6306,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // needed. A network is needed if it is the best network for // one or more NetworkRequests, or if it is a VPN. // - // - Tears down newNetwork if it just became validated - // but turns out to be unneeded. + // - Writes into the passed reassignment object all changes that should be done for + // rematching this network with all requests, to be applied later. // // NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy, // it does not remove NetworkRequests that other Networks could better satisfy. @@ -6295,15 +6315,23 @@ public class ConnectivityService extends IConnectivityManager.Stub // This function should be used when possible instead of {@code rematchAllNetworksAndRequests} // as it performs better by a factor of the number of Networks. // + // TODO : stop writing to the passed reassignment. This is temporarily more useful, but + // it's unidiomatic Java and it's hard to read. + // + // @param changes a currently-building list of changes to write to // @param newNetwork is the network to be matched against NetworkRequests. // @param now the time the rematch starts, as returned by SystemClock.elapsedRealtime(); - private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, long now) { + private void rematchNetworkAndRequests(@NonNull final NetworkReassignment changes, + @NonNull final NetworkAgentInfo newNetwork, final long now) { ensureRunningOnConnectivityServiceThread(); if (!newNetwork.everConnected) return; boolean isNewDefault = false; NetworkAgentInfo oldDefaultNetwork = null; final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork(); + changes.addRematchedNetwork(new NetworkReassignment.NetworkBgStatePair(newNetwork, + wasBackgroundNetwork)); + final int score = newNetwork.getCurrentScore(); if (VDBG || DDBG) log("rematching " + newNetwork.name()); @@ -6460,8 +6488,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // scoring network and then a higher scoring network, which could produce multiple // callbacks. Arrays.sort(nais); + final NetworkReassignment changes = new NetworkReassignment(); for (final NetworkAgentInfo nai : nais) { - rematchNetworkAndRequests(nai, now); + rematchNetworkAndRequests(changes, nai, now); } final NetworkAgentInfo newDefaultNetwork = getDefaultNetwork(); From 62edfd877960352741d73fc1cce9668038e5494b Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 2 Dec 2019 18:39:29 +0900 Subject: [PATCH 2/2] [NS A25] Send all listen callbacks after all rematches Reupload of I2db9535b1d72edd46b968b1bae66b148aa815235 with a bugfix. Bug: 113554781 Test: ConnectivityServiceTests NetworkStackTests Change-Id: I904d87c01d9422ba6233d22a189e8017dd298d37 --- .../android/server/ConnectivityService.java | 94 ++++++++++--------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 17bfcd694d..29f9e58a5d 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5791,6 +5791,19 @@ public class ConnectivityService extends IConnectivityManager.Stub return INetd.PERMISSION_NONE; } + private void updateNetworkPermissions(@NonNull final NetworkAgentInfo nai, + @NonNull final NetworkCapabilities newNc) { + final int oldPermission = getNetworkPermission(nai.networkCapabilities); + final int newPermission = getNetworkPermission(newNc); + if (oldPermission != newPermission && nai.created && !nai.isVPN()) { + try { + mNMS.setNetworkPermission(nai.network.netId, newPermission); + } catch (RemoteException e) { + loge("Exception in setNetworkPermission: " + e); + } + } + } + /** * Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are * maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal, @@ -5862,21 +5875,11 @@ public class ConnectivityService extends IConnectivityManager.Stub * @param nai the network having its capabilities updated. * @param nc the new network capabilities. */ - private void updateCapabilities(int oldScore, NetworkAgentInfo nai, NetworkCapabilities nc) { + private void updateCapabilities(final int oldScore, @NonNull final NetworkAgentInfo nai, + @NonNull final NetworkCapabilities nc) { NetworkCapabilities newNc = mixInCapabilities(nai, nc); - if (Objects.equals(nai.networkCapabilities, newNc)) return; - - final int oldPermission = getNetworkPermission(nai.networkCapabilities); - final int newPermission = getNetworkPermission(newNc); - if (oldPermission != newPermission && nai.created && !nai.isVPN()) { - try { - mNMS.setNetworkPermission(nai.network.netId, newPermission); - } catch (RemoteException e) { - loge("Exception in setNetworkPermission: " + e); - } - } - + updateNetworkPermissions(nai, newNc); final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc); updateUids(nai, prevNc, newNc); @@ -6256,6 +6259,10 @@ public class ConnectivityService extends IConnectivityManager.Stub @NonNull private final Set mRematchedNetworks = new ArraySet<>(); + @NonNull Iterable getRematchedNetworks() { + return mRematchedNetworks; + } + void addRematchedNetwork(@NonNull final NetworkBgStatePair network) { mRematchedNetworks.add(network); } @@ -6328,9 +6335,8 @@ public class ConnectivityService extends IConnectivityManager.Stub boolean isNewDefault = false; NetworkAgentInfo oldDefaultNetwork = null; - final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork(); changes.addRematchedNetwork(new NetworkReassignment.NetworkBgStatePair(newNetwork, - wasBackgroundNetwork)); + newNetwork.isBackgroundNetwork())); final int score = newNetwork.getCurrentScore(); @@ -6434,39 +6440,12 @@ public class ConnectivityService extends IConnectivityManager.Stub if (newNetwork.getCurrentScore() != score) { Slog.wtf(TAG, String.format( "BUG: %s changed score during rematch: %d -> %d", - newNetwork.name(), score, newNetwork.getCurrentScore())); + newNetwork.name(), score, newNetwork.getCurrentScore())); } // Notify requested networks are available after the default net is switched, but // before LegacyTypeTracker sends legacy broadcasts for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri); - - // Finally, process listen requests and update capabilities if the background state has - // changed for this network. For consistency with previous behavior, send onLost callbacks - // before onAvailable. - processNewlyLostListenRequests(newNetwork); - - // Maybe the network changed background states. Update its capabilities. - final boolean backgroundChanged = wasBackgroundNetwork != newNetwork.isBackgroundNetwork(); - if (backgroundChanged) { - final NetworkCapabilities newNc = mixInCapabilities(newNetwork, - newNetwork.networkCapabilities); - - final int oldPermission = getNetworkPermission(newNetwork.networkCapabilities); - final int newPermission = getNetworkPermission(newNc); - if (oldPermission != newPermission) { - try { - mNMS.setNetworkPermission(newNetwork.network.netId, newPermission); - } catch (RemoteException e) { - loge("Exception in setNetworkPermission: " + e); - } - } - - newNetwork.getAndSetNetworkCapabilities(newNc); - notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_CAP_CHANGED); - } - - processNewlySatisfiedListenRequests(newNetwork); } /** @@ -6495,6 +6474,17 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkAgentInfo newDefaultNetwork = getDefaultNetwork(); + for (final NetworkReassignment.NetworkBgStatePair event : changes.getRematchedNetworks()) { + // Process listen requests and update capabilities if the background state has + // changed for this network. For consistency with previous behavior, send onLost + // callbacks before onAvailable. + processNewlyLostListenRequests(event.mNetwork); + if (event.mOldBackground != event.mNetwork.isBackgroundNetwork()) { + applyBackgroundChangeForRematch(event.mNetwork); + } + processNewlySatisfiedListenRequests(event.mNetwork); + } + for (final NetworkAgentInfo nai : nais) { // Rematching may have altered the linger state of some networks, so update all linger // timers. updateLingerState reads the state from the network agent and does nothing @@ -6526,6 +6516,24 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + /** + * Apply a change in background state resulting from rematching networks with requests. + * + * During rematch, a network may change background states by starting to satisfy or stopping + * to satisfy a foreground request. Listens don't count for this. When a network changes + * background states, its capabilities need to be updated and callbacks fired for the + * capability change. + * + * @param nai The network that changed background states + */ + private void applyBackgroundChangeForRematch(@NonNull final NetworkAgentInfo nai) { + final NetworkCapabilities newNc = mixInCapabilities(nai, nai.networkCapabilities); + if (Objects.equals(nai.networkCapabilities, newNc)) return; + updateNetworkPermissions(nai, newNc); + nai.getAndSetNetworkCapabilities(newNc); + notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED); + } + private void updateLegacyTypeTrackerAndVpnLockdownForRematch( @Nullable final NetworkAgentInfo oldDefaultNetwork, @Nullable final NetworkAgentInfo newDefaultNetwork,