Show restricted message in Wi-Fi hotspot settings

- Remove Wi-Fi hotspot preferences in settings search if Wi-Fi hotspot is disallowed

- See the result screenshot in b/203168953#comment12

Bug: 203168953
Test: manual test
make RunSettingsRoboTests ROBOTEST_FILTER=WifiTetherSettingsTest

Change-Id: Id4416fd0659b596e4e6f31890a139198219f4552
This commit is contained in:
Weng Su
2022-05-03 02:31:39 +08:00
parent 27aa5f9d94
commit e37a553e94
2 changed files with 198 additions and 109 deletions

View File

@@ -30,6 +30,7 @@ import android.os.UserManager;
import android.util.FeatureFlagUtils; import android.util.FeatureFlagUtils;
import android.util.Log; import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.settings.R; import com.android.settings.R;
@@ -41,6 +42,7 @@ import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settingslib.TetherUtil; import com.android.settingslib.TetherUtil;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -56,6 +58,8 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
@VisibleForTesting @VisibleForTesting
static final String KEY_WIFI_TETHER_NETWORK_NAME = "wifi_tether_network_name"; static final String KEY_WIFI_TETHER_NETWORK_NAME = "wifi_tether_network_name";
@VisibleForTesting @VisibleForTesting
static final String KEY_WIFI_TETHER_SECURITY = "wifi_tether_security";
@VisibleForTesting
static final String KEY_WIFI_TETHER_NETWORK_PASSWORD = "wifi_tether_network_password"; static final String KEY_WIFI_TETHER_NETWORK_PASSWORD = "wifi_tether_network_password";
@VisibleForTesting @VisibleForTesting
static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off"; static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off";
@@ -72,7 +76,7 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
private WifiManager mWifiManager; private WifiManager mWifiManager;
private boolean mRestartWifiApAfterConfigChange; private boolean mRestartWifiApAfterConfigChange;
private boolean mUnavailable; private boolean mUnavailable;
private WifiRestriction mWifiRestriction;
@VisibleForTesting @VisibleForTesting
TetherChangeReceiver mTetherChangeReceiver; TetherChangeReceiver mTetherChangeReceiver;
@@ -82,6 +86,12 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
public WifiTetherSettings() { public WifiTetherSettings() {
super(UserManager.DISALLOW_CONFIG_TETHERING); super(UserManager.DISALLOW_CONFIG_TETHERING);
mWifiRestriction = new WifiRestriction();
}
public WifiTetherSettings(WifiRestriction wifiRestriction) {
super(UserManager.DISALLOW_CONFIG_TETHERING);
mWifiRestriction = wifiRestriction;
} }
@Override @Override
@@ -98,9 +108,7 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
setIfOnlyAvailableForAdmins(true); setIfOnlyAvailableForAdmins(true);
if (isUiRestricted()) { mUnavailable = isUiRestricted() || !mWifiRestriction.isHotspotAvailable(getContext());
mUnavailable = true;
}
} }
@Override @Override
@@ -135,6 +143,11 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
if (!mWifiRestriction.isHotspotAvailable(getContext())) {
getEmptyTextView().setText(R.string.not_allowed_by_ent);
getPreferenceScreen().removeAll();
return;
}
if (mUnavailable) { if (mUnavailable) {
if (!isUiRestrictedByOnlyAdmin()) { if (!isUiRestrictedByOnlyAdmin()) {
getEmptyTextView().setText(R.string.tethering_settings_not_available); getEmptyTextView().setText(R.string.tethering_settings_not_available);
@@ -228,15 +241,33 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
use(WifiTetherMaximizeCompatibilityPreferenceController.class).updateDisplay(); use(WifiTetherMaximizeCompatibilityPreferenceController.class).updateDisplay();
} }
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.wifi_tether_settings) { new SearchIndexProvider(R.xml.wifi_tether_settings);
@VisibleForTesting
static class SearchIndexProvider extends BaseSearchIndexProvider {
private final WifiRestriction mWifiRestriction;
SearchIndexProvider(int xmlRes) {
super(xmlRes);
mWifiRestriction = new WifiRestriction();
}
@VisibleForTesting
SearchIndexProvider(int xmlRes, WifiRestriction wifiRestriction) {
super(xmlRes);
mWifiRestriction = wifiRestriction;
}
@Override @Override
public List<String> getNonIndexableKeys(Context context) { public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context); final List<String> keys = super.getNonIndexableKeys(context);
if (!TetherUtil.isTetherAvailable(context)) { if (!mWifiRestriction.isTetherAvailable(context)
|| !mWifiRestriction.isHotspotAvailable(context)) {
keys.add(KEY_WIFI_TETHER_NETWORK_NAME); keys.add(KEY_WIFI_TETHER_NETWORK_NAME);
keys.add(KEY_WIFI_TETHER_SECURITY);
keys.add(KEY_WIFI_TETHER_NETWORK_PASSWORD); keys.add(KEY_WIFI_TETHER_NETWORK_PASSWORD);
keys.add(KEY_WIFI_TETHER_AUTO_OFF); keys.add(KEY_WIFI_TETHER_AUTO_OFF);
keys.add(KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY); keys.add(KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
@@ -257,7 +288,20 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
Context context) { Context context) {
return buildPreferenceControllers(context, null /* listener */); return buildPreferenceControllers(context, null /* listener */);
} }
}; }
@VisibleForTesting
static class WifiRestriction {
public boolean isTetherAvailable(@Nullable Context context) {
if (context == null) return true;
return TetherUtil.isTetherAvailable(context);
}
public boolean isHotspotAvailable(@Nullable Context context) {
if (context == null) return true;
return WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(context);
}
}
@VisibleForTesting @VisibleForTesting
class TetherChangeReceiver extends BroadcastReceiver { class TetherChangeReceiver extends BroadcastReceiver {

View File

@@ -19,6 +19,7 @@ package com.android.settings.wifi.tether;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
@@ -33,38 +34,41 @@ import android.net.ConnectivityManager;
import android.net.TetheringManager; import android.net.TetheringManager;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.util.FeatureFlagUtils;
import android.widget.TextView; import android.widget.TextView;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.core.FeatureFlags; import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowFragment; import com.android.settings.testutils.shadow.ShadowFragment;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class WifiTetherSettingsTest { public class WifiTetherSettingsTest {
private static final int XML_RES = R.xml.wifi_tether_settings;
private static final String[] WIFI_REGEXS = {"wifi_regexs"}; private static final String[] WIFI_REGEXS = {"wifi_regexs"};
private Context mContext; @Rule
private WifiTetherSettings mWifiTetherSettings; public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Spy
Context mContext = ApplicationProvider.getApplicationContext();
@Mock @Mock
private WifiManager mWifiManager; private WifiManager mWifiManager;
@Mock @Mock
@@ -73,81 +77,55 @@ public class WifiTetherSettingsTest {
private UserManager mUserManager; private UserManager mUserManager;
@Mock @Mock
private TetheringManager mTetheringManager; private TetheringManager mTetheringManager;
@Mock
private WifiTetherSettings.WifiRestriction mWifiRestriction;
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock
private TextView mEmptyTextView;
private WifiTetherSettings mWifiTetherSettings;
@Before @Before
public void setUp() { public void setUp() {
mContext = spy(RuntimeEnvironment.application);
MockitoAnnotations.initMocks(this);
doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class); doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
doReturn(mConnectivityManager) doReturn(mConnectivityManager)
.when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE); .when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
doReturn(mTetheringManager).when(mContext).getSystemService(Context.TETHERING_SERVICE); doReturn(mTetheringManager).when(mContext).getSystemService(Context.TETHERING_SERVICE);
doReturn(WIFI_REGEXS).when(mTetheringManager).getTetherableWifiRegexs(); doReturn(WIFI_REGEXS).when(mTetheringManager).getTetherableWifiRegexs();
doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE); doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
mWifiTetherSettings = new WifiTetherSettings(); mWifiTetherSettings = new WifiTetherSettings(mWifiRestriction);
}
@Test
public void wifiTetherNonIndexableKeys_tetherAvailable_keysNotReturned() {
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE, false);
// To let TetherUtil.isTetherAvailable return true, select one of the combinations
setupIsTetherAvailable(true);
final List<String> niks =
WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
assertThat(niks).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(niks).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(niks).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(niks).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
}
@Test
public void wifiTetherNonIndexableKeys_tetherNotAvailable_keysReturned() {
// To let TetherUtil.isTetherAvailable return false, select one of the combinations
setupIsTetherAvailable(false);
final List<String> niks =
WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
assertThat(niks).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(niks).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(niks).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(niks).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
}
@Test
public void createPreferenceControllers_notEmpty() {
assertThat(WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getPreferenceControllers(mContext))
.isNotEmpty();
} }
@Test @Test
@Config(shadows = ShadowFragment.class) @Config(shadows = ShadowFragment.class)
public void startFragment_notAdminUser_shouldRemoveAllPreferences() { public void onStart_uiIsRestricted_removeAllPreferences() {
final WifiTetherSettings settings = spy(new WifiTetherSettings()); spyWifiTetherSettings();
final FragmentActivity activity = mock(FragmentActivity.class);
when(settings.getActivity()).thenReturn(activity);
when(settings.getContext()).thenReturn(mContext);
final Resources.Theme theme = mContext.getTheme();
when(activity.getTheme()).thenReturn(theme);
when(activity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
doNothing().when(settings)
.onCreatePreferences(any(Bundle.class), nullable(String.class));
final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
ReflectionHelpers.setField(settings, "mDashboardFeatureProvider",
fakeFeatureFactory.dashboardFeatureProvider);
final TextView emptyTextView = mock(TextView.class);
ReflectionHelpers.setField(settings, "mEmptyTextView", emptyTextView);
final PreferenceScreen screen = mock(PreferenceScreen.class);
doReturn(screen).when(settings).getPreferenceScreen();
settings.onCreate(Bundle.EMPTY);
settings.onStart(); mWifiTetherSettings.onStart();
verify(screen).removeAll(); verify(mPreferenceScreen).removeAll();
}
@Test
@Config(shadows = ShadowFragment.class)
public void onStart_hotspotNotAvailable_removeAllPreferences() {
spyWifiTetherSettings();
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(false);
mWifiTetherSettings.onStart();
verify(mPreferenceScreen).removeAll();
verify(mEmptyTextView).setText(anyInt());
}
@Test
public void createPreferenceControllers_getPreferenceControllersNotEmpty() {
assertThat(WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getPreferenceControllers(mContext))
.isNotEmpty();
} }
@Test @Test
@@ -159,19 +137,86 @@ public class WifiTetherSettingsTest {
.isEqualTo(1); .isEqualTo(1);
} }
private void setupIsTetherAvailable(boolean returnValue) { @Test
when(mConnectivityManager.isTetheringSupported()).thenReturn(true); public void getNonIndexableKeys_tetherAvailable_keysNotReturned() {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction);
// For RestrictedLockUtils.checkIfRestrictionEnforced final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
final int userId = UserHandle.myUserId();
List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
when(mUserManager.getUserRestrictionSources(
UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId)))
.thenReturn(enforcingUsers);
// For RestrictedLockUtils.hasBaseUserRestriction assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
when(mUserManager.hasBaseUserRestriction( assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId))) assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
.thenReturn(!returnValue); assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
}
@Test
public void getNonIndexableKeys_tetherNotAvailable_keysReturned() {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(false);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
}
@Test
public void getNonIndexableKeys_hotspotNotAvailable_keysReturned() {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(false);
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
}
@Test
public void getNonIndexableKeys_tetherAndHotspotNotAvailable_keysReturned() {
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(false);
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(false);
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction);
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
}
private void spyWifiTetherSettings() {
mWifiTetherSettings = spy(new WifiTetherSettings(mWifiRestriction));
final FragmentActivity activity = mock(FragmentActivity.class);
when(mWifiTetherSettings.getActivity()).thenReturn(activity);
when(mWifiTetherSettings.getContext()).thenReturn(mContext);
final Resources.Theme theme = mContext.getTheme();
when(activity.getTheme()).thenReturn(theme);
when(activity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
doNothing().when(mWifiTetherSettings)
.onCreatePreferences(any(Bundle.class), nullable(String.class));
final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
ReflectionHelpers.setField(mWifiTetherSettings, "mDashboardFeatureProvider",
fakeFeatureFactory.dashboardFeatureProvider);
ReflectionHelpers.setField(mWifiTetherSettings, "mEmptyTextView", mEmptyTextView);
doReturn(mPreferenceScreen).when(mWifiTetherSettings).getPreferenceScreen();
mWifiTetherSettings.onCreate(Bundle.EMPTY);
} }
} }