From d3358d8a6f86d37852387acfc0751908eb43c56c Mon Sep 17 00:00:00 2001 From: Chilun Date: Mon, 26 Mar 2018 18:28:56 +0800 Subject: [PATCH] Add index for Hotspot settings page into search Added index provider into TetherSettings and WifiTetherSettings pages. Added robotests to check the keys returned by getNonIndexableKeys. Move repeated code into utility class. Bug: 74777873 Test: make -j RunSettingsRoboTests Test: atest UniquePreferenceTest Change-Id: I6cb09d735afa4867d25a79de733ce8c59634e49b --- res/xml/tether_prefs.xml | 7 +- res/xml/wifi_tether_settings.xml | 3 +- src/com/android/settings/TetherSettings.java | 64 +++++++- .../network/TetherPreferenceController.java | 8 +- .../wifi/tether/WifiTetherSettings.java | 45 +++++- ...randfather_not_implementing_index_provider | 1 - .../android/settings/TetherSettingsTest.java | 150 ++++++++++++++++++ .../wifi/tether/WifiTetherSettingsTest.java | 106 +++++++++++++ 8 files changed, 365 insertions(+), 19 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/TetherSettingsTest.java create mode 100644 tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java diff --git a/res/xml/tether_prefs.xml b/res/xml/tether_prefs.xml index 2a841d71608..70a57d7c98a 100644 --- a/res/xml/tether_prefs.xml +++ b/res/xml/tether_prefs.xml @@ -17,6 +17,7 @@ + android:summary="@string/usb_tethering_subtext" + settings:keywords="@string/keywords_hotspot_tethering" /> + android:summary="@string/bluetooth_tethering_subtext" + settings:keywords="@string/keywords_hotspot_tethering" /> @@ -43,4 +44,4 @@ android:dialogTitle="@string/wifi_hotspot_ap_band_title" android:negativeButtonText="@string/cancel" android:positiveButtonText="@string/apply"/> - \ No newline at end of file + diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index 8cb8efc27df..848e1765699 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -34,27 +34,41 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.UserManager; -import androidx.preference.SwitchPreference; +import android.provider.SearchIndexableResource; +import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; +import androidx.preference.SwitchPreference; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.datausage.DataSaverBackend; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable; import com.android.settings.wifi.tether.WifiTetherPreferenceController; import com.android.settingslib.TetherUtil; +import com.android.settingslib.search.SearchIndexable; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.atomic.AtomicReference; /* * Displays preferences for Tethering. */ +@SearchIndexable public class TetherSettings extends RestrictedSettingsFragment implements DataSaverBackend.Listener { - private static final String USB_TETHER_SETTINGS = "usb_tether_settings"; - private static final String ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering"; - private static final String DATA_SAVER_FOOTER = "disabled_on_data_saver"; + @VisibleForTesting + static final String KEY_TETHER_PREFS_SCREEN = "tether_prefs_screen"; + @VisibleForTesting + static final String KEY_WIFI_TETHER = "wifi_tether"; + @VisibleForTesting + static final String KEY_USB_TETHER_SETTINGS = "usb_tether_settings"; + @VisibleForTesting + static final String KEY_ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering"; + private static final String KEY_DATA_SAVER_FOOTER = "disabled_on_data_saver"; private static final String TAG = "TetheringSettings"; @@ -110,7 +124,7 @@ public class TetherSettings extends RestrictedSettingsFragment mDataSaverBackend = new DataSaverBackend(getContext()); mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled(); - mDataSaverFooter = findPreference(DATA_SAVER_FOOTER); + mDataSaverFooter = findPreference(KEY_DATA_SAVER_FOOTER); setIfOnlyAvailableForAdmins(true); if (isUiRestricted()) { @@ -126,8 +140,8 @@ public class TetherSettings extends RestrictedSettingsFragment BluetoothProfile.PAN); } - mUsbTether = (SwitchPreference) findPreference(USB_TETHER_SETTINGS); - mBluetoothTether = (SwitchPreference) findPreference(ENABLE_BLUETOOTH_TETHERING); + mUsbTether = (SwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS); + mBluetoothTether = (SwitchPreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING); mDataSaverBackend.addListener(this); @@ -433,6 +447,42 @@ public class TetherSettings extends RestrictedSettingsFragment } }; + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List getXmlResourcesToIndex( + Context context, boolean enabled) { + final SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.tether_prefs; + return Arrays.asList(sir); + } + + @Override + public List getNonIndexableKeys(Context context) { + final List keys = super.getNonIndexableKeys(context); + final ConnectivityManager cm = + context.getSystemService(ConnectivityManager.class); + + if (!TetherUtil.isTetherAvailable(context)) { + keys.add(KEY_TETHER_PREFS_SCREEN); + keys.add(KEY_WIFI_TETHER); + } + + final boolean usbAvailable = + cm.getTetherableUsbRegexs().length != 0; + if (!usbAvailable || Utils.isMonkeyRunning()) { + keys.add(KEY_USB_TETHER_SETTINGS); + } + + final boolean bluetoothAvailable = + cm.getTetherableBluetoothRegexs().length != 0; + if (!bluetoothAvailable) { + keys.add(KEY_ENABLE_BLUETOOTH_TETHERING); + } + return keys; + } + }; + private static final class OnStartTetheringCallback extends ConnectivityManager.OnStartTetheringCallback { final WeakReference mTetherSettings; diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java index 636fe0cee07..3ab83cda0b5 100644 --- a/src/com/android/settings/network/TetherPreferenceController.java +++ b/src/com/android/settings/network/TetherPreferenceController.java @@ -17,7 +17,6 @@ package com.android.settings.network; import static android.os.UserManager.DISALLOW_CONFIG_TETHERING; import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced; -import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothPan; @@ -40,6 +39,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.TetherSettings; import com.android.settings.core.PreferenceControllerMixin; +import com.android.settingslib.TetherUtil; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; @@ -112,11 +112,7 @@ public class TetherPreferenceController extends AbstractPreferenceController imp @Override public boolean isAvailable() { - final boolean isBlocked = - (!mConnectivityManager.isTetheringSupported() && !mAdminDisallowedTetherConfig) - || hasBaseUserRestriction(mContext, DISALLOW_CONFIG_TETHERING, - UserHandle.myUserId()); - return !isBlocked; + return TetherUtil.isTetherAvailable(mContext); } @Override diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java index 7c50f0c2cdb..5e202d63471 100644 --- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java +++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java @@ -27,28 +27,42 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.UserManager; -import androidx.annotation.VisibleForTesting; +import android.provider.SearchIndexableResource; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.dashboard.RestrictedDashboardFragment; +import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.widget.SwitchBar; import com.android.settings.widget.SwitchBarController; +import com.android.settingslib.TetherUtil; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.search.SearchIndexable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.UUID; +@SearchIndexable public class WifiTetherSettings extends RestrictedDashboardFragment implements WifiTetherBasePreferenceController.OnTetherConfigUpdateListener { private static final String TAG = "WifiTetherSettings"; private static final IntentFilter TETHER_STATE_CHANGE_FILTER; - private static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off"; + private static final String KEY_WIFI_TETHER_SCREEN = "wifi_tether_settings_screen"; + @VisibleForTesting + static final String KEY_WIFI_TETHER_NETWORK_NAME = "wifi_tether_network_name"; + @VisibleForTesting + static final String KEY_WIFI_TETHER_NETWORK_PASSWORD = "wifi_tether_network_password"; + @VisibleForTesting + static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off"; + @VisibleForTesting + static final String KEY_WIFI_TETHER_NETWORK_AP_BAND = "wifi_tether_network_ap_band"; private WifiTetherSwitchBarController mSwitchBarController; private WifiTetherSSIDPreferenceController mSSIDPreferenceController; @@ -182,6 +196,33 @@ public class WifiTetherSettings extends RestrictedDashboardFragment .updateDisplay(); } + public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List getXmlResourcesToIndex( + Context context, boolean enabled) { + final SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.wifi_tether_settings; + return Arrays.asList(sir); + } + + @Override + public List getNonIndexableKeys(Context context) { + final List keys = super.getNonIndexableKeys(context); + + if (!TetherUtil.isTetherAvailable(context)) { + keys.add(KEY_WIFI_TETHER_NETWORK_NAME); + keys.add(KEY_WIFI_TETHER_NETWORK_PASSWORD); + keys.add(KEY_WIFI_TETHER_AUTO_OFF); + keys.add(KEY_WIFI_TETHER_NETWORK_AP_BAND); + } + + // Remove duplicate + keys.add(KEY_WIFI_TETHER_SCREEN); + return keys; + } + }; + @VisibleForTesting class TetherChangeReceiver extends BroadcastReceiver { @Override diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider index 8bd4f823840..31e3a54ee26 100644 --- a/tests/robotests/assets/grandfather_not_implementing_index_provider +++ b/tests/robotests/assets/grandfather_not_implementing_index_provider @@ -21,7 +21,6 @@ com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionMi com.android.settings.enterprise.ApplicationListFragment$EnterpriseInstalledPackages com.android.settings.enterprise.EnterpriseSetDefaultAppsListFragment com.android.settings.inputmethod.KeyboardLayoutPickerFragment -com.android.settings.wifi.tether.WifiTetherSettings com.android.settings.wifi.SavedAccessPointsWifiSettings com.android.settings.notification.ZenModeEventRuleSettings com.android.settings.notification.ZenModeScheduleRuleSettings diff --git a/tests/robotests/src/com/android/settings/TetherSettingsTest.java b/tests/robotests/src/com/android/settings/TetherSettingsTest.java new file mode 100644 index 00000000000..1ccd958cfb3 --- /dev/null +++ b/tests/robotests/src/com/android/settings/TetherSettingsTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; +import android.net.ConnectivityManager; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +public class TetherSettingsTest { + + private Context mContext; + + @Mock + private ConnectivityManager mConnectivityManager; + @Mock + private UserManager mUserManager; + + @Before + public void setUp() { + mContext = spy(RuntimeEnvironment.application); + + MockitoAnnotations.initMocks(this); + doReturn(mConnectivityManager) + .when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE); + doReturn(mUserManager) + .when(mContext).getSystemService(Context.USER_SERVICE); + + setupIsTetherAvailable(true); + + when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(new String[]{}); + when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{}); + } + + @Test + public void testTetherNonIndexableKeys_tetherAvailable_keysNotReturned() { + // To let TetherUtil.isTetherAvailable return true, select one of the combinations + setupIsTetherAvailable(true); + + final List niks = + TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); + + assertThat(niks).doesNotContain(TetherSettings.KEY_TETHER_PREFS_SCREEN); + assertThat(niks).doesNotContain(TetherSettings.KEY_WIFI_TETHER); + } + + @Test + public void testTetherNonIndexableKeys_tetherNotAvailable_keysReturned() { + // To let TetherUtil.isTetherAvailable return false, select one of the combinations + setupIsTetherAvailable(false); + + final List niks = + TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); + + assertThat(niks).contains(TetherSettings.KEY_TETHER_PREFS_SCREEN); + assertThat(niks).contains(TetherSettings.KEY_WIFI_TETHER); + } + + @Test + public void testTetherNonIndexableKeys_usbNotAvailable_usbKeyReturned() { + when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(new String[]{}); + + final List niks = + TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); + + assertThat(niks).contains(TetherSettings.KEY_USB_TETHER_SETTINGS); + } + + @Test + public void testTetherNonIndexableKeys_usbAvailable_usbKeyNotReturned() { + // We can ignore the condition of Utils.isMonkeyRunning() + // In normal case, monkey and robotest should not execute at the same time + when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(new String[]{"dummyRegex"}); + + final List niks = + TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); + + assertThat(niks).doesNotContain(TetherSettings.KEY_USB_TETHER_SETTINGS); + } + + @Test + public void testTetherNonIndexableKeys_bluetoothNotAvailable_bluetoothKeyReturned() { + when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{}); + + final List niks = + TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); + + assertThat(niks).contains(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING); + } + + @Test + public void testTetherNonIndexableKeys_bluetoothAvailable_bluetoothKeyNotReturned() { + when(mConnectivityManager.getTetherableBluetoothRegexs()) + .thenReturn(new String[]{"dummyRegex"}); + + final List niks = + TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); + + assertThat(niks).doesNotContain(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING); + } + + private void setupIsTetherAvailable(boolean returnValue) { + when(mConnectivityManager.isTetheringSupported()).thenReturn(true); + + // For RestrictedLockUtils.checkIfRestrictionEnforced + final int userId = UserHandle.myUserId(); + List enforcingUsers = new ArrayList<>(); + when(mUserManager.getUserRestrictionSources( + UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId))) + .thenReturn(enforcingUsers); + + // For RestrictedLockUtils.hasBaseUserRestriction + when(mUserManager.hasBaseUserRestriction( + UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId))) + .thenReturn(!returnValue); + } +} diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java new file mode 100644 index 00000000000..58bb1989d98 --- /dev/null +++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.wifi.tether; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; +import android.net.ConnectivityManager; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +public class WifiTetherSettingsTest { + + private Context mContext; + + @Mock + private ConnectivityManager mConnectivityManager; + @Mock + private UserManager mUserManager; + + @Before + public void setUp() { + mContext = spy(RuntimeEnvironment.application); + + MockitoAnnotations.initMocks(this); + doReturn(mConnectivityManager) + .when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE); + doReturn(mUserManager) + .when(mContext).getSystemService(Context.USER_SERVICE); + } + + @Test + public void testWifiTetherNonIndexableKeys_tetherAvailable_keysNotReturned() { + // To let TetherUtil.isTetherAvailable return true, select one of the combinations + setupIsTetherAvailable(true); + + final List 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_NETWORK_AP_BAND); + } + + @Test + public void testWifiTetherNonIndexableKeys_tetherNotAvailable_keysReturned() { + // To let TetherUtil.isTetherAvailable return false, select one of the combinations + setupIsTetherAvailable(false); + + final List 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_NETWORK_AP_BAND); + } + + private void setupIsTetherAvailable(boolean returnValue) { + when(mConnectivityManager.isTetheringSupported()).thenReturn(true); + + // For RestrictedLockUtils.checkIfRestrictionEnforced + final int userId = UserHandle.myUserId(); + List enforcingUsers = new ArrayList<>(); + when(mUserManager.getUserRestrictionSources( + UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId))) + .thenReturn(enforcingUsers); + + // For RestrictedLockUtils.hasBaseUserRestriction + when(mUserManager.hasBaseUserRestriction( + UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId))) + .thenReturn(!returnValue); + } +}