Merge "Create preference controller for each tethering option"
diff --git a/src/com/android/settings/network/BluetoothTetherPreferenceController.java b/src/com/android/settings/network/BluetoothTetherPreferenceController.java
new file mode 100644
index 0000000..10849a0
--- /dev/null
+++ b/src/com/android/settings/network/BluetoothTetherPreferenceController.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2019 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.network;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * This controller helps to manage the switch state and visibility of bluetooth tether switch
+ * preference. It stores preference value when preference changed.
+ * TODO(b/147272749): Extend BasePreferenceController.java instead.
+ */
+public final class BluetoothTetherPreferenceController extends AbstractPreferenceController
+ implements LifecycleObserver, Preference.OnPreferenceChangeListener {
+
+ private static final String TAG = "BluetoothTetherPreferenceController";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ @VisibleForTesting
+ static final String PREF_KEY = "enable_bluetooth_tethering";
+ private final ConnectivityManager mCm;
+ private int mBluetoothState;
+ private Preference mPreference;
+ private final SharedPreferences mSharedPreferences;
+
+ public BluetoothTetherPreferenceController(Context context, Lifecycle lifecycle) {
+ super(context);
+ mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mSharedPreferences =
+ context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ public void onStart() {
+ mBluetoothState = BluetoothAdapter.getDefaultAdapter().getState();
+ mContext.registerReceiver(mBluetoothChangeReceiver,
+ new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+ public void onStop() {
+ mContext.unregisterReceiver(mBluetoothChangeReceiver);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ final String[] bluetoothRegexs = mCm.getTetherableBluetoothRegexs();
+ return bluetoothRegexs != null && bluetoothRegexs.length > 0;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(PREF_KEY);
+ if (mPreference != null && mPreference instanceof SwitchPreference) {
+ ((SwitchPreference) mPreference)
+ .setChecked(mSharedPreferences.getBoolean(PREF_KEY, false));
+ }
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ switch (mBluetoothState) {
+ case BluetoothAdapter.STATE_ON:
+ case BluetoothAdapter.STATE_OFF:
+ // fall through.
+ case BluetoothAdapter.ERROR:
+ preference.setEnabled(true);
+ break;
+ case BluetoothAdapter.STATE_TURNING_OFF:
+ case BluetoothAdapter.STATE_TURNING_ON:
+ // fall through.
+ default:
+ preference.setEnabled(false);
+ }
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return PREF_KEY;
+ }
+
+ @VisibleForTesting
+ final BroadcastReceiver mBluetoothChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (TextUtils.equals(BluetoothAdapter.ACTION_STATE_CHANGED, intent.getAction())) {
+ mBluetoothState =
+ intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
+ updateState(mPreference);
+ }
+ }
+ };
+
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object o) {
+ if (DEBUG) {
+ Log.d(TAG, "preference changing to " + o);
+ }
+ final SharedPreferences.Editor editor = mSharedPreferences.edit();
+ editor.putBoolean(PREF_KEY, (Boolean) o);
+ editor.apply();
+ return true;
+ }
+}
diff --git a/src/com/android/settings/network/TetherEnabler.java b/src/com/android/settings/network/TetherEnabler.java
index 9106aa1..6c6c959 100644
--- a/src/com/android/settings/network/TetherEnabler.java
+++ b/src/com/android/settings/network/TetherEnabler.java
@@ -32,11 +32,11 @@
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
+import android.util.Log;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
-import androidx.preference.PreferenceManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.datausage.DataSaverBackend;
@@ -52,13 +52,20 @@
*/
public final class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListener,
- DataSaverBackend.Listener, LifecycleObserver {
+ DataSaverBackend.Listener, LifecycleObserver,
+ SharedPreferences.OnSharedPreferenceChangeListener {
+
+ private static final String TAG = "TetherEnabler";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ public static final String SHARED_PREF = "tether_options";
+
@VisibleForTesting
- static final String WIFI_TETHER_KEY = "enable_wifi_tethering";
+ static final String WIFI_TETHER_KEY = WifiTetherDisablePreferenceController.PREF_KEY;
@VisibleForTesting
- static final String USB_TETHER_KEY = "enable_usb_tethering";
+ static final String USB_TETHER_KEY = UsbTetherPreferenceController.PREF_KEY;
@VisibleForTesting
- static final String BLUETOOTH_TETHER_KEY = "enable_bluetooth_tethering";
+ static final String BLUETOOTH_TETHER_KEY = BluetoothTetherPreferenceController.PREF_KEY;
private final SwitchWidgetController mSwitchWidgetController;
private final WifiManager mWifiManager;
@@ -76,7 +83,6 @@
public void onTetheringFailed() {
super.onTetheringFailed();
mSwitchWidgetController.setChecked(false);
- setSwitchWidgetEnabled(true);
}
};
private final AtomicReference<BluetoothPan> mBluetoothPan;
@@ -84,12 +90,12 @@
private boolean mBluetoothEnableForTether;
private final BluetoothAdapter mBluetoothAdapter;
- TetherEnabler(Context context, SwitchWidgetController switchWidgetController,
+ public TetherEnabler(Context context, SwitchWidgetController switchWidgetController,
AtomicReference<BluetoothPan> bluetoothPan) {
mContext = context;
mSwitchWidgetController = switchWidgetController;
mDataSaverBackend = new DataSaverBackend(context);
- mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
+ mSharedPreferences = context.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE);
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -110,6 +116,16 @@
setSwitchWidgetEnabled(true);
}
+ @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
+ public void onResume() {
+ mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
+ public void onPause() {
+ mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
+ }
+
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
mDataSaverBackend.remListener(this);
@@ -148,19 +164,16 @@
@VisibleForTesting
void stopTether() {
- setSwitchWidgetEnabled(false);
- // Wi-Fi tether is selected by default
+ // Wi-Fi tether is selected by default.
if (mSharedPreferences.getBoolean(WIFI_TETHER_KEY, true)) {
mConnectivityManager.stopTethering(TETHERING_WIFI);
}
- // USB tether is not selected by default
if (mSharedPreferences.getBoolean(USB_TETHER_KEY, false)) {
mConnectivityManager.stopTethering(TETHERING_USB);
}
- // Bluetooth tether is not selected by default
if (mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)) {
mConnectivityManager.stopTethering(TETHERING_BLUETOOTH);
}
@@ -168,19 +181,16 @@
@VisibleForTesting
void startTether() {
- setSwitchWidgetEnabled(false);
- // Wi-Fi tether is selected by default
+ // Wi-Fi tether is selected by default.
if (mSharedPreferences.getBoolean(WIFI_TETHER_KEY, true)) {
startTethering(TETHERING_WIFI);
}
- // USB tether is not selected by default
if (mSharedPreferences.getBoolean(USB_TETHER_KEY, false)) {
startTethering(TETHERING_USB);
}
- // Bluetooth tether is not selected by default
if (mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)) {
startTethering(TETHERING_BLUETOOTH);
}
@@ -188,18 +198,24 @@
@VisibleForTesting
void startTethering(int choice) {
+ if (choice == TETHERING_WIFI && mWifiManager.isWifiApEnabled()) {
+ if (DEBUG) {
+ Log.d(TAG, "Wifi tether already active!");
+ }
+ return;
+ }
+
if (choice == TETHERING_BLUETOOTH) {
- // Turn on Bluetooth first.
if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
+ if (DEBUG) {
+ Log.d(TAG, "Turn on bluetooth first.");
+ }
mBluetoothEnableForTether = true;
mBluetoothAdapter.enable();
return;
}
- } else if (choice == TETHERING_WIFI && mWifiManager.isWifiApEnabled()) {
- return;
}
-
mConnectivityManager.startTethering(choice, true /* showProvisioningUi */,
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
}
@@ -213,24 +229,21 @@
ConnectivityManager.EXTRA_ACTIVE_TETHER);
mSwitchWidgetController.setChecked(
isTethering(active.toArray(new String[active.size()])));
- setSwitchWidgetEnabled(true);
} else if (TextUtils.equals(BluetoothAdapter.ACTION_STATE_CHANGED, action)) {
- if (mBluetoothEnableForTether) {
- switch (intent
- .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
- case BluetoothAdapter.STATE_ON:
+ switch (intent
+ .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
+ case BluetoothAdapter.STATE_ON:
+ if (mBluetoothEnableForTether) {
startTethering(TETHERING_BLUETOOTH);
- mBluetoothEnableForTether = false;
- break;
-
- case BluetoothAdapter.STATE_OFF:
- case BluetoothAdapter.ERROR:
- mBluetoothEnableForTether = false;
- break;
-
- default:
- // ignore transition states
- }
+ }
+ // Fall through.
+ case BluetoothAdapter.STATE_OFF:
+ // Fall through.
+ case BluetoothAdapter.ERROR:
+ mBluetoothEnableForTether = false;
+ break;
+ default:
+ // ignore transition states
}
}
}
@@ -251,4 +264,30 @@
public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
// we don't care, since we just want to read the value
}
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (!mSwitchWidgetController.isChecked()) {
+ return;
+ }
+ if (TextUtils.equals(WIFI_TETHER_KEY, key)) {
+ if (sharedPreferences.getBoolean(key, true)) {
+ startTethering(TETHERING_WIFI);
+ } else {
+ mConnectivityManager.stopTethering(TETHERING_WIFI);
+ }
+ } else if (TextUtils.equals(USB_TETHER_KEY, key)) {
+ if (sharedPreferences.getBoolean(key, false)) {
+ startTethering(TETHERING_USB);
+ } else {
+ mConnectivityManager.stopTethering(TETHERING_USB);
+ }
+ } else if (TextUtils.equals(BLUETOOTH_TETHER_KEY, key)) {
+ if (sharedPreferences.getBoolean(key, false)) {
+ startTethering(TETHERING_BLUETOOTH);
+ } else {
+ mConnectivityManager.stopTethering(TETHERING_BLUETOOTH);
+ }
+ }
+ }
}
diff --git a/src/com/android/settings/network/UsbTetherPreferenceController.java b/src/com/android/settings/network/UsbTetherPreferenceController.java
new file mode 100644
index 0000000..74e8be8
--- /dev/null
+++ b/src/com/android/settings/network/UsbTetherPreferenceController.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2019 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.network;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.hardware.usb.UsbManager;
+import android.net.ConnectivityManager;
+import android.os.Environment;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.Utils;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+/**
+ * This controller helps to manage the switch state and visibility of USB tether switch
+ * preference. It stores preference values when preference changed.
+ * TODO(b/147272749): Extend BasePreferenceController.java instead.
+ *
+ */
+public final class UsbTetherPreferenceController extends AbstractPreferenceController implements
+ LifecycleObserver, Preference.OnPreferenceChangeListener {
+
+ private static final String TAG = "UsbTetherPrefController";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ @VisibleForTesting
+ static final String PREF_KEY = "enable_usb_tethering";
+
+ private final ConnectivityManager mCm;
+ private boolean mUsbConnected;
+ private boolean mMassStorageActive;
+ private Preference mPreference;
+ private final SharedPreferences mSharedPreferences;
+
+ public UsbTetherPreferenceController(Context context, Lifecycle lifecycle) {
+ super(context);
+ mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mSharedPreferences =
+ context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ public void onStart() {
+ mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState());
+ IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE);
+ filter.addAction(Intent.ACTION_MEDIA_SHARED);
+ filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
+ mContext.registerReceiver(mUsbChangeReceiver, filter);
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+ public void onStop() {
+ mContext.unregisterReceiver(mUsbChangeReceiver);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ String[] usbRegexs = mCm.getTetherableUsbRegexs();
+ return usbRegexs != null && usbRegexs.length > 0 && !Utils.isMonkeyRunning();
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return PREF_KEY;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(PREF_KEY);
+ if (mPreference != null && mPreference instanceof SwitchPreference) {
+ ((SwitchPreference) mPreference)
+ .setChecked(mSharedPreferences.getBoolean(PREF_KEY, false));
+ }
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (preference != null) {
+ if (mUsbConnected && !mMassStorageActive) {
+ preference.setEnabled(true);
+ } else {
+ preference.setEnabled(false);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ final BroadcastReceiver mUsbChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (TextUtils.equals(Intent.ACTION_MEDIA_SHARED, action)) {
+ mMassStorageActive = true;
+ } else if (TextUtils.equals(Intent.ACTION_MEDIA_UNSHARED, action)) {
+ mMassStorageActive = false;
+ } else if (TextUtils.equals(UsbManager.ACTION_USB_STATE, action)) {
+ mUsbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
+ }
+ updateState(mPreference);
+ }
+ };
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object o) {
+ if (DEBUG) {
+ Log.d(TAG, "preference changing to " + o);
+ }
+ final SharedPreferences.Editor editor = mSharedPreferences.edit();
+ editor.putBoolean(PREF_KEY, (Boolean) o);
+ editor.apply();
+ return true;
+ }
+}
diff --git a/src/com/android/settings/network/WifiTetherDisablePreferenceController.java b/src/com/android/settings/network/WifiTetherDisablePreferenceController.java
new file mode 100644
index 0000000..bf0e208
--- /dev/null
+++ b/src/com/android/settings/network/WifiTetherDisablePreferenceController.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2019 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.network;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+/**
+ * This controller helps to manage the switch state and visibility of wifi tether disable switch
+ * preference. When the preference checked, wifi tether will be disabled.
+ * It stores preference value when preference changed and listens to usb tether and bluetooth tether
+ * preferences.
+ *
+ * @see BluetoothTetherPreferenceController
+ * @see UsbTetherPreferenceController
+ * TODO(b/147272749): Extend BasePreferenceController.java instead.
+ *
+ */
+public final class WifiTetherDisablePreferenceController extends AbstractPreferenceController
+ implements LifecycleObserver, Preference.OnPreferenceChangeListener,
+ SharedPreferences.OnSharedPreferenceChangeListener {
+
+ private static final String TAG = "WifiTetherDisablePreferenceController";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ @VisibleForTesting
+ static final String PREF_KEY = "enable_wifi_tethering";
+ private final ConnectivityManager mCm;
+ private boolean mBluetoothTetherEnabled;
+ private boolean mUSBTetherEnabled;
+ private PreferenceScreen mScreen;
+ private Preference mPreference;
+ private final SharedPreferences mSharedPreferences;
+
+ public WifiTetherDisablePreferenceController(Context context, Lifecycle lifecycle) {
+ super(context);
+ mSharedPreferences =
+ context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
+ mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mUSBTetherEnabled = mSharedPreferences.getBoolean(
+ TetherEnabler.USB_TETHER_KEY, false);
+ mBluetoothTetherEnabled = mSharedPreferences.getBoolean(
+ TetherEnabler.BLUETOOTH_TETHER_KEY, false);
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
+ public void onResume() {
+ mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
+ public void onPause() {
+ mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ final String[] wifiRegexs = mCm.getTetherableWifiRegexs();
+ return wifiRegexs != null && wifiRegexs.length > 0 && shouldShow();
+ }
+
+ @VisibleForTesting
+ boolean shouldShow() {
+ return mBluetoothTetherEnabled || mUSBTetherEnabled;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return PREF_KEY;
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ // TODO(b/146818850): Update summary accordingly.
+ return super.getSummary();
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mScreen = screen;
+ mPreference = screen.findPreference(PREF_KEY);
+ if (mPreference != null && mPreference instanceof SwitchPreference) {
+ ((SwitchPreference) mPreference)
+ .setChecked(!mSharedPreferences.getBoolean(PREF_KEY, true));
+ mPreference.setOnPreferenceChangeListener(this);
+ }
+ updateState(mPreference);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ setVisible(mScreen, PREF_KEY, shouldShow());
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ if (TextUtils.equals(TetherEnabler.USB_TETHER_KEY, key)) {
+ mUSBTetherEnabled = sharedPreferences.getBoolean(key, false);
+ } else if (TextUtils.equals(TetherEnabler.BLUETOOTH_TETHER_KEY, key)) {
+ mBluetoothTetherEnabled = sharedPreferences.getBoolean(key, false);
+ }
+
+ // Check if we are hiding this preference. If so, make sure the preference is set to
+ // unchecked to enable wifi tether.
+ if (mPreference != null && mPreference instanceof SwitchPreference && !shouldShow()) {
+ final SwitchPreference switchPreference = (SwitchPreference) mPreference;
+ if (switchPreference.isChecked()) {
+ if (DEBUG) {
+ Log.d(TAG,
+ "All other types are unchecked, wifi tether enabled automatically");
+ }
+ // Need to call this method before internal state set.
+ if (switchPreference.callChangeListener(false)) {
+ switchPreference.setChecked(false);
+ }
+ }
+ }
+
+ updateState(mPreference);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object o) {
+ // The shared preference's value is in the opposite of this preference's value.
+ final boolean enableWifi = !(boolean) o;
+ if (true) {
+ Log.d(TAG, "check state changing to " + o);
+ }
+ final SharedPreferences.Editor editor = mSharedPreferences.edit();
+ editor.putBoolean(PREF_KEY, enableWifi);
+ editor.apply();
+ return true;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/BluetoothTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/BluetoothTetherPreferenceControllerTest.java
new file mode 100644
index 0000000..c76e234
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/BluetoothTetherPreferenceControllerTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 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.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothTetherPreferenceControllerTest {
+
+ @Mock
+ private ConnectivityManager mConnectivityManager;
+
+ private BluetoothTetherPreferenceController mController;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
+ mConnectivityManager);
+ when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[] {""});
+ mController = new BluetoothTetherPreferenceController(mContext, mock(Lifecycle.class));
+ }
+
+ @Test
+ public void lifecycle_shouldRegisterReceiverOnStart() {
+ mController.onStart();
+
+ verify(mContext).registerReceiver(
+ eq(mController.mBluetoothChangeReceiver),
+ any());
+ }
+
+ @Test
+ public void lifecycle_shouldUnregisterReceiverOnStop() {
+ mController.onStart();
+ mController.onStop();
+
+ verify(mContext).unregisterReceiver(
+ eq(mController.mBluetoothChangeReceiver));
+ }
+
+ @Test
+ public void display_availableChangedCorrectly() {
+ when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[] {""});
+ assertThat(mController.isAvailable()).isTrue();
+
+ when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[0]);
+ assertThat(mController.isAvailable()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
index 06f3893..9dcfa89 100644
--- a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
@@ -26,7 +26,6 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -83,10 +82,23 @@
mNetworkPolicyManager);
when(mConnectivityManager.getTetherableIfaces()).thenReturn(new String[0]);
panReference.set(mBluetoothPan);
+ when(context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE))
+ .thenReturn(mSharedPreferences);
mEnabler = new TetherEnabler(context, new SwitchBarController(mSwitchBar), panReference);
}
@Test
+ public void lifecycle_onPause_unRegisterSharedPreferenceListener() {
+ mEnabler.onResume();
+ verify(mSharedPreferences).registerOnSharedPreferenceChangeListener(
+ eq(mEnabler));
+
+ mEnabler.onPause();
+ verify(mSharedPreferences).unregisterOnSharedPreferenceChangeListener(
+ eq(mEnabler));
+ }
+
+ @Test
public void lifecycle_onStart_setCheckedCorrectly() {
when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{""});
@@ -122,29 +134,27 @@
@Test
public void onSwitchToggled_onlyStartsWifiTetherWhenNeeded() {
+ when(mSharedPreferences.getBoolean(TetherEnabler.WIFI_TETHER_KEY, true)).thenReturn(true);
when(mWifiManager.isWifiApEnabled()).thenReturn(true);
mEnabler.onSwitchToggled(true);
-
verify(mConnectivityManager, never()).startTethering(anyInt(), anyBoolean(), any(), any());
doReturn(false).when(mWifiManager).isWifiApEnabled();
mEnabler.onSwitchToggled(true);
-
- verify(mConnectivityManager, times(1))
- .startTethering(anyInt(), anyBoolean(), any(), any());
+ verify(mConnectivityManager).startTethering(anyInt(), anyBoolean(), any(), any());
}
@Test
public void onSwitchToggled_shouldStartUSBTetherWhenSelected() {
SharedPreferences preference = mock(SharedPreferences.class);
ReflectionHelpers.setField(mEnabler, "mSharedPreferences", preference);
- when(preference.getBoolean(mEnabler.WIFI_TETHER_KEY, true)).thenReturn(false);
- when(preference.getBoolean(mEnabler.USB_TETHER_KEY, false)).thenReturn(true);
- when(preference.getBoolean(mEnabler.BLUETOOTH_TETHER_KEY, true)).thenReturn(false);
+ when(preference.getBoolean(TetherEnabler.WIFI_TETHER_KEY, true)).thenReturn(false);
+ when(preference.getBoolean(TetherEnabler.USB_TETHER_KEY, false)).thenReturn(true);
+ when(preference.getBoolean(TetherEnabler.BLUETOOTH_TETHER_KEY, true)).thenReturn(false);
mEnabler.startTether();
- verify(mConnectivityManager, times(1))
- .startTethering(eq(ConnectivityManager.TETHERING_USB), anyBoolean(), any(), any());
+ verify(mConnectivityManager).startTethering(
+ eq(ConnectivityManager.TETHERING_USB), anyBoolean(), any(), any());
verify(mConnectivityManager, never())
.startTethering(eq(ConnectivityManager.TETHERING_WIFI), anyBoolean(), any(), any());
verify(mConnectivityManager, never()).startTethering(
@@ -158,11 +168,11 @@
when(adapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
- verify(adapter, times(1)).enable();
+ verify(adapter).enable();
when(adapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
- verify(mConnectivityManager, times(1)).startTethering(
+ verify(mConnectivityManager).startTethering(
eq(ConnectivityManager.TETHERING_BLUETOOTH), anyBoolean(), any(), any());
}
}
diff --git a/tests/robotests/src/com/android/settings/network/UsbTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/UsbTetherPreferenceControllerTest.java
new file mode 100644
index 0000000..9127e4b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/UsbTetherPreferenceControllerTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 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.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class UsbTetherPreferenceControllerTest {
+
+ @Mock
+ private ConnectivityManager mConnectivityManager;
+
+ private Context mContext;
+ private UsbTetherPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
+ mConnectivityManager);
+ when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(new String[] {""});
+ mController = new UsbTetherPreferenceController(mContext, mock(Lifecycle.class));
+ }
+
+ @Test
+ public void lifecycle_shouldRegisterReceiverOnStart() {
+ mController.onStart();
+
+ verify(mContext).registerReceiver(eq(mController.mUsbChangeReceiver), any());
+ }
+
+ @Test
+ public void lifecycle_shouldUnregisterReceiverOnStop() {
+ mController.onStart();
+ mController.onStop();
+
+ verify(mContext).unregisterReceiver(eq(mController.mUsbChangeReceiver));
+ }
+
+ @Test
+ public void display_availableChangedCorrectly() {
+ when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(new String[] {""});
+ assertThat(mController.isAvailable()).isTrue();
+
+ when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(new String[0]);
+ assertThat(mController.isAvailable()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/WifiTetherDisablePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/WifiTetherDisablePreferenceControllerTest.java
new file mode 100644
index 0000000..e42c477
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/WifiTetherDisablePreferenceControllerTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 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.network;
+
+import static com.android.settings.network.WifiTetherDisablePreferenceController.PREF_KEY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class WifiTetherDisablePreferenceControllerTest {
+
+ @Mock
+ private ConnectivityManager mConnectivityManager;
+ @Mock
+ private SharedPreferences mSharedPreferences;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private SwitchPreference mPreference;
+ private Context mContext;
+ private WifiTetherDisablePreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mPreference = spy(SwitchPreference.class);
+ when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
+ mConnectivityManager);
+ when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{""});
+ when(mContext.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE))
+ .thenReturn(mSharedPreferences);
+ mController = new WifiTetherDisablePreferenceController(mContext, mock(Lifecycle.class));
+ ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
+ ReflectionHelpers.setField(mController, "mPreference", mPreference);
+ when(mPreferenceScreen.findPreference(PREF_KEY)).thenReturn(mPreference);
+ }
+
+ @Test
+
+ public void lifecycle_shouldRegisterReceiverOnResume() {
+ mController.onResume();
+
+ verify(mSharedPreferences).registerOnSharedPreferenceChangeListener(eq(mController));
+ }
+
+ @Test
+ public void lifecycle_shouldUnregisterReceiverOnStop() {
+ mController.onResume();
+ mController.onPause();
+
+ verify(mSharedPreferences).unregisterOnSharedPreferenceChangeListener(eq(mController));
+ }
+
+ @Test
+ public void display_availableChangedCorrectly() {
+ when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[0]);
+ assertThat(mController.isAvailable()).isFalse();
+
+ when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"test"});
+ ReflectionHelpers.setField(mController, "mBluetoothTetherEnabled", false);
+ ReflectionHelpers.setField(mController, "mUSBTetherEnabled", false);
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void switch_shouldListenToUsbAndBluetooth() {
+ when(mSharedPreferences.getBoolean(
+ BluetoothTetherPreferenceController.PREF_KEY, false)).thenReturn(true);
+ mController.onSharedPreferenceChanged(mSharedPreferences,
+ BluetoothTetherPreferenceController.PREF_KEY);
+ verify(mPreference).setVisible(eq(true));
+
+ when(mSharedPreferences.getBoolean(
+ UsbTetherPreferenceController.PREF_KEY, false)).thenReturn(true);
+ mController.onSharedPreferenceChanged(mSharedPreferences,
+ UsbTetherPreferenceController.PREF_KEY);
+ assertThat(mController.shouldShow()).isTrue();
+
+ when(mSharedPreferences.getBoolean(
+ UsbTetherPreferenceController.PREF_KEY, false)).thenReturn(false);
+ mController.onSharedPreferenceChanged(mSharedPreferences,
+ UsbTetherPreferenceController.PREF_KEY);
+ assertThat(mController.shouldShow()).isTrue();
+
+ when(mSharedPreferences.getBoolean(
+ BluetoothTetherPreferenceController.PREF_KEY, false)).thenReturn(false);
+ when(mSharedPreferences.edit()).thenReturn(mock(SharedPreferences.Editor.class));
+ when(mPreference.isChecked()).thenReturn(true);
+ mController.onSharedPreferenceChanged(mSharedPreferences,
+ BluetoothTetherPreferenceController.PREF_KEY);
+ verify(mPreference).setChecked(eq(false));
+ verify(mPreference).setVisible(eq(false));
+ }
+}