diff --git a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java index 6140d714fab..e78773ee0e8 100644 --- a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java +++ b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java @@ -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 m5gAvailable; protected Boolean mIs6gBandSupported; - protected Boolean mIs6gAvailable; + protected SapBand mBand6g = new SapBand(WifiScanner.WIFI_BAND_6_GHZ); protected MutableLiveData 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 channels = mWifiManager.getUsableChannels(band, OP_MODE_SAP); - log("isChannelAvailable(), band:" + band + ", channels:" + channels); - return (channels != null && channels.size() > 0); + List 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); } diff --git a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java index af3b8f13ad4..20b30754fac 100644 --- a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java +++ b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java @@ -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 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 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); @@ -645,50 +647,44 @@ public class WifiHotspotRepositoryTest { assertThat(mRepository.isSpeedFeatureAvailable()).isFalse(); } - @Test - public void isSpeedFeatureAvailable_throwExceptionWhenGet5gSapChannel_returnFalse() { - 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(); - } - - @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); - doThrow(IllegalArgumentException.class).when(mWifiManager) - .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP); - - assertThat(mRepository.isSpeedFeatureAvailable()).isFalse(); - - doThrow(UnsupportedOperationException.class).when(mWifiManager) - .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP); - - assertThat(mRepository.isSpeedFeatureAvailable()).isFalse(); - } - @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); assertThat(mRepository.isSpeedFeatureAvailable()).isTrue(); } + @Test + public void isChannelAvailable_throwIllegalArgumentException_hasUsableChannelsFalse() { + doThrow(IllegalArgumentException.class).when(mWifiManager) + .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP); + + 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); + + mRepository.isChannelAvailable(mRepository.mBand6g); + + assertThat(mRepository.mBand6g.hasUsableChannels).isFalse(); + assertThat(mRepository.mBand6g.isUsableChannelsUnsupported).isTrue(); + } + + @Test + public void isChannelAvailable_noExceptionAndHasUsableChannels_hasUsableChannelsTrue() { + mRepository.isChannelAvailable(mRepository.mBand6g); + + assertThat(mRepository.mBand6g.hasUsableChannels).isTrue(); + assertThat(mRepository.mBand6g.isUsableChannelsUnsupported).isFalse(); + } + @Test @UiThreadTest public void getRestarting_shouldNotReturnNull() { @@ -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); }