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

Commit 68b9e68a authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Automerger Merge Worker
Browse files

Merge "[SB Refactor] Account for underlying wifi networks in old pipeline."...

Merge "[SB Refactor] Account for underlying wifi networks in old pipeline." into udc-dev am: 55282bc6

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22820241



Change-Id: Ie34f14b36b8c73db949a76309bf0c682977b070e
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 809058ce 55282bc6
Loading
Loading
Loading
Loading
+79 −25
Original line number Diff line number Diff line
@@ -14,7 +14,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
@@ -26,6 +28,8 @@ import android.net.NetworkKey;
import android.net.NetworkRequest;
import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
import android.net.TransportInfo;
import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
@@ -34,8 +38,9 @@ import android.os.HandlerThread;
import android.os.Looper;
import android.provider.Settings;

import androidx.annotation.Nullable;

import com.android.settingslib.R;
import com.android.settingslib.Utils;

import java.io.PrintWriter;
import java.text.SimpleDateFormat;
@@ -46,6 +51,7 @@ import java.util.Set;
/**
 * Track status of Wi-Fi for the Sys UI.
 */
@SuppressLint("MissingPermission")
public class WifiStatusTracker {
    private static final int HISTORY_SIZE = 32;
    private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -66,8 +72,9 @@ public class WifiStatusTracker {
    private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
            .clearCapabilities()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build();
            .addTransportType(TRANSPORT_WIFI)
            .addTransportType(TRANSPORT_CELLULAR)
            .build();
    private final NetworkCallback mNetworkCallback =
            new NetworkCallback(NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
        // Note: onCapabilitiesChanged is guaranteed to be called "immediately" after onAvailable
@@ -75,18 +82,10 @@ public class WifiStatusTracker {
        @Override
        public void onCapabilitiesChanged(
                Network network, NetworkCapabilities networkCapabilities) {
            boolean isVcnOverWifi = false;
            boolean isWifi = false;
            WifiInfo wifiInfo = null;
            if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                wifiInfo = Utils.tryGetWifiInfoForVcn(networkCapabilities);
                isVcnOverWifi = (wifiInfo != null);
            } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
                isWifi = true;
            }
            WifiInfo wifiInfo = getMainOrUnderlyingWifiInfo(networkCapabilities);
            boolean isWifi = connectionIsWifi(networkCapabilities, wifiInfo);
            // As long as it is a WiFi network, we will log it in the dumpsys for debugging.
            if (isVcnOverWifi || isWifi) {
            if (isWifi) {
                String log = new StringBuilder()
                        .append(SSDF.format(System.currentTimeMillis())).append(",")
                        .append("onCapabilitiesChanged: ")
@@ -303,17 +302,8 @@ public class WifiStatusTracker {
            return;
        }
        NetworkCapabilities networkCapabilities;
        isDefaultNetwork = false;
        if (mDefaultNetworkCapabilities != null) {
            boolean isWifi = mDefaultNetworkCapabilities.hasTransport(
                    NetworkCapabilities.TRANSPORT_WIFI);
            boolean isVcnOverWifi = mDefaultNetworkCapabilities.hasTransport(
                    NetworkCapabilities.TRANSPORT_CELLULAR)
                            && (Utils.tryGetWifiInfoForVcn(mDefaultNetworkCapabilities) != null);
            if (isWifi || isVcnOverWifi) {
                isDefaultNetwork = true;
            }
        }
        isDefaultNetwork = mDefaultNetworkCapabilities != null
                && connectionIsWifi(mDefaultNetworkCapabilities);
        if (isDefaultNetwork) {
            // Wifi is connected and the default network.
            networkCapabilities = mDefaultNetworkCapabilities;
@@ -352,6 +342,70 @@ public class WifiStatusTracker {
                ? null : AccessPoint.getSpeedLabel(mContext, scoredNetwork, rssi);
    }

    @Nullable
    private WifiInfo getMainOrUnderlyingWifiInfo(NetworkCapabilities networkCapabilities) {
        WifiInfo mainWifiInfo = getMainWifiInfo(networkCapabilities);
        if (mainWifiInfo != null) {
            return mainWifiInfo;
        }

        // Only CELLULAR networks may have underlying wifi information that's relevant to SysUI,
        // so skip the underlying network check if it's not CELLULAR.
        if (!networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
            return mainWifiInfo;
        }

        List<Network> underlyingNetworks = networkCapabilities.getUnderlyingNetworks();
        if (underlyingNetworks == null) {
            return null;
        }

        // Some connections, like VPN connections, may have underlying networks that are
        // eventually traced to a wifi or carrier merged connection. So, check those underlying
        // networks for possible wifi information as well. See b/225902574.
        for (Network underlyingNetwork : underlyingNetworks) {
            NetworkCapabilities underlyingNetworkCapabilities =
                    mConnectivityManager.getNetworkCapabilities(underlyingNetwork);
            WifiInfo underlyingWifiInfo = getMainWifiInfo(underlyingNetworkCapabilities);
            if (underlyingWifiInfo != null) {
                return underlyingWifiInfo;
            }
        }

        return null;
    }

    @Nullable
    private WifiInfo getMainWifiInfo(NetworkCapabilities networkCapabilities) {
        boolean canHaveWifiInfo = networkCapabilities.hasTransport(TRANSPORT_WIFI)
                || networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
        if (!canHaveWifiInfo) {
            return null;
        }

        TransportInfo transportInfo = networkCapabilities.getTransportInfo();
        if (transportInfo instanceof VcnTransportInfo) {
            // This VcnTransportInfo logic is copied from
            // [com.android.settingslib.Utils.tryGetWifiInfoForVcn]. It's copied instead of
            // re-used because it makes the logic here clearer.
            return ((VcnTransportInfo) transportInfo).getWifiInfo();
        } else if (transportInfo instanceof WifiInfo) {
            return (WifiInfo) transportInfo;
        } else {
            return null;
        }
    }

    private boolean connectionIsWifi(NetworkCapabilities networkCapabilities) {
        return connectionIsWifi(
                networkCapabilities,
                getMainOrUnderlyingWifiInfo(networkCapabilities));
    }

    private boolean connectionIsWifi(NetworkCapabilities networkCapabilities, WifiInfo wifiInfo) {
        return wifiInfo != null || networkCapabilities.hasTransport(TRANSPORT_WIFI);
    }

    /** Refresh the status label on Locale changed. */
    public void refreshLocale() {
        updateStatusLabel();
+197 −14
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;

import java.util.Arrays;

@RunWith(RobolectricTestRunner.class)
public class WifiStatusTrackerTest {
    @Mock Context mContext;
@@ -48,13 +50,32 @@ public class WifiStatusTrackerTest {
    @Mock ConnectivityManager mConnectivityManager;
    @Mock Runnable mCallback;

    private WifiStatusTracker mWifiStatusTracker;

    private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
            mNetworkCallbackCaptor =
            ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);

    private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
            mDefaultNetworkCallbackCaptor =
            ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        mWifiStatusTracker = new WifiStatusTracker(
                mContext,
                mWifiManager,
                mNetworkScoreManager,
                mConnectivityManager,
                mCallback);
        mWifiStatusTracker.setListening(true);

        verify(mConnectivityManager)
                .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
        verify(mConnectivityManager)
                .registerDefaultNetworkCallback(mDefaultNetworkCallbackCaptor.capture(), any());
    }

    /**
@@ -62,13 +83,6 @@ public class WifiStatusTrackerTest {
     */
    @Test
    public void testWifiInfoClearedOnPrimaryNetworkLost() {
        WifiStatusTracker wifiStatusTracker = new WifiStatusTracker(mContext, mWifiManager,
                mNetworkScoreManager, mConnectivityManager, mCallback);
        wifiStatusTracker.setListening(true);

        verify(mConnectivityManager)
                .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());

        // Trigger a validation callback for the primary Wifi network.
        WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
        when(primaryWifiInfo.makeCopy(anyLong())).thenReturn(primaryWifiInfo);
@@ -86,8 +100,8 @@ public class WifiStatusTrackerTest {
        mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);

        // Verify primary wifi info is the one being used.
        assertThat(wifiStatusTracker.connected).isTrue();
        assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
        assertThat(mWifiStatusTracker.connected).isTrue();
        assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);

        // Trigger a validation callback for the non-primary Wifi network.
        WifiInfo nonPrimaryWifiInfo = Mockito.mock(WifiInfo.class);
@@ -106,20 +120,189 @@ public class WifiStatusTrackerTest {
        mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(nonPrimaryNetwork, nonPrimaryCap);

        // Verify primary wifi info is still the one being used.
        assertThat(wifiStatusTracker.connected).isTrue();
        assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
        assertThat(mWifiStatusTracker.connected).isTrue();
        assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);

        // Lose the non-primary network.
        mNetworkCallbackCaptor.getValue().onLost(nonPrimaryNetwork);

        // Verify primary wifi info is still the one being used.
        assertThat(wifiStatusTracker.connected).isTrue();
        assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
        assertThat(mWifiStatusTracker.connected).isTrue();
        assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);

        // Lose the primary network.
        mNetworkCallbackCaptor.getValue().onLost(primaryNetwork);

        // Verify we aren't connected anymore.
        assertThat(wifiStatusTracker.connected).isFalse();
        assertThat(mWifiStatusTracker.connected).isFalse();
    }

    @Test
    public void isCarrierMerged_typicalWifi_false() {
        WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
        when(primaryWifiInfo.isPrimary()).thenReturn(true);

        NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
        when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)).thenReturn(true);
        when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);

        Network primaryNetwork = Mockito.mock(Network.class);
        int primaryNetworkId = 1;
        when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);

        mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);

        assertThat(mWifiStatusTracker.isCarrierMerged).isFalse();
    }

    @Test
    public void isCarrierMerged_typicalCellular_false() {
        NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
        when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);

        Network primaryNetwork = Mockito.mock(Network.class);
        int primaryNetworkId = 1;
        when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);

        mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);

        assertThat(mWifiStatusTracker.isCarrierMerged).isFalse();
    }

    @Test
    public void isCarrierMerged_cellularCarrierMergedWifi_true() {
        WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
        when(primaryWifiInfo.isPrimary()).thenReturn(true);
        when(primaryWifiInfo.isCarrierMerged()).thenReturn(true);

        NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
        when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
        when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);

        Network primaryNetwork = Mockito.mock(Network.class);
        int primaryNetworkId = 1;
        when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);

        mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);

        assertThat(mWifiStatusTracker.isCarrierMerged).isTrue();
    }

    /** Test for b/225902574. */
    @Test
    public void isCarrierMerged_cellularWithUnderlyingCarrierMergedWifi_true() {
        WifiInfo underlyingCarrierMergedInfo = Mockito.mock(WifiInfo.class);
        when(underlyingCarrierMergedInfo.isPrimary()).thenReturn(true);
        when(underlyingCarrierMergedInfo.isCarrierMerged()).thenReturn(true);

        NetworkCapabilities underlyingNetworkCapabilities = Mockito.mock(NetworkCapabilities.class);
        when(underlyingNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
                .thenReturn(true);
        when(underlyingNetworkCapabilities.getTransportInfo())
                .thenReturn(underlyingCarrierMergedInfo);

        Network underlyingNetwork = Mockito.mock(Network.class);
        when(mConnectivityManager.getNetworkCapabilities(underlyingNetwork))
                .thenReturn(underlyingNetworkCapabilities);

        NetworkCapabilities mainCapabilities = Mockito.mock(NetworkCapabilities.class);
        when(mainCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
                .thenReturn(true);
        when(mainCapabilities.getTransportInfo()).thenReturn(null);
        when(mainCapabilities.getUnderlyingNetworks())
                .thenReturn(Arrays.asList(underlyingNetwork));

        Network primaryNetwork = Mockito.mock(Network.class);
        int primaryNetworkId = 1;
        when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);

        mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, mainCapabilities);

        assertThat(mWifiStatusTracker.isCarrierMerged).isTrue();
    }

    @Test
    public void isDefaultNetwork_typicalWifi_true() {
        WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
        when(primaryWifiInfo.isPrimary()).thenReturn(true);

        NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
        when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)).thenReturn(true);
        when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);

        Network primaryNetwork = Mockito.mock(Network.class);
        int primaryNetworkId = 1;
        when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);

        mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);

        assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
    }

    @Test
    public void isDefaultNetwork_typicalCellular_false() {
        NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
        when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);

        Network primaryNetwork = Mockito.mock(Network.class);
        int primaryNetworkId = 1;
        when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);

        mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);

        assertThat(mWifiStatusTracker.isDefaultNetwork).isFalse();
    }

    @Test
    public void isDefaultNetwork_cellularCarrierMergedWifi_true() {
        WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
        when(primaryWifiInfo.isPrimary()).thenReturn(true);
        when(primaryWifiInfo.isCarrierMerged()).thenReturn(true);

        NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
        when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
        when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);

        Network primaryNetwork = Mockito.mock(Network.class);
        int primaryNetworkId = 1;
        when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);

        mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);

        assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
    }

    /** Test for b/225902574. */
    @Test
    public void isDefaultNetwork_cellularWithUnderlyingCarrierMergedWifi_true() {
        WifiInfo underlyingCarrierMergedInfo = Mockito.mock(WifiInfo.class);
        when(underlyingCarrierMergedInfo.isPrimary()).thenReturn(true);
        when(underlyingCarrierMergedInfo.isCarrierMerged()).thenReturn(true);

        NetworkCapabilities underlyingNetworkCapabilities = Mockito.mock(NetworkCapabilities.class);
        when(underlyingNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
                .thenReturn(true);
        when(underlyingNetworkCapabilities.getTransportInfo())
                .thenReturn(underlyingCarrierMergedInfo);

        Network underlyingNetwork = Mockito.mock(Network.class);
        when(mConnectivityManager.getNetworkCapabilities(underlyingNetwork))
                .thenReturn(underlyingNetworkCapabilities);

        NetworkCapabilities mainCapabilities = Mockito.mock(NetworkCapabilities.class);
        when(mainCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
                .thenReturn(true);
        when(mainCapabilities.getTransportInfo()).thenReturn(null);
        when(mainCapabilities.getUnderlyingNetworks())
                .thenReturn(Arrays.asList(underlyingNetwork));

        Network primaryNetwork = Mockito.mock(Network.class);
        int primaryNetworkId = 1;
        when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);

        mDefaultNetworkCallbackCaptor.getValue()
                .onCapabilitiesChanged(primaryNetwork, mainCapabilities);

        assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
    }
}