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

Commit 8e4f9929 authored by Mark Chien's avatar Mark Chien Committed by android-build-merger
Browse files

Merge "Track default upstream when system is ready"

am: d9eeba6f

Change-Id: I7febc52d94c1249b76608853d5cc142cdb8ad9df
parents a11f1d2d d9eeba6f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1968,6 +1968,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
    void systemReady() {
        mProxyTracker.loadGlobalProxy();
        registerNetdEventCallback();
        mTethering.systemReady();

        synchronized (this) {
            mSystemReady = true;
+5 −1
Original line number Diff line number Diff line
@@ -1382,7 +1382,7 @@ public class Tethering extends BaseNetworkObserver {
                    return;
                }

                mUpstreamNetworkMonitor.start(mDeps.getDefaultNetworkRequest());
                mUpstreamNetworkMonitor.startObserveAllNetworks();

                // TODO: De-duplicate with updateUpstreamWanted() below.
                if (upstreamWanted()) {
@@ -1658,6 +1658,10 @@ public class Tethering extends BaseNetworkObserver {
        }
    }

    public void systemReady() {
        mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest());
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        // Binder.java closes the resource for us.
+51 −44
Original line number Diff line number Diff line
@@ -55,10 +55,13 @@ import java.util.Set;
 * A class to centralize all the network and link properties information
 * pertaining to the current and any potential upstream network.
 *
 * Calling #start() registers two callbacks: one to track the system default
 * network and a second to observe all networks.  The latter is necessary
 * while the expression of preferred upstreams remains a list of legacy
 * connectivity types.  In future, this can be revisited.
 * The owner of UNM gets it to register network callbacks by calling the
 * following methods :
 * Calling #startTrackDefaultNetwork() to track the system default network.
 * Calling #startObserveAllNetworks() to observe all networks. Listening all
 * networks is necessary while the expression of preferred upstreams remains
 * a list of legacy connectivity types.  In future, this can be revisited.
 * Calling #registerMobileNetworkRequest() to bring up mobile DUN/HIPRI network.
 *
 * The methods and data members of this class are only to be accessed and
 * modified from the tethering master state machine thread. Any other
@@ -119,33 +122,31 @@ public class UpstreamNetworkMonitor {
        mCM = cm;
    }

    public void start(NetworkRequest defaultNetworkRequest) {
        stop();

        final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
                .clearCapabilities().build();
        mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL);
        cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler);

        if (defaultNetworkRequest != null) {
    public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest) {
        // This is not really a "request", just a way of tracking the system default network.
        // It's guaranteed not to actually bring up any networks because it's the same request
        // as the ConnectivityService default request, and thus shares fate with it. We can't
        // use registerDefaultNetworkCallback because it will not track the system default
        // network if there is a VPN that applies to our UID.
        if (mDefaultNetworkCallback == null) {
            final NetworkRequest trackDefaultRequest = new NetworkRequest(defaultNetworkRequest);
            mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
            cm().requestNetwork(trackDefaultRequest, mDefaultNetworkCallback, mHandler);
        }
    }

    public void startObserveAllNetworks() {
        stop();

        final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
                .clearCapabilities().build();
        mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL);
        cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler);
    }

    public void stop() {
        releaseMobileNetworkRequest();

        releaseCallback(mDefaultNetworkCallback);
        mDefaultNetworkCallback = null;
        mDefaultInternetNetwork = null;

        releaseCallback(mListenAllCallback);
        mListenAllCallback = null;

@@ -264,9 +265,7 @@ public class UpstreamNetworkMonitor {
        mNetworkMap.put(network, new NetworkState(null, null, null, network, null, null));
    }

    private void handleNetCap(int callbackType, Network network, NetworkCapabilities newNc) {
        if (callbackType == CALLBACK_DEFAULT_INTERNET) mDefaultInternetNetwork = network;

    private void handleNetCap(Network network, NetworkCapabilities newNc) {
        final NetworkState prev = mNetworkMap.get(network);
        if (prev == null || newNc.equals(prev.networkCapabilities)) {
            // Ignore notifications about networks for which we have not yet
@@ -315,21 +314,17 @@ public class UpstreamNetworkMonitor {
        notifyTarget(EVENT_ON_LINKPROPERTIES, network);
    }

    private void handleSuspended(int callbackType, Network network) {
        if (callbackType != CALLBACK_LISTEN_ALL) return;
    private void handleSuspended(Network network) {
        if (!network.equals(mTetheringUpstreamNetwork)) return;
        mLog.log("SUSPENDED current upstream: " + network);
    }

    private void handleResumed(int callbackType, Network network) {
        if (callbackType != CALLBACK_LISTEN_ALL) return;
    private void handleResumed(Network network) {
        if (!network.equals(mTetheringUpstreamNetwork)) return;
        mLog.log("RESUMED current upstream: " + network);
    }

    private void handleLost(int callbackType, Network network) {
        if (network.equals(mDefaultInternetNetwork)) {
            mDefaultInternetNetwork = null;
    private void handleLost(Network network) {
        // There are few TODOs within ConnectivityService's rematching code
        // pertaining to spurious onLost() notifications.
        //
@@ -338,8 +333,6 @@ public class UpstreamNetworkMonitor {
        //       been lost (by any callback)
        //     - deletes the entry from the map only when the LISTEN_ALL
        //       callback gets notified.
            if (callbackType == CALLBACK_DEFAULT_INTERNET) return;
        }

        if (!mNetworkMap.containsKey(network)) {
            // Ignore loss of networks about which we had not previously
@@ -393,11 +386,17 @@ public class UpstreamNetworkMonitor {

        @Override
        public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
            handleNetCap(mCallbackType, network, newNc);
            if (mCallbackType == CALLBACK_DEFAULT_INTERNET) {
                mDefaultInternetNetwork = network;
                return;
            }
            handleNetCap(network, newNc);
        }

        @Override
        public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
            if (mCallbackType == CALLBACK_DEFAULT_INTERNET) return;

            handleLinkProp(network, newLp);
            // Any non-LISTEN_ALL callback will necessarily concern a network that will
            // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
@@ -409,17 +408,25 @@ public class UpstreamNetworkMonitor {

        @Override
        public void onNetworkSuspended(Network network) {
            handleSuspended(mCallbackType, network);
            if (mCallbackType == CALLBACK_LISTEN_ALL) {
                handleSuspended(network);
            }
        }

        @Override
        public void onNetworkResumed(Network network) {
            handleResumed(mCallbackType, network);
            if (mCallbackType == CALLBACK_LISTEN_ALL) {
                handleResumed(network);
            }
        }

        @Override
        public void onLost(Network network) {
            handleLost(mCallbackType, network);
            if (mCallbackType == CALLBACK_DEFAULT_INTERNET) {
                mDefaultInternetNetwork = null;
                return;
            }
            handleLost(network);
            // Any non-LISTEN_ALL callback will necessarily concern a network that will
            // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
            // So it's not useful to do this work for non-LISTEN_ALL callbacks.
+2 −12
Original line number Diff line number Diff line
@@ -71,7 +71,6 @@ import android.net.MacAddress;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.RouteInfo;
@@ -130,10 +129,6 @@ public class TetheringTest {
    private static final String TEST_USB_IFNAME = "test_rndis0";
    private static final String TEST_WLAN_IFNAME = "test_wlan0";

    // Actual contents of the request don't matter for this test. The lack of
    // any specific TRANSPORT_* is sufficient to identify this request.
    private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build();

    @Mock private ApplicationInfo mApplicationInfo;
    @Mock private Context mContext;
    @Mock private INetworkManagementService mNMService;
@@ -257,11 +252,6 @@ public class TetheringTest {
            isTetheringSupportedCalls++;
            return true;
        }

        @Override
        public NetworkRequest getDefaultNetworkRequest() {
            return mDefaultRequest;
        }
    }

    private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
@@ -496,7 +486,7 @@ public class TetheringTest {
                TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
        verifyNoMoreInteractions(mWifiManager);
        verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
        verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
        verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
        // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
        assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);

@@ -730,7 +720,7 @@ public class TetheringTest {
                TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
        verifyNoMoreInteractions(mWifiManager);
        verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
        verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
        verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
        // In tethering mode, in the default configuration, an explicit request
        // for a mobile network is also made.
        verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
+38 −27
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -53,7 +54,6 @@ import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.util.SharedLog;

import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

@@ -65,7 +65,6 @@ import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
@@ -126,7 +125,7 @@ public class UpstreamNetworkMonitorTest {
    }

    @Test
    public void testDoesNothingBeforeStarted() {
    public void testDoesNothingBeforeTrackDefaultAndStarted() throws Exception {
        assertTrue(mCM.hasNoCallbacks());
        assertFalse(mUNM.mobileNetworkRequested());

@@ -138,37 +137,40 @@ public class UpstreamNetworkMonitorTest {

    @Test
    public void testDefaultNetworkIsTracked() throws Exception {
        assertEquals(0, mCM.trackingDefault.size());
        assertTrue(mCM.hasNoCallbacks());
        mUNM.startTrackDefaultNetwork(mDefaultRequest);

        mUNM.start(mDefaultRequest);
        mUNM.startObserveAllNetworks();
        assertEquals(1, mCM.trackingDefault.size());

        mUNM.stop();
        assertTrue(mCM.hasNoCallbacks());
        assertTrue(mCM.onlyHasDefaultCallbacks());
    }

    @Test
    public void testListensForAllNetworks() throws Exception {
        assertTrue(mCM.listening.isEmpty());

        mUNM.start(mDefaultRequest);
        mUNM.startTrackDefaultNetwork(mDefaultRequest);
        mUNM.startObserveAllNetworks();
        assertFalse(mCM.listening.isEmpty());
        assertTrue(mCM.isListeningForAll());

        mUNM.stop();
        assertTrue(mCM.hasNoCallbacks());
        assertTrue(mCM.onlyHasDefaultCallbacks());
    }

    @Test
    public void testCallbacksRegistered() {
        mUNM.start(mDefaultRequest);
        verify(mCM, times(1)).registerNetworkCallback(
                any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
        mUNM.startTrackDefaultNetwork(mDefaultRequest);
        verify(mCM, times(1)).requestNetwork(
                eq(mDefaultRequest), any(NetworkCallback.class), any(Handler.class));
        mUNM.startObserveAllNetworks();
        verify(mCM, times(1)).registerNetworkCallback(
                any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));

        mUNM.stop();
        verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class));
        verify(mCM, times(1)).unregisterNetworkCallback(any(NetworkCallback.class));
    }

    @Test
@@ -176,7 +178,7 @@ public class UpstreamNetworkMonitorTest {
        assertFalse(mUNM.mobileNetworkRequested());
        assertEquals(0, mCM.requested.size());

        mUNM.start(mDefaultRequest);
        mUNM.startObserveAllNetworks();
        assertFalse(mUNM.mobileNetworkRequested());
        assertEquals(0, mCM.requested.size());

@@ -199,11 +201,9 @@ public class UpstreamNetworkMonitorTest {
        assertFalse(mUNM.mobileNetworkRequested());
        assertEquals(0, mCM.requested.size());

        mUNM.start(mDefaultRequest);
        mUNM.startObserveAllNetworks();
        verify(mCM, times(1)).registerNetworkCallback(
                any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
        verify(mCM, times(1)).requestNetwork(
                eq(mDefaultRequest), any(NetworkCallback.class), any(Handler.class));
        assertFalse(mUNM.mobileNetworkRequested());
        assertEquals(0, mCM.requested.size());

@@ -227,7 +227,7 @@ public class UpstreamNetworkMonitorTest {
        assertTrue(mCM.isDunRequested());

        mUNM.stop();
        verify(mCM, times(3)).unregisterNetworkCallback(any(NetworkCallback.class));
        verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class));

        verifyNoMoreInteractions(mCM);
    }
@@ -237,7 +237,7 @@ public class UpstreamNetworkMonitorTest {
        assertFalse(mUNM.mobileNetworkRequested());
        assertEquals(0, mCM.requested.size());

        mUNM.start(mDefaultRequest);
        mUNM.startObserveAllNetworks();
        assertFalse(mUNM.mobileNetworkRequested());
        assertEquals(0, mCM.requested.size());

@@ -257,7 +257,7 @@ public class UpstreamNetworkMonitorTest {

    @Test
    public void testUpdateMobileRequiresDun() throws Exception {
        mUNM.start(mDefaultRequest);
        mUNM.startObserveAllNetworks();

        // Test going from no-DUN to DUN correctly re-registers callbacks.
        mUNM.updateMobileRequiresDun(false);
@@ -285,7 +285,8 @@ public class UpstreamNetworkMonitorTest {
        final Collection<Integer> preferredTypes = new ArrayList<>();
        preferredTypes.add(TYPE_WIFI);

        mUNM.start(mDefaultRequest);
        mUNM.startTrackDefaultNetwork(mDefaultRequest);
        mUNM.startObserveAllNetworks();
        // There are no networks, so there is nothing to select.
        assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));

@@ -350,7 +351,8 @@ public class UpstreamNetworkMonitorTest {

    @Test
    public void testGetCurrentPreferredUpstream() throws Exception {
        mUNM.start(mDefaultRequest);
        mUNM.startTrackDefaultNetwork(mDefaultRequest);
        mUNM.startObserveAllNetworks();
        mUNM.updateMobileRequiresDun(false);

        // [0] Mobile connects, DUN not required -> mobile selected.
@@ -389,7 +391,8 @@ public class UpstreamNetworkMonitorTest {

    @Test
    public void testLocalPrefixes() throws Exception {
        mUNM.start(mDefaultRequest);
        mUNM.startTrackDefaultNetwork(mDefaultRequest);
        mUNM.startObserveAllNetworks();

        // [0] Test minimum set of local prefixes.
        Set<IpPrefix> local = mUNM.getLocalPrefixes();
@@ -521,11 +524,19 @@ public class UpstreamNetworkMonitorTest {
        }

        boolean hasNoCallbacks() {
            return allCallbacks.isEmpty() &&
                   trackingDefault.isEmpty() &&
                   listening.isEmpty() &&
                   requested.isEmpty() &&
                   legacyTypeMap.isEmpty();
            return allCallbacks.isEmpty()
                    && trackingDefault.isEmpty()
                    && listening.isEmpty()
                    && requested.isEmpty()
                    && legacyTypeMap.isEmpty();
        }

        boolean onlyHasDefaultCallbacks() {
            return (allCallbacks.size() == 1)
                    && (trackingDefault.size() == 1)
                    && listening.isEmpty()
                    && requested.isEmpty()
                    && legacyTypeMap.isEmpty();
        }

        boolean isListeningForAll() {