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

Commit 8d4eb82d authored by Weng Su's avatar Weng Su
Browse files

Refer the SoftApCapability cache if getUsableChannels is unsupported

- Get SAP band capability from SoftApCapability#getSupportedChannelList

Bug: 272450463
Bug: 338503507
Bug: 340789513
Flag: EXEMPT bugfix
Test: Manual testing
atest -c WifiHotspotRepositoryTest

Change-Id: I7b792c27bc3c41e78417032f797d57b030d6db72
parent 13025136
Loading
Loading
Loading
Loading
+86 −45
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;

import android.content.Context;
import android.net.TetheringManager;
import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiAvailableChannel;
import android.net.wifi.WifiManager;
@@ -97,10 +98,10 @@ public class WifiHotspotRepository {

    protected Boolean mIsDualBand;
    protected Boolean mIs5gBandSupported;
    protected Boolean mIs5gAvailable;
    protected SapBand mBand5g = new SapBand(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS);
    protected MutableLiveData<Boolean> m5gAvailable;
    protected Boolean mIs6gBandSupported;
    protected Boolean mIs6gAvailable;
    protected SapBand mBand6g = new SapBand(WifiScanner.WIFI_BAND_6_GHZ);
    protected MutableLiveData<Boolean> m6gAvailable;
    protected ActiveCountryCodeChangedCallback mActiveCountryCodeChangedCallback;

@@ -388,15 +389,10 @@ public class WifiHotspotRepository {
     * @return {@code true} if Wi-Fi Hotspot 5 GHz Band is available
     */
    public boolean is5gAvailable() {
        if (mIs5gAvailable == null) {
            // If Settings is unable to get available 5GHz SAP information, Wi-Fi Framework's
            // proposal is to assume that 5GHz is available. (See b/272450463#comment16)
            mIs5gAvailable = is5GHzBandSupported()
                    && isChannelAvailable(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS,
                    true /* defaultValue */);
            log("is5gAvailable():" + mIs5gAvailable);
        if (!mBand5g.isUsableChannelsReady && is5GHzBandSupported()) {
            isChannelAvailable(mBand5g);
        }
        return mIs5gAvailable;
        return mBand5g.isAvailable();
    }

    /**
@@ -435,12 +431,10 @@ public class WifiHotspotRepository {
     * @return {@code true} if Wi-Fi Hotspot 6 GHz Band is available
     */
    public boolean is6gAvailable() {
        if (mIs6gAvailable == null) {
            mIs6gAvailable = is6GHzBandSupported()
                    && isChannelAvailable(WifiScanner.WIFI_BAND_6_GHZ, false /* defaultValue */);
            log("is6gAvailable():" + mIs6gAvailable);
        if (!mBand6g.isUsableChannelsReady && is6GHzBandSupported()) {
            isChannelAvailable(mBand6g);
        }
        return mIs6gAvailable;
        return mBand6g.isAvailable();
    }

    /**
@@ -463,28 +457,31 @@ public class WifiHotspotRepository {
    /**
     * Return whether the Hotspot channel is available or not.
     *
     * @param band         one of the following band constants defined in
     *                     {@code WifiScanner#WIFI_BAND_*} constants.
     * @param sapBand      The SapBand#band constants defined in {@code WifiScanner#WIFI_BAND_*}
     *                     1. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}
     *                     2. {@code WifiScanner#WIFI_BAND_6_GHZ}
     * @param defaultValue returns the default value if WifiManager#getUsableChannels is
     *                     unavailable to get the SAP information.
     */
    protected boolean isChannelAvailable(int band, boolean defaultValue) {
    @VisibleForTesting
    boolean isChannelAvailable(SapBand sapBand) {
        try {
            List<WifiAvailableChannel> channels = mWifiManager.getUsableChannels(band, OP_MODE_SAP);
            log("isChannelAvailable(), band:" + band + ", channels:" + channels);
            return (channels != null && channels.size() > 0);
            List<WifiAvailableChannel> channels =
                    mWifiManager.getUsableChannels(sapBand.band, OP_MODE_SAP);
            log("isChannelAvailable(), band:" + sapBand.band + ", channels:" + channels);
            sapBand.hasUsableChannels = (channels != null && channels.size() > 0);
            sapBand.isUsableChannelsUnsupported = false;
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Querying usable SAP channels failed, band:" + band);
            Log.e(TAG, "Querying usable SAP channels failed, band:" + sapBand.band);
            sapBand.hasUsableChannels = false;
            sapBand.isUsableChannelsUnsupported = true;
        } catch (UnsupportedOperationException e) {
            // This is expected on some hardware.
            Log.e(TAG, "Querying usable SAP channels is unsupported, band:" + band);
            Log.e(TAG, "Querying usable SAP channels is unsupported, band:" + sapBand.band);
            sapBand.hasUsableChannels = false;
            sapBand.isUsableChannelsUnsupported = true;
        }
        // Disable Wi-Fi hotspot speed feature if an error occurs while getting usable channels.
        mIsSpeedFeatureAvailable = false;
        Log.w(TAG, "isChannelAvailable(): Wi-Fi hotspot speed feature disabled");
        return defaultValue;
        sapBand.isUsableChannelsReady = true;
        log("isChannelAvailable(), " + sapBand);
        return sapBand.isAvailable();
    }

    private boolean isConfigShowSpeed() {
@@ -519,19 +516,6 @@ public class WifiHotspotRepository {
            log("isSpeedFeatureAvailable():false, 5 GHz band is not supported on this device");
            return false;
        }
        // Check if 5 GHz band SAP channel is not ready
        isChannelAvailable(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, true /* defaultValue */);
        if (mIsSpeedFeatureAvailable != null && !mIsSpeedFeatureAvailable) {
            log("isSpeedFeatureAvailable():false, error occurred while getting 5 GHz SAP channel");
            return false;
        }

        // Check if 6 GHz band SAP channel is not ready
        isChannelAvailable(WifiScanner.WIFI_BAND_6_GHZ, false /* defaultValue */);
        if (mIsSpeedFeatureAvailable != null && !mIsSpeedFeatureAvailable) {
            log("isSpeedFeatureAvailable():false, error occurred while getting 6 GHz SAP channel");
            return false;
        }

        mIsSpeedFeatureAvailable = true;
        log("isSpeedFeatureAvailable():true");
@@ -539,8 +523,8 @@ public class WifiHotspotRepository {
    }

    protected void purgeRefreshData() {
        mIs5gAvailable = null;
        mIs6gAvailable = null;
        mBand5g.isUsableChannelsReady = false;
        mBand6g.isUsableChannelsReady = false;
    }

    protected void startAutoRefresh() {
@@ -621,9 +605,23 @@ public class WifiHotspotRepository {
        mTetheringManager.stopTethering(TETHERING_WIFI);
    }

    @VisibleForTesting
    void updateCapabilityChanged() {
        if (mBand5g.isUsableChannelsUnsupported) {
            update5gAvailable();
            log("updateCapabilityChanged(), " + mBand5g);
        }
        if (mBand6g.isUsableChannelsUnsupported) {
            update6gAvailable();
            log("updateCapabilityChanged(), " + mBand6g);
        }
        if (mBand5g.isUsableChannelsUnsupported || mBand6g.isUsableChannelsUnsupported) {
            updateSpeedType();
        }
    }

    @VisibleForTesting
    class SoftApCallback implements WifiManager.SoftApCallback {
        private static final String TAG = "SoftApCallback";

        @Override
        public void onStateChanged(int state, int failureReason) {
@@ -642,6 +640,14 @@ public class WifiHotspotRepository {
                setRestarting(false);
            }
        }

        @Override
        public void onCapabilityChanged(@NonNull SoftApCapability softApCapability) {
            log("onCapabilityChanged(), softApCapability:" + softApCapability);
            mBand5g.hasCapability = softApCapability.getSupportedChannelList(BAND_5GHZ).length > 0;
            mBand6g.hasCapability = softApCapability.getSupportedChannelList(BAND_6GHZ).length > 0;
            updateCapabilityChanged();
        }
    }

    private class StartTetheringCallback implements TetheringManager.StartTetheringCallback {
@@ -656,6 +662,41 @@ public class WifiHotspotRepository {
        }
    }

    /**
     * Wi-Fi Hotspot SoftAp Band
     */
    @VisibleForTesting
    static class SapBand {
        public int band;
        public boolean isUsableChannelsReady;
        public boolean hasUsableChannels;
        public boolean isUsableChannelsUnsupported;
        public boolean hasCapability;

        SapBand(int band) {
            this.band = band;
        }

        /**
         * Return whether SoftAp band is available or not.
         */
        public boolean isAvailable() {
            return isUsableChannelsUnsupported ? hasCapability : hasUsableChannels;
        }

        @Override
        @NonNull
        public String toString() {
            return "SapBand{"
                    + "band:" + band
                    + ",isUsableChannelsReady:" + isUsableChannelsReady
                    + ",hasUsableChannels:" + hasUsableChannels
                    + ",isUsableChannelsUnsupported:" + isUsableChannelsUnsupported
                    + ",hasChannelsCapability:" + hasCapability
                    + '}';
        }
    }

    private void log(String msg) {
        FeatureFactory.getFeatureFactory().getWifiFeatureProvider().verboseLog(TAG, msg);
    }
+86 −50
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -72,7 +73,6 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

import java.util.Arrays;
import java.util.List;

@RunWith(AndroidJUnit4.class)
public class WifiHotspotRepositoryTest {
@@ -107,13 +107,23 @@ public class WifiHotspotRepositoryTest {
    public void setUp() {
        doReturn(new TestHandler()).when(mContext).getMainThreadHandler();
        doReturn(SPEED_6GHZ).when(mSpeedType).getValue();
        doReturn(true).when(mWifiManager).is5GHzBandSupported();
        doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP))).when(mWifiManager)
                .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
        doReturn(true).when(mWifiManager).is6GHzBandSupported();
        doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_6GHZ, OP_MODE_SAP))).when(mWifiManager)
                .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);

        mRepository = new WifiHotspotRepository(mContext, mWifiManager, mTetheringManager);
        mRepository.mSecurityType = mSecurityType;
        mRepository.mSpeedType = mSpeedType;
        mRepository.mIsDualBand = true;
        mRepository.mIs5gAvailable = true;
        mRepository.mIs6gAvailable = true;
        mRepository.mBand5g.isUsableChannelsReady = true;
        mRepository.mBand5g.isUsableChannelsUnsupported = false;
        mRepository.mBand5g.hasUsableChannels = true;
        mRepository.mBand6g.isUsableChannelsReady = true;
        mRepository.mBand6g.isUsableChannelsUnsupported = false;
        mRepository.mBand6g.hasUsableChannels = true;
    }

    @Test
@@ -372,7 +382,7 @@ public class WifiHotspotRepositoryTest {
    @Test
    public void updateSpeedType_singleBand5gPreferredBut5gUnavailable_get2gSpeedType() {
        mRepository.mIsDualBand = false;
        mRepository.mIs5gAvailable = false;
        mRepository.mBand5g.hasUsableChannels = false;
        SoftApConfiguration config = new SoftApConfiguration.Builder()
                .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
@@ -397,7 +407,7 @@ public class WifiHotspotRepositoryTest {
    @Test
    public void updateSpeedType_singleBand6gPreferredBut6gUnavailable_get5gSpeedType() {
        mRepository.mIsDualBand = false;
        mRepository.mIs6gAvailable = false;
        mRepository.mBand6g.hasUsableChannels = false;
        SoftApConfiguration config = new SoftApConfiguration.Builder()
                .setBand(WIFI_6GHZ_BAND_PREFERRED).build();
        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
@@ -410,8 +420,8 @@ public class WifiHotspotRepositoryTest {
    @Test
    public void updateSpeedType_singleBand6gPreferredBut5gAnd6gUnavailable_get2gSpeedType() {
        mRepository.mIsDualBand = false;
        mRepository.mIs5gAvailable = false;
        mRepository.mIs6gAvailable = false;
        mRepository.mBand5g.hasUsableChannels = false;
        mRepository.mBand6g.hasUsableChannels = false;
        SoftApConfiguration config = new SoftApConfiguration.Builder()
                .setBand(WIFI_6GHZ_BAND_PREFERRED).build();
        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
@@ -436,7 +446,7 @@ public class WifiHotspotRepositoryTest {
    @Test
    public void updateSpeedType_dualBand2gAnd5gBut5gUnavailable_get2gSpeedType() {
        mRepository.mIsDualBand = true;
        mRepository.mIs5gAvailable = false;
        mRepository.mBand5g.hasUsableChannels = false;
        SoftApConfiguration config = new SoftApConfiguration.Builder()
                .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
@@ -552,12 +562,8 @@ public class WifiHotspotRepositoryTest {
    @Test
    public void is5gAvailable_hasUsableChannels_returnTrue() {
        mRepository.mIs5gBandSupported = true;
        // Reset mIs5gAvailable to trigger an update
        mRepository.mIs5gAvailable = null;
        List<WifiAvailableChannel> channels =
                Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP));
        when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP))
                .thenReturn(channels);
        // Reset m5gBand to trigger an update
        mRepository.mBand5g.isUsableChannelsReady = false;

        assertThat(mRepository.is5gAvailable()).isTrue();
    }
@@ -565,8 +571,8 @@ public class WifiHotspotRepositoryTest {
    @Test
    public void is5gAvailable_noUsableChannels_returnFalse() {
        mRepository.mIs5gBandSupported = true;
        // Reset mIs5gAvailable to trigger an update
        mRepository.mIs5gAvailable = null;
        // Reset m5gBand to trigger an update
        mRepository.mBand5g.isUsableChannelsReady = false;
        when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP))
                .thenReturn(null);

@@ -576,8 +582,8 @@ public class WifiHotspotRepositoryTest {
    @Test
    @UiThreadTest
    public void get5gAvailable_shouldNotReturnNull() {
        // Reset m5gAvailable to trigger an update
        mRepository.m5gAvailable = null;
        // Reset m5gBand to trigger an update
        mRepository.mBand5g.isUsableChannelsReady = false;

        assertThat(mRepository.get5gAvailable()).isNotNull();
    }
@@ -600,12 +606,8 @@ public class WifiHotspotRepositoryTest {
    @Test
    public void is6gAvailable_hasUsableChannels_returnTrue() {
        mRepository.mIs6gBandSupported = true;
        // Reset mIs6gAvailable to trigger an update
        mRepository.mIs6gAvailable = null;
        List<WifiAvailableChannel> channels =
                Arrays.asList(new WifiAvailableChannel(FREQ_6GHZ, OP_MODE_SAP));
        when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP))
                .thenReturn(channels);
        // Reset m6gBand to trigger an update
        mRepository.mBand6g.isUsableChannelsReady = false;

        assertThat(mRepository.is6gAvailable()).isTrue();
    }
@@ -613,8 +615,8 @@ public class WifiHotspotRepositoryTest {
    @Test
    public void is6gAvailable_noUsableChannels_returnFalse() {
        mRepository.mIs6gBandSupported = true;
        // Reset mIs6gAvailable to trigger an update
        mRepository.mIs6gAvailable = null;
        // Reset m6gBand to trigger an update
        mRepository.mBand6g.isUsableChannelsReady = false;
        when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP))
                .thenReturn(null);

@@ -646,47 +648,41 @@ public class WifiHotspotRepositoryTest {
    }

    @Test
    public void isSpeedFeatureAvailable_throwExceptionWhenGet5gSapChannel_returnFalse() {
    public void isSpeedFeatureAvailable_conditionsAreReady_returnTrue() {
        mRepository.mIsConfigShowSpeed = true;
        mRepository.mIs5gBandSupported = true;
        doThrow(IllegalArgumentException.class).when(mWifiManager)
                .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);

        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();

        doThrow(UnsupportedOperationException.class).when(mWifiManager)
                .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);

        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
        assertThat(mRepository.isSpeedFeatureAvailable()).isTrue();
    }

    @Test
    public void isSpeedFeatureAvailable_throwExceptionWhenGet6gSapChannel_returnFalse() {
        mRepository.mIsConfigShowSpeed = true;
        mRepository.mIs5gBandSupported = true;
        doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP))).when(mWifiManager)
                .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
    public void isChannelAvailable_throwIllegalArgumentException_hasUsableChannelsFalse() {
        doThrow(IllegalArgumentException.class).when(mWifiManager)
                .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);

        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
        mRepository.isChannelAvailable(mRepository.mBand6g);

        assertThat(mRepository.mBand6g.hasUsableChannels).isFalse();
        assertThat(mRepository.mBand6g.isUsableChannelsUnsupported).isTrue();
    }

    @Test
    public void isChannelAvailable_throwUnsupportedOperationException_hasUsableChannelsFalse() {
        doThrow(UnsupportedOperationException.class).when(mWifiManager)
                .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);

        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
        mRepository.isChannelAvailable(mRepository.mBand6g);

        assertThat(mRepository.mBand6g.hasUsableChannels).isFalse();
        assertThat(mRepository.mBand6g.isUsableChannelsUnsupported).isTrue();
    }

    @Test
    public void isSpeedFeatureAvailable_conditionsAreReady_returnTrue() {
        mRepository.mIsConfigShowSpeed = true;
        mRepository.mIs5gBandSupported = true;
        doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP))).when(mWifiManager)
                .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
        doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_6GHZ, OP_MODE_SAP))).when(mWifiManager)
                .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
    public void isChannelAvailable_noExceptionAndHasUsableChannels_hasUsableChannelsTrue() {
        mRepository.isChannelAvailable(mRepository.mBand6g);

        assertThat(mRepository.isSpeedFeatureAvailable()).isTrue();
        assertThat(mRepository.mBand6g.hasUsableChannels).isTrue();
        assertThat(mRepository.mBand6g.isUsableChannelsUnsupported).isFalse();
    }

    @Test
@@ -745,6 +741,46 @@ public class WifiHotspotRepositoryTest {
        assertThat(mRepository.mIsRestarting).isFalse();
    }

    @Test
    public void updateCapabilityChanged_band5gUsableChannelsUnsupported_update5gAvailable() {
        mRepository = spy(new WifiHotspotRepository(mContext, mWifiManager, mTetheringManager));
        mRepository.mBand5g.isUsableChannelsUnsupported = true;

        mRepository.updateCapabilityChanged();

        verify(mRepository).update5gAvailable();
        verify(mRepository).updateSpeedType();
    }

    @Test
    public void updateCapabilityChanged_band6gUsableChannelsUnsupported_update5gAvailable() {
        mRepository = spy(new WifiHotspotRepository(mContext, mWifiManager, mTetheringManager));
        mRepository.mBand6g.isUsableChannelsUnsupported = true;

        mRepository.updateCapabilityChanged();

        verify(mRepository).update6gAvailable();
        verify(mRepository).updateSpeedType();
    }

    @Test
    public void isAvailable_isUsableChannelsUnsupportedFalse_returnHasUsableChannels() {
        mRepository.mBand6g.isUsableChannelsUnsupported = false;
        mRepository.mBand6g.hasUsableChannels = false;
        mRepository.mBand6g.hasCapability = true;

        assertThat(mRepository.mBand6g.isAvailable()).isFalse();
    }

    @Test
    public void isAvailable_isUsableChannelsUnsupportedTrue_returnHasCapability() {
        mRepository.mBand6g.isUsableChannelsUnsupported = true;
        mRepository.mBand6g.hasUsableChannels = false;
        mRepository.mBand6g.hasCapability = true;

        assertThat(mRepository.mBand6g.isAvailable()).isTrue();
    }

    private void mockConfigSecurityType(int securityType) {
        mockConfig(securityType, SPEED_2GHZ);
    }