From fdd11f803c75094e361ed67612733cbea8303ac8 Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Tue, 9 Apr 2019 18:41:49 +0800 Subject: [PATCH] Make DNS cache lifecycle management explicit 1. ConnectivityService calls netd binder to create/destroy network directly. 2. Call dnsresolver binder to create/destroy cache after create/destroy network. 3. Remove unused network create/destroy methods in NetworkManagementService. Bug: 129453995 Test: atest FrameworksNetTests Change-Id: I15660d27f735e33d621d4af8972cdf115bf76dfa --- .../android/server/ConnectivityService.java | 51 +++++++++++-------- .../server/connectivity/DnsManager.java | 6 --- .../server/ConnectivityServiceTest.java | 14 ++++- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 244fef4f8d..56d4e02b52 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3065,11 +3065,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // fallback network the default or requested a new network from the // NetworkFactories, so network traffic isn't interrupted for an unnecessarily // long time. - try { - mNetd.networkDestroy(nai.network.netId); - } catch (RemoteException | ServiceSpecificException e) { - loge("Exception destroying network: " + e); - } + destroyNativeNetwork(nai); mDnsManager.removeNetwork(nai.network); } synchronized (mNetworkForNetId) { @@ -3077,6 +3073,35 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) { + try { + // This should never fail. Specifying an already in use NetID will cause failure. + if (networkAgent.isVPN()) { + mNetd.networkCreateVpn(networkAgent.network.netId, + (networkAgent.networkMisc == null + || !networkAgent.networkMisc.allowBypass)); + } else { + mNetd.networkCreatePhysical(networkAgent.network.netId, + getNetworkPermission(networkAgent.networkCapabilities)); + } + mDnsResolver.createNetworkCache(networkAgent.network.netId); + return true; + } catch (RemoteException | ServiceSpecificException e) { + loge("Error creating network " + networkAgent.network.netId + ": " + + e.getMessage()); + return false; + } + } + + private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) { + try { + mNetd.networkDestroy(networkAgent.network.netId); + mDnsResolver.destroyNetworkCache(networkAgent.network.netId); + } catch (RemoteException | ServiceSpecificException e) { + loge("Exception destroying network: " + e); + } + } + // If this method proves to be too slow then we can maintain a separate // pendingIntent => NetworkRequestInfo map. // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo. @@ -6477,21 +6502,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // A network that has just connected has zero requests and is thus a foreground network. networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND); - try { - // This should never fail. Specifying an already in use NetID will cause failure. - if (networkAgent.isVPN()) { - mNMS.createVirtualNetwork(networkAgent.network.netId, - (networkAgent.networkMisc == null || - !networkAgent.networkMisc.allowBypass)); - } else { - mNMS.createPhysicalNetwork(networkAgent.network.netId, - getNetworkPermission(networkAgent.networkCapabilities)); - } - } catch (Exception e) { - loge("Error creating network " + networkAgent.network.netId + ": " - + e.getMessage()); - return; - } + if (!createNativeNetwork(networkAgent)) return; networkAgent.created = true; } diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java index e33392d359..2321afb7df 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/services/core/java/com/android/server/connectivity/DnsManager.java @@ -263,12 +263,6 @@ public class DnsManager { } public void removeNetwork(Network network) { - try { - mDnsResolver.clearResolverConfiguration(network.netId); - } catch (RemoteException | ServiceSpecificException e) { - Slog.e(TAG, "Error clearing DNS configuration: " + e); - return; - } mPrivateDnsMap.remove(network.netId); mPrivateDnsValidationMap.remove(network.netId); } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index e3c6c4113c..77dc3ac8f3 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -4868,7 +4868,10 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(cellLp); mCellNetworkAgent.connect(false); waitForIdle(); - // CS tells netd about the empty DNS config for this network. + + verify(mMockDnsResolver, times(1)).createNetworkCache( + eq(mCellNetworkAgent.getNetwork().netId)); + // CS tells dnsresolver about the empty DNS config for this network. verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any()); reset(mMockDnsResolver); @@ -4952,6 +4955,8 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(cellLp); mCellNetworkAgent.connect(false); waitForIdle(); + verify(mMockDnsResolver, times(1)).createNetworkCache( + eq(mCellNetworkAgent.getNetwork().netId)); verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( mResolverParamsParcelCaptor.capture()); ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue(); @@ -5825,12 +5830,17 @@ public class ConnectivityServiceTest { cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME)); reset(mNetworkManagementService); reset(mMockDnsResolver); + reset(mMockNetd); when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME)) .thenReturn(getClatInterfaceConfig(myIpv4)); // Connect with ipv6 link properties. Expect prefix discovery to be started. mCellNetworkAgent.sendLinkProperties(cellLp); mCellNetworkAgent.connect(true); + + verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt()); + verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId)); + networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); @@ -6022,7 +6032,7 @@ public class ConnectivityServiceTest { verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME)); verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId)); verify(mMockDnsResolver, times(1)) - .clearResolverConfiguration(eq(mCellNetworkAgent.getNetwork().netId)); + .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId)); // Disconnect wifi ConditionVariable cv = waitForConnectivityBroadcasts(1);