Merge "Refer the SoftApCapability cache if getUsableChannels is unsupported" into main

This commit is contained in:
Treehugger Robot
2024-05-28 06:37:06 +00:00
committed by Android (Google) Code Review
2 changed files with 184 additions and 107 deletions

View File

@@ -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);
}

View File

@@ -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);
@@ -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);
}