Add tether preferences into AllInOneTetherSettings
These preferences are for user to toggle a specific tethering option,
like USB, BT or WIFI.
Bug: 147323306
Test: CodeInspectionTest, AllInOneTetherSettingsTest, TetherEnablerTest
Change-Id: I1229ffd2dd12b39e9c6e48dc29c6e46ce9ad7634
diff --git a/res/xml/all_tether_prefs.xml b/res/xml/all_tether_prefs.xml
index 07e5d64..bc3471b 100644
--- a/res/xml/all_tether_prefs.xml
+++ b/res/xml/all_tether_prefs.xml
@@ -53,6 +53,31 @@
android:title="@string/wifi_hotspot_ap_band_title"/>
</PreferenceCategory>
+ <PreferenceCategory
+ android:key="tethering_options_group"
+ android:title="Tethering"
+ settings:searchable="false">
+ <SwitchPreference
+ android:key="enable_usb_tethering"
+ android:title="@string/usb_tethering_button_text"
+ android:summary="@string/usb_tethering_subtext"
+ settings:controller="com.android.settings.network.UsbTetherPreferenceController"
+ settings:keywords="@string/keywords_hotspot_tethering" />
+
+ <SwitchPreference
+ android:key="enable_bluetooth_tethering_2"
+ android:title="@string/bluetooth_tether_checkbox_text"
+ android:summary="@string/bluetooth_tethering_subtext"
+ settings:controller="com.android.settings.network.BluetoothTetherPreferenceController"
+ settings:keywords="@string/keywords_hotspot_tethering" />
+
+ <SwitchPreference
+ android:key="disable_wifi_tethering"
+ android:title="Don't use Wi-Fi hotspot"
+ settings:controller="com.android.settings.network.WifiTetherDisablePreferenceController"
+ settings:keywords="@string/keywords_hotspot_tethering" />
+ </PreferenceCategory>
+
<Preference
android:key="disabled_on_data_saver_2"
android:summary="@string/tether_settings_disabled_on_data_saver"
diff --git a/src/com/android/settings/AllInOneTetherSettings.java b/src/com/android/settings/AllInOneTetherSettings.java
index 996c434..f2a0f52 100644
--- a/src/com/android/settings/AllInOneTetherSettings.java
+++ b/src/com/android/settings/AllInOneTetherSettings.java
@@ -120,22 +120,23 @@
public void onReceive(Context content, Intent intent) {
String action = intent.getAction();
if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "updating display config due to receiving broadcast action " + action);
+ Log.d(TAG,
+ "updating display config due to receiving broadcast action " + action);
}
updateDisplayWithNewConfig();
if (TextUtils.equals(action, ACTION_TETHER_STATE_CHANGED)) {
- if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED
- && mRestartWifiApAfterConfigChange) {
- mRestartWifiApAfterConfigChange = false;
- mTetherEnabler.startTethering(TETHERING_WIFI);
- }
+ restartWifiTetherIfNeed(mWifiManager.getWifiApState());
} else if (TextUtils.equals(action, WIFI_AP_STATE_CHANGED_ACTION)) {
- int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0);
- if (state == WifiManager.WIFI_AP_STATE_DISABLED
- && mRestartWifiApAfterConfigChange) {
- mRestartWifiApAfterConfigChange = false;
- mTetherEnabler.startTethering(TETHERING_WIFI);
- }
+ restartWifiTetherIfNeed(intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0));
+ }
+ }
+
+ private void restartWifiTetherIfNeed(int state) {
+ if (state == WifiManager.WIFI_AP_STATE_DISABLED
+ && mWifiTetherChosen
+ && mRestartWifiApAfterConfigChange) {
+ mRestartWifiApAfterConfigChange = false;
+ mTetherEnabler.startTethering(TETHERING_WIFI);
}
}
};
@@ -418,7 +419,7 @@
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
- return buildPreferenceControllers(context, null /* AllTetherSettings */);
+ return buildPreferenceControllers(context, null /*listener*/);
}
};
}
diff --git a/src/com/android/settings/network/TetherEnabler.java b/src/com/android/settings/network/TetherEnabler.java
index 2ea3c04..ffb0ef2 100644
--- a/src/com/android/settings/network/TetherEnabler.java
+++ b/src/com/android/settings/network/TetherEnabler.java
@@ -20,6 +20,8 @@
import static android.net.ConnectivityManager.TETHERING_USB;
import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static com.android.settings.AllInOneTetherSettings.DEDUP_POSTFIX;
+
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.content.BroadcastReceiver;
@@ -34,6 +36,7 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
@@ -50,9 +53,11 @@
* TetherEnabler is a helper to manage Tethering switch on/off state. It turns on/off
* different types of tethering based on stored values in {@link SharedPreferences} and ensures
* tethering state updated by data saver state.
+ *
+ * This class is not designed for extending. It's extendable solely for the test purpose.
*/
-public final class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListener,
+public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListener,
DataSaverBackend.Listener, LifecycleObserver,
SharedPreferences.OnSharedPreferenceChangeListener {
@@ -63,12 +68,9 @@
// This KEY is used for a shared preference value, not for any displayed preferences.
public static final String KEY_ENABLE_WIFI_TETHERING = "enable_wifi_tethering";
- @VisibleForTesting
- static final String WIFI_TETHER_DISABLE_KEY = "disable_wifi_tethering";
- @VisibleForTesting
- static final String USB_TETHER_KEY = "enable_usb_tethering";
- @VisibleForTesting
- static final String BLUETOOTH_TETHER_KEY = "enable_bluetooth_tethering";
+ public static final String WIFI_TETHER_DISABLE_KEY = "disable_wifi_tethering";
+ public static final String USB_TETHER_KEY = "enable_usb_tethering";
+ public static final String BLUETOOTH_TETHER_KEY = "enable_bluetooth_tethering" + DEDUP_POSTFIX;
private final SwitchWidgetController mSwitchWidgetController;
private final WifiManager mWifiManager;
@@ -113,7 +115,7 @@
mContext.registerReceiver(mTetherChangeReceiver, filter);
mOnStartTetheringCallback = new OnStartTetheringCallback(this);
- updateState();
+ updateState(null/*tethered*/);
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@@ -133,14 +135,20 @@
mContext.unregisterReceiver(mTetherChangeReceiver);
}
- private void updateState() {
- mSwitchWidgetController.setChecked(isTethering());
+ @VisibleForTesting
+ void updateState(@Nullable String[] tethered) {
+ boolean isTethering = tethered == null ? isTethering() : isTethering(tethered);
+ if (DEBUG) {
+ Log.d(TAG, "updateState: " + isTethering);
+ }
+ setSwitchCheckedInternal(isTethering);
mSwitchWidgetController.setEnabled(!mDataSaverEnabled);
}
- private void updateState(String[] tethered) {
- mSwitchWidgetController.setChecked(isTethering(tethered));
- mSwitchWidgetController.setEnabled(!mDataSaverEnabled);
+ private void setSwitchCheckedInternal(boolean checked) {
+ mSwitchWidgetController.stopListening();
+ mSwitchWidgetController.setChecked(checked);
+ mSwitchWidgetController.startListening();
}
private boolean isTethering() {
@@ -269,7 +277,7 @@
if (active != null) {
updateState(active.toArray(new String[0]));
} else {
- updateState();
+ updateState(null/*tethered*/);
}
}
}
@@ -371,7 +379,7 @@
private void update() {
TetherEnabler enabler = mTetherEnabler.get();
if (enabler != null) {
- enabler.updateState();
+ enabler.updateState(null/*tethered*/);
}
}
}
diff --git a/src/com/android/settings/network/WifiTetherDisablePreferenceController.java b/src/com/android/settings/network/WifiTetherDisablePreferenceController.java
index ddc2bf7..a7242cf 100644
--- a/src/com/android/settings/network/WifiTetherDisablePreferenceController.java
+++ b/src/com/android/settings/network/WifiTetherDisablePreferenceController.java
@@ -31,6 +31,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.TetherUtil;
/**
* This controller helps to manage the switch state and visibility of wifi tether disable switch
@@ -84,7 +85,8 @@
@Override
public int getAvailabilityStatus() {
final String[] wifiRegexs = mCm.getTetherableWifiRegexs();
- if (wifiRegexs == null || wifiRegexs.length == 0 || !shouldShow()) {
+ if (wifiRegexs == null || wifiRegexs.length == 0 || !shouldShow()
+ || !TetherUtil.isTetherAvailable(mContext)) {
return CONDITIONALLY_UNAVAILABLE;
} else {
return AVAILABLE;
diff --git a/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java b/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
index 61db0e5..55486d2 100644
--- a/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
@@ -16,9 +16,14 @@
package com.android.settings;
+import static com.android.settings.network.TetherEnabler.BLUETOOTH_TETHER_KEY;
+import static com.android.settings.network.TetherEnabler.USB_TETHER_KEY;
+import static com.android.settings.network.TetherEnabler.WIFI_TETHER_DISABLE_KEY;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -31,6 +36,7 @@
import com.android.settings.core.FeatureFlags;
import com.android.settings.testutils.shadow.ShadowWifiManager;
import com.android.settings.wifi.tether.WifiTetherAutoOffPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
@@ -40,6 +46,7 @@
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@@ -48,6 +55,8 @@
@Config(shadows = {ShadowWifiManager.class})
public class AllInOneTetherSettingsTest {
private static final String[] WIFI_REGEXS = {"wifi_regexs"};
+ private static final String[] USB_REGEXS = {"usb_regexs"};
+ private static final String[] BT_REGEXS = {"bt_regexs"};
private Context mContext;
private AllInOneTetherSettings mAllInOneTetherSettings;
@@ -65,33 +74,54 @@
doReturn(mConnectivityManager)
.when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
doReturn(WIFI_REGEXS).when(mConnectivityManager).getTetherableWifiRegexs();
+ doReturn(USB_REGEXS).when(mConnectivityManager).getTetherableUsbRegexs();
+ doReturn(BT_REGEXS).when(mConnectivityManager).getTetherableBluetoothRegexs();
doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
+ // Assume the feature is enabled for most test cases.
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE, true);
mAllInOneTetherSettings = new AllInOneTetherSettings();
+ ReflectionHelpers.setField(mAllInOneTetherSettings, "mLifecycle", mock(Lifecycle.class));
}
@Test
- public void getNonIndexableKeys_tetherAvailable_keysNotReturned() {
+ public void getNonIndexableKeys_tetherAvailable_featureEnabled_keysReturnedCorrectly() {
// To let TetherUtil.isTetherAvailable return true, select one of the combinations
setupIsTetherAvailable(true);
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE, true);
+ final List<String> niks =
+ AllInOneTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+
+ assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
+ assertThat(niks).doesNotContain(
+ AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
+ assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
+ assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_AP_BAND);
+ assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_SECURITY);
+ assertThat(niks).doesNotContain(BLUETOOTH_TETHER_KEY);
+ assertThat(niks).doesNotContain(USB_TETHER_KEY);
+
+ // This key should be returned because it's not visible by default.
+ assertThat(niks).contains(WIFI_TETHER_DISABLE_KEY);
+ }
+
+ @Test
+ public void getNonIndexableKeys_tetherAvailable_featureDisabled_keysReturned() {
+ setupIsTetherAvailable(true);
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE, false);
+
final List<String> niks =
AllInOneTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
- if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE)) {
- assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
- assertThat(niks).doesNotContain(
- AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
- assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
- assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_AP_BAND);
- assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_SECURITY);
- } else {
- assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
- assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
- assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
- assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_AP_BAND);
- assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_SECURITY);
- }
+ assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
+ assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
+ assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
+ assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_AP_BAND);
+ assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_SECURITY);
+ assertThat(niks).contains(WIFI_TETHER_DISABLE_KEY);
+ assertThat(niks).contains(BLUETOOTH_TETHER_KEY);
+ assertThat(niks).contains(USB_TETHER_KEY);
}
@Test
@@ -107,6 +137,9 @@
assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_AP_BAND);
assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_SECURITY);
+ assertThat(niks).contains(WIFI_TETHER_DISABLE_KEY);
+ assertThat(niks).doesNotContain(BLUETOOTH_TETHER_KEY);
+ assertThat(niks).doesNotContain(USB_TETHER_KEY);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
index 6fa2251..3aa82fe 100644
--- a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
@@ -41,6 +41,7 @@
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.SwitchBarController;
+import com.android.settings.widget.SwitchWidgetController;
import org.junit.Before;
import org.junit.Test;
@@ -67,6 +68,7 @@
private SwitchBar mSwitchBar;
private TetherEnabler mEnabler;
+ private SwitchWidgetController mSwitchWidgetController;
@Before
public void setUp() {
@@ -74,7 +76,8 @@
Context context = spy(ApplicationProvider.getApplicationContext());
AtomicReference<BluetoothPan> panReference = spy(AtomicReference.class);
- mSwitchBar = new SwitchBar(context);
+ mSwitchBar = spy(new SwitchBar(context));
+ mSwitchWidgetController = spy(new SwitchBarController(mSwitchBar));
when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
mConnectivityManager);
@@ -84,7 +87,7 @@
panReference.set(mBluetoothPan);
when(context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE))
.thenReturn(mSharedPreferences);
- mEnabler = new TetherEnabler(context, new SwitchBarController(mSwitchBar), panReference);
+ mEnabler = spy(new TetherEnabler(context, mSwitchWidgetController, panReference));
}
@Test
@@ -121,7 +124,7 @@
@Test
public void onDataSaverChanged_setsEnabledCorrectly() {
- assertThat(mSwitchBar.isEnabled()).isTrue();
+ mSwitchBar.setEnabled(true);
// try to turn data saver on
when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(true);
@@ -179,4 +182,33 @@
verify(mConnectivityManager).startTethering(
eq(ConnectivityManager.TETHERING_BLUETOOTH), anyBoolean(), any(), any());
}
+
+ @Test
+ public void updateState_onSwitchToggleNeverCalled() {
+ mSwitchWidgetController.setListener(mEnabler);
+ mSwitchWidgetController.startListening();
+
+ mEnabler.updateState(null/*tethered*/);
+ verify(mEnabler, never()).onSwitchToggled(anyBoolean());
+ }
+
+ @Test
+ public void updateState_shouldEnableSwitchBarNotTethering() {
+ mSwitchWidgetController.setListener(mEnabler);
+ mSwitchWidgetController.startListening();
+
+ ReflectionHelpers.setField(mEnabler, "mDataSaverEnabled", false);
+ mEnabler.updateState(null/*tethered*/);
+ verify(mSwitchBar).setEnabled(true);
+ }
+
+ @Test
+ public void updateState_shouldEnableSwitchBarTethering() {
+ mSwitchWidgetController.setListener(mEnabler);
+ mSwitchWidgetController.startListening();
+
+ ReflectionHelpers.setField(mEnabler, "mDataSaverEnabled", false);
+ mEnabler.updateState(new String[]{""});
+ verify(mSwitchBar).setEnabled(true);
+ }
}