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

Commit ac955b31 authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

Don't crash ConnectivityService if the network stack crashes.

When the network stack crashes, the system will rebind to it.
Existing references are no longer useful (they just throw
RemoteException) but if the system is still up, then the user
can at least recover the situation by taking actions such as
going into airplane mode, toggling wifi, etc.

This CL stops ConnectivityService from crashing the system when
it cannot talk to NetworkMonitor. This is arguably better than
crashing the system, because crashing the system is disruptive
and carries the serious risk of a bootloop from which it is not
possible to recover.

NetworkStackClient already contains code to crash the system
when the network stack crashes. This change help ensure that
if a crash occurs, it is the result of an explicit decision by
that code instead of an unchecked exception in one of the callers
of the network stack.

Bug: 133725814
Test: builds, boots
Test: atest FrameworksNetTests NetworkStackTests
Change-Id: Ib9a15fececd8579fc5b139fe0341275a45512e0f
parent 836f6a4a
Loading
Loading
Loading
Loading
+15 −50
Original line number Original line Diff line number Diff line
@@ -91,6 +91,7 @@ import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc;
import android.net.NetworkMisc;
import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkQuotaInfo;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkRequest;
@@ -1784,8 +1785,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
            // callback from each caller type. Need to re-factor NetdEventListenerService to allow
            // callback from each caller type. Need to re-factor NetdEventListenerService to allow
            // multiple NetworkMonitor registrants.
            // multiple NetworkMonitor registrants.
            if (nai != null && nai.satisfies(mDefaultRequest)) {
            if (nai != null && nai.satisfies(mDefaultRequest)) {
                Binder.withCleanCallingIdentity(() ->
                nai.networkMonitor().notifyDnsResponse(returnCode);
                        nai.networkMonitor().notifyDnsResponse(returnCode));
            }
            }
        }
        }


@@ -2852,11 +2852,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        // Notify the NetworkAgentInfo/NetworkMonitor in case NetworkMonitor needs to cancel or
        // Notify the NetworkAgentInfo/NetworkMonitor in case NetworkMonitor needs to cancel or
        // schedule DNS resolutions. If a DNS resolution is required the
        // schedule DNS resolutions. If a DNS resolution is required the
        // result will be sent back to us.
        // result will be sent back to us.
        try {
        nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
        nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
        }


        // With Private DNS bypass support, we can proceed to update the
        // With Private DNS bypass support, we can proceed to update the
        // Private DNS config immediately, even if we're in strict mode
        // Private DNS config immediately, even if we're in strict mode
@@ -3022,11 +3018,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
            // Disable wakeup packet monitoring for each interface.
            // Disable wakeup packet monitoring for each interface.
            wakeupModifyInterface(iface, nai.networkCapabilities, false);
            wakeupModifyInterface(iface, nai.networkCapabilities, false);
        }
        }
        try {
        nai.networkMonitor().notifyNetworkDisconnected();
        nai.networkMonitor().notifyNetworkDisconnected();
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
        }
        mNetworkAgentInfos.remove(nai.messenger);
        mNetworkAgentInfos.remove(nai.messenger);
        nai.clatd.update();
        nai.clatd.update();
        synchronized (mNetworkForNetId) {
        synchronized (mNetworkForNetId) {
@@ -3439,11 +3431,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
            //
            //
            // TODO: NetworkMonitor does not refer to the "never ask again" bit. The bit is stored
            // TODO: NetworkMonitor does not refer to the "never ask again" bit. The bit is stored
            // per network. Therefore, NetworkMonitor may still do https probe.
            // per network. Therefore, NetworkMonitor may still do https probe.
            try {
            nai.networkMonitor().setAcceptPartialConnectivity();
            nai.networkMonitor().setAcceptPartialConnectivity();
            } catch (RemoteException e) {
                e.rethrowAsRuntimeException();
            }
        }
        }
    }
    }


@@ -3475,11 +3463,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
            NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
            NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
            if (nai == null) return;
            if (nai == null) return;
            if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
            if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
            try {
            nai.networkMonitor().launchCaptivePortalApp();
            nai.networkMonitor().launchCaptivePortalApp();
            } catch (RemoteException e) {
                e.rethrowAsRuntimeException();
            }
        });
        });
    }
    }


@@ -3514,7 +3498,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }
        }


        @Override
        @Override
        public void appResponse(final int response) throws RemoteException {
        public void appResponse(final int response) {
            if (response == CaptivePortal.APP_RETURN_WANTED_AS_IS) {
            if (response == CaptivePortal.APP_RETURN_WANTED_AS_IS) {
                enforceSettingsPermission();
                enforceSettingsPermission();
            }
            }
@@ -3524,16 +3508,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
            if (nai == null) return;
            if (nai == null) return;


            // nai.networkMonitor() is thread-safe
            // nai.networkMonitor() is thread-safe
            final INetworkMonitor nm = nai.networkMonitor();
            final NetworkMonitorManager nm = nai.networkMonitor();
            if (nm == null) return;
            if (nm == null) return;

            final long token = Binder.clearCallingIdentity();
            try {
            nm.notifyCaptivePortalAppFinished(response);
            nm.notifyCaptivePortalAppFinished(response);
            } finally {
                // Not using Binder.withCleanCallingIdentity() to keep the checked RemoteException
                Binder.restoreCallingIdentity(token);
            }
        }
        }


        @Override
        @Override
@@ -4104,11 +4081,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
        if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
            return;
            return;
        }
        }
        try {
        nai.networkMonitor().forceReevaluation(uid);
        nai.networkMonitor().forceReevaluation(uid);
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
        }
    }
    }


    /**
    /**
@@ -5541,11 +5514,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
            // Start or stop DNS64 detection and 464xlat according to network state.
            // Start or stop DNS64 detection and 464xlat according to network state.
            networkAgent.clatd.update();
            networkAgent.clatd.update();
            notifyIfacesChangedForNetworkStats();
            notifyIfacesChangedForNetworkStats();
            try {
            networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
            networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
            } catch (RemoteException e) {
                e.rethrowAsRuntimeException();
            }
            if (networkAgent.everConnected) {
            if (networkAgent.everConnected) {
                notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
                notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
            }
            }
@@ -6529,15 +6498,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
            // command must be sent after updating LinkProperties to maximize chances of
            // command must be sent after updating LinkProperties to maximize chances of
            // NetworkMonitor seeing the correct LinkProperties when starting.
            // NetworkMonitor seeing the correct LinkProperties when starting.
            // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
            // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
            try {
            if (networkAgent.networkMisc.acceptPartialConnectivity) {
            if (networkAgent.networkMisc.acceptPartialConnectivity) {
                networkAgent.networkMonitor().setAcceptPartialConnectivity();
                networkAgent.networkMonitor().setAcceptPartialConnectivity();
            }
            }
            networkAgent.networkMonitor().notifyNetworkConnected(
            networkAgent.networkMonitor().notifyNetworkConnected(
                    networkAgent.linkProperties, networkAgent.networkCapabilities);
                    networkAgent.linkProperties, networkAgent.networkCapabilities);
            } catch (RemoteException e) {
                e.rethrowAsRuntimeException();
            }
            scheduleUnvalidatedPrompt(networkAgent);
            scheduleUnvalidatedPrompt(networkAgent);


            // Whether a particular NetworkRequest listen should cause signal strength thresholds to
            // Whether a particular NetworkRequest listen should cause signal strength thresholds to
+7 −11
Original line number Original line Diff line number Diff line
@@ -25,12 +25,12 @@ import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo;
import android.net.NetworkMisc;
import android.net.NetworkMisc;
import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.NetworkState;
import android.os.Handler;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.INetworkManagementService;
import android.os.Messenger;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemClock;
import android.util.Log;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseArray;
@@ -247,7 +247,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
    public final Nat464Xlat clatd;
    public final Nat464Xlat clatd;


    // Set after asynchronous creation of the NetworkMonitor.
    // Set after asynchronous creation of the NetworkMonitor.
    private volatile INetworkMonitor mNetworkMonitor;
    private volatile NetworkMonitorManager mNetworkMonitor;


    private static final String TAG = ConnectivityService.class.getSimpleName();
    private static final String TAG = ConnectivityService.class.getSimpleName();
    private static final boolean VDBG = false;
    private static final boolean VDBG = false;
@@ -278,7 +278,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
     * Inform NetworkAgentInfo that a new NetworkMonitor was created.
     * Inform NetworkAgentInfo that a new NetworkMonitor was created.
     */
     */
    public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
    public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
        mNetworkMonitor = networkMonitor;
        mNetworkMonitor = new NetworkMonitorManager(networkMonitor);
    }
    }


    /**
    /**
@@ -290,13 +290,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
     */
     */
    public void setNetworkCapabilities(NetworkCapabilities nc) {
    public void setNetworkCapabilities(NetworkCapabilities nc) {
        networkCapabilities = nc;
        networkCapabilities = nc;
        final INetworkMonitor nm = mNetworkMonitor;
        final NetworkMonitorManager nm = mNetworkMonitor;
        if (nm != null) {
        if (nm != null) {
            try {
            nm.notifyNetworkCapabilitiesChanged(nc);
            nm.notifyNetworkCapabilitiesChanged(nc);
            } catch (RemoteException e) {
                Log.e(TAG, "Error notifying NetworkMonitor of updated NetworkCapabilities", e);
            }
        }
        }
    }
    }


@@ -317,11 +313,11 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
    }
    }


    /**
    /**
     * Get the INetworkMonitor in this NetworkAgentInfo.
     * Get the NetworkMonitorManager in this NetworkAgentInfo.
     *
     *
     * <p>This will be null before {@link #onNetworkMonitorCreated(INetworkMonitor)} is called.
     * <p>This will be null before {@link #onNetworkMonitorCreated(INetworkMonitor)} is called.
     */
     */
    public INetworkMonitor networkMonitor() {
    public NetworkMonitorManager networkMonitor() {
        return mNetworkMonitor;
        return mNetworkMonitor;
    }
    }