Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc2aa347 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Luke Huang
Browse files

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

Merged-In: I388e208143c38b89bcbb0589de393250024d59aa
(cherry picked from commit 204ca13e)

Change-Id: I4d3dfd9305b60a724aa2dc38448948d8e710c932
parent 0c0106f5
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -362,18 +362,6 @@ interface INetworkManagementService
     */
    boolean isNetworkActive();

    /**
     * Setup a new physical network.
     * @param permission PERMISSION_NONE if no permissions required to access this network.
     *                   PERMISSION_NETWORK or PERMISSION_SYSTEM to set respective permission.
     */
    void createPhysicalNetwork(int netId, int permission);

    /**
     * Setup a new VPN.
     */
    void createVirtualNetwork(int netId, boolean secure);

    /**
     * Add an interface to a network.
     */
+31 −20
Original line number Diff line number Diff line
@@ -3071,11 +3071,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) {
@@ -3083,6 +3079,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.
@@ -6476,21 +6501,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;
        }

+0 −22
Original line number Diff line number Diff line
@@ -2050,28 +2050,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
        pw.println("]");
    }

    @Override
    public void createPhysicalNetwork(int netId, int permission) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);

        try {
            mNetdService.networkCreatePhysical(netId, permission);
        } catch (RemoteException | ServiceSpecificException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void createVirtualNetwork(int netId, boolean secure) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);

        try {
            mNetdService.networkCreateVpn(netId, secure);
        } catch (RemoteException | ServiceSpecificException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void addInterfaceToNetwork(String iface, int netId) {
        modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface);
+0 −6
Original line number Diff line number Diff line
@@ -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);
    }
+12 −2
Original line number Diff line number Diff line
@@ -4894,7 +4894,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);

@@ -4978,6 +4981,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();
@@ -5851,12 +5856,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);

@@ -6048,7 +6058,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);