Refactor new tether settings to remove SharedPreferences

Bluetooth, USB and Wifi Disable tether preferences will turn on/off that
type of tethering interface instantly without storing it into
SharedPreferences. They are listening to TetherEnabler to update their
state.
Refactored to remove dependancy on SharedPreferences.

Bug: 151367756
Test: TetherEnablerTest; BluetoothTetherPreferenceControllerTest;
UsbTetherPreferenceControllerTest;
WifiTetherDisablePreferenceControllerTest; AllInOneSettingsTest;
AllInOneTetherPreferenceControllerTest

Change-Id: Ia6cc60bc4de8f08413beb6d41552a18f6fa6a55b
This commit is contained in:
Zhen Zhang
2020-03-15 11:18:01 -07:00
parent f5ff928958
commit 7f2d6ce058
12 changed files with 406 additions and 498 deletions

View File

@@ -20,8 +20,6 @@ import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.ConnectivityManager.TETHERING_WIFI;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
import static com.android.settings.network.TetherEnabler.KEY_ENABLE_WIFI_TETHERING;
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
@@ -30,7 +28,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -74,8 +71,7 @@ import java.util.concurrent.atomic.AtomicReference;
@SearchIndexable
public class AllInOneTetherSettings extends RestrictedDashboardFragment
implements DataSaverBackend.Listener,
WifiTetherBasePreferenceController.OnTetherConfigUpdateListener,
SharedPreferences.OnSharedPreferenceChangeListener {
WifiTetherBasePreferenceController.OnTetherConfigUpdateListener {
// TODO(b/148622133): Should clean up the postfix once this fragment replaced TetherSettings.
public static final String DEDUP_POSTFIX = "_2";
@@ -114,9 +110,18 @@ public class AllInOneTetherSettings extends RestrictedDashboardFragment
private WifiTetherApBandPreferenceController mApBandPreferenceController;
private WifiTetherSecurityPreferenceController mSecurityPreferenceController;
private PreferenceGroup mWifiTetherGroup;
private SharedPreferences mSharedPreferences;
private boolean mWifiTetherChosen;
private boolean mBluetoothTethering;
private boolean mUsbTethering;
private boolean mWifiTethering;
private TetherEnabler mTetherEnabler;
private final TetherEnabler.OnTetherStateUpdateListener mStateUpdateListener =
state -> {
mBluetoothTethering = TetherEnabler.isBluetoothTethering(state);
mUsbTethering = TetherEnabler.isUsbTethering(state);
mWifiTethering = TetherEnabler.isWifiTethering(state);
mWifiTetherGroup.setVisible(shouldShowWifiConfig());
reConfigInitialExpandedChildCount();
};
private final BroadcastReceiver mTetherChangeReceiver = new BroadcastReceiver() {
@Override
@@ -136,7 +141,6 @@ public class AllInOneTetherSettings extends RestrictedDashboardFragment
private void restartWifiTetherIfNeed(int state) {
if (state == WifiManager.WIFI_AP_STATE_DISABLED
&& mWifiTetherChosen
&& mRestartWifiApAfterConfigChange) {
mRestartWifiApAfterConfigChange = false;
mTetherEnabler.startTethering(TETHERING_WIFI);
@@ -168,8 +172,6 @@ public class AllInOneTetherSettings extends RestrictedDashboardFragment
public void onAttach(Context context) {
super.onAttach(context);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mSharedPreferences =
context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
mSSIDPreferenceController = use(WifiTetherSSIDPreferenceController.class);
mSecurityPreferenceController = use(WifiTetherSecurityPreferenceController.class);
@@ -199,9 +201,6 @@ public class AllInOneTetherSettings extends RestrictedDashboardFragment
// Set initial state based on Data Saver mode.
onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled());
// Set initial state based on SharedPreferences value.
onSharedPreferenceChanged(mSharedPreferences, KEY_ENABLE_WIFI_TETHERING);
}
@Override
@@ -222,6 +221,9 @@ public class AllInOneTetherSettings extends RestrictedDashboardFragment
mTetherEnabler = new TetherEnabler(activity,
new SwitchBarController(switchBar), mBluetoothPan);
getSettingsLifecycle().addObserver(mTetherEnabler);
use(UsbTetherPreferenceController.class).setTetherEnabler(mTetherEnabler);
use(BluetoothTetherPreferenceController.class).setTetherEnabler(mTetherEnabler);
use(WifiTetherDisablePreferenceController.class).setTetherEnabler(mTetherEnabler);
switchBar.show();
}
@@ -247,13 +249,13 @@ public class AllInOneTetherSettings extends RestrictedDashboardFragment
@Override
public void onResume() {
super.onResume();
mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
mTetherEnabler.addListener(mStateUpdateListener);
}
@Override
public void onPause() {
super.onPause();
mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
mTetherEnabler.removeListener(mStateUpdateListener);
}
@Override
@@ -365,13 +367,8 @@ public class AllInOneTetherSettings extends RestrictedDashboardFragment
mApBandPreferenceController.updateDisplay();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (TextUtils.equals(key, KEY_ENABLE_WIFI_TETHERING)) {
mWifiTetherChosen = sharedPreferences.getBoolean(KEY_ENABLE_WIFI_TETHERING, true);
mWifiTetherGroup.setVisible(mWifiTetherChosen);
reConfigInitialExpandedChildCount();
}
private boolean shouldShowWifiConfig() {
return mWifiTethering || (!mBluetoothTethering && !mUsbTethering);
}
private void reConfigInitialExpandedChildCount() {
@@ -380,7 +377,7 @@ public class AllInOneTetherSettings extends RestrictedDashboardFragment
@Override
public int getInitialExpandedChildCount() {
if (!mWifiTetherChosen) {
if (!shouldShowWifiConfig()) {
// Expand all preferences in the screen.
return getPreferenceScreen().getPreferenceCount();
}

View File

@@ -17,16 +17,12 @@ package com.android.settings.network;
import static android.os.UserManager.DISALLOW_CONFIG_TETHERING;
import static com.android.settings.network.TetherEnabler.BLUETOOTH_TETHER_KEY;
import static com.android.settings.network.TetherEnabler.KEY_ENABLE_WIFI_TETHERING;
import static com.android.settings.network.TetherEnabler.USB_TETHER_KEY;
import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfRestrictionEnforced;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.UserHandle;
import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -56,19 +52,23 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
LifecycleObserver, TetherEnabler.OnTetherStateUpdateListener {
private static final String TAG = "AllInOneTetherPreferenceController";
private static final byte HOTSPOT_ONLY = 1;
private static final byte USB_ONLY = 1 << 1;
private static final byte BLUETOOTH_ONLY = 1 << 2;
private static final byte HOTSPOT_AND_USB = HOTSPOT_ONLY | USB_ONLY;
private static final byte HOTSPOT_AND_BLUETOOTH = HOTSPOT_ONLY | BLUETOOTH_ONLY;
private static final byte USB_AND_BLUETOOTH = USB_ONLY | BLUETOOTH_ONLY;
private static final byte HOTSPOT_AND_USB_AND_BLUETOOTH =
HOTSPOT_ONLY | USB_ONLY | BLUETOOTH_ONLY;
private static final byte TETHERING_TYPE_HOTSPOT_ONLY = 1;
private static final byte TETHERING_TYPE_USB_ONLY = 1 << 1;
private static final byte TETHERING_TYPE_BLUETOOTH_ONLY = 1 << 2;
private static final byte TETHERING_TYPE_HOTSPOT_AND_USB =
TETHERING_TYPE_HOTSPOT_ONLY | TETHERING_TYPE_USB_ONLY;
private static final byte TETHERING_TYPE_HOTSPOT_AND_BLUETOOTH =
TETHERING_TYPE_HOTSPOT_ONLY | TETHERING_TYPE_BLUETOOTH_ONLY;
private static final byte TETHERING_TYPE_USB_AND_BLUETOOTH =
TETHERING_TYPE_USB_ONLY | TETHERING_TYPE_BLUETOOTH_ONLY;
private static final byte TETHERING_TYPE_HOTSPOT_AND_USB_AND_BLUETOOTH =
TETHERING_TYPE_HOTSPOT_ONLY | TETHERING_TYPE_USB_ONLY | TETHERING_TYPE_BLUETOOTH_ONLY;
// A bitwise value that stands for the current tethering interface type.
private int mTetheringType;
private final boolean mAdminDisallowedTetherConfig;
private final AtomicReference<BluetoothPan> mBluetoothPan;
private final BluetoothAdapter mBluetoothAdapter;
private final SharedPreferences mTetherEnablerSharedPreferences;
@VisibleForTesting
final BluetoothProfile.ServiceListener mBtProfileServiceListener =
new BluetoothProfile.ServiceListener() {
@@ -92,7 +92,6 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
mAdminDisallowedTetherConfig = false;
mBluetoothPan = new AtomicReference<>();
mBluetoothAdapter = null;
mTetherEnablerSharedPreferences = null;
}
public AllInOneTetherPreferenceController(Context context, String key) {
@@ -101,8 +100,6 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
mAdminDisallowedTetherConfig = checkIfRestrictionEnforced(
context, DISALLOW_CONFIG_TETHERING, UserHandle.myUserId()) != null;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mTetherEnablerSharedPreferences =
context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
}
@Override
@@ -128,29 +125,22 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
@Override
public CharSequence getSummary() {
if (mPreference != null && mPreference.isChecked()) {
int chosenType = 0;
chosenType |= mTetherEnablerSharedPreferences
.getBoolean(KEY_ENABLE_WIFI_TETHERING, true) ? HOTSPOT_ONLY : 0;
chosenType |= mTetherEnablerSharedPreferences.getBoolean(USB_TETHER_KEY, false)
? USB_ONLY : 0;
chosenType |= mTetherEnablerSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)
? BLUETOOTH_ONLY : 0;
switch (chosenType) {
case HOTSPOT_ONLY:
switch (mTetheringType) {
case TETHERING_TYPE_HOTSPOT_ONLY:
return mContext.getString(R.string.tether_settings_summary_hotspot_only);
case USB_ONLY:
case TETHERING_TYPE_USB_ONLY:
return mContext.getString(R.string.tether_settings_summary_usb_tethering_only);
case BLUETOOTH_ONLY:
case TETHERING_TYPE_BLUETOOTH_ONLY:
return mContext.getString(
R.string.tether_settings_summary_bluetooth_tethering_only);
case HOTSPOT_AND_USB:
case TETHERING_TYPE_HOTSPOT_AND_USB:
return mContext.getString(R.string.tether_settings_summary_hotspot_and_usb);
case HOTSPOT_AND_BLUETOOTH:
case TETHERING_TYPE_HOTSPOT_AND_BLUETOOTH:
return mContext.getString(
R.string.tether_settings_summary_hotspot_and_bluetooth);
case USB_AND_BLUETOOTH:
case TETHERING_TYPE_USB_AND_BLUETOOTH:
return mContext.getString(R.string.tether_settings_summary_usb_and_bluetooth);
case HOTSPOT_AND_USB_AND_BLUETOOTH:
case TETHERING_TYPE_HOTSPOT_AND_USB_AND_BLUETOOTH:
return mContext.getString(
R.string.tether_settings_summary_hotspot_and_usb_and_bluetooth);
default:
@@ -174,14 +164,14 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
@OnLifecycleEvent(Event.ON_RESUME)
public void onResume() {
if (mTetherEnabler != null) {
mTetherEnabler.setListener(this);
mTetherEnabler.addListener(this);
}
}
@OnLifecycleEvent(Event.ON_PAUSE)
public void onPause() {
if (mTetherEnabler != null) {
mTetherEnabler.setListener(null);
mTetherEnabler.removeListener(this);
}
}
@@ -206,7 +196,12 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
}
@Override
public void onTetherStateUpdated(boolean isTethering) {
public void onTetherStateUpdated(@TetherEnabler.TetheringState int state) {
mTetheringType = 0;
mTetheringType |= TetherEnabler.isBluetoothTethering(state) ? TETHERING_TYPE_BLUETOOTH_ONLY
: 0;
mTetheringType |= TetherEnabler.isWifiTethering(state) ? TETHERING_TYPE_HOTSPOT_ONLY : 0;
mTetheringType |= TetherEnabler.isUsbTethering(state) ? TETHERING_TYPE_USB_ONLY : 0;
updateState(mPreference);
}
}

View File

@@ -21,8 +21,7 @@ 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.net.TetheringManager;
import android.text.TextUtils;
import android.util.Log;
@@ -30,9 +29,6 @@ import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.TogglePreferenceController;
import com.google.common.annotations.VisibleForTesting;
@@ -40,36 +36,33 @@ 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.
*/
public final class BluetoothTetherPreferenceController extends TogglePreferenceController
implements LifecycleObserver, SharedPreferences.OnSharedPreferenceChangeListener {
public final class BluetoothTetherPreferenceController extends TetherBasePreferenceController
implements LifecycleObserver {
private static final String TAG = "BluetoothTetherPreferenceController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final ConnectivityManager mCm;
private int mBluetoothState;
private Preference mPreference;
private final SharedPreferences mSharedPreferences;
private boolean mBluetoothTethering;
public BluetoothTetherPreferenceController(Context context, String prefKey) {
super(context, prefKey);
mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mSharedPreferences =
context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
public BluetoothTetherPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public boolean isChecked() {
return mSharedPreferences.getBoolean(mPreferenceKey, false);
return mBluetoothTethering;
}
@Override
public boolean setChecked(boolean isChecked) {
if (DEBUG) {
Log.d(TAG, "preference changing to " + isChecked);
if (mTetherEnabler == null) {
return false;
}
if (isChecked) {
mTetherEnabler.startTethering(TetheringManager.TETHERING_BLUETOOTH);
} else {
mTetherEnabler.stopTethering(TetheringManager.TETHERING_BLUETOOTH);
}
final SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(mPreferenceKey, isChecked);
editor.apply();
return true;
}
@@ -80,27 +73,11 @@ public final class BluetoothTetherPreferenceController extends TogglePreferenceC
new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
@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() {
mContext.unregisterReceiver(mBluetoothChangeReceiver);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(mPreferenceKey);
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
@@ -133,6 +110,12 @@ public final class BluetoothTetherPreferenceController extends TogglePreferenceC
}
}
@Override
public void onTetherStateUpdated(int state) {
mBluetoothTethering = TetherEnabler.isBluetoothTethering(state);
updateState(mPreference);
}
@VisibleForTesting
final BroadcastReceiver mBluetoothChangeReceiver = new BroadcastReceiver() {
@Override
@@ -144,11 +127,4 @@ public final class BluetoothTetherPreferenceController extends TogglePreferenceC
}
}
};
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (TextUtils.equals(mPreferenceKey, key)) {
updateState(mPreference);
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2020 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.net.ConnectivityManager;
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 com.android.settings.core.TogglePreferenceController;
public abstract class TetherBasePreferenceController extends TogglePreferenceController
implements LifecycleObserver, TetherEnabler.OnTetherStateUpdateListener {
private static final String TAG = "TetherBasePreferenceController";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
final ConnectivityManager mCm;
TetherEnabler mTetherEnabler;
Preference mPreference;
public TetherBasePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
/**
* Set TetherEnabler for the controller. Call this method to initialize the controller.
* @param tetherEnabler The tetherEnabler to set for the controller.
*/
public void setTetherEnabler(TetherEnabler tetherEnabler) {
mTetherEnabler = tetherEnabler;
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
// Must call setEnabler() before
if (mTetherEnabler != null) {
mTetherEnabler.addListener(this);
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
if (mTetherEnabler != null) {
mTetherEnabler.removeListener(this);
}
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(mPreferenceKey);
}
}

View File

@@ -31,7 +31,6 @@ 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.net.wifi.WifiManager;
import android.os.Handler;
@@ -51,21 +50,19 @@ import com.android.settings.widget.SwitchWidgetController;
import java.lang.annotation.Retention;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* 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.
* TetherEnabler is a helper to manage Tethering switch on/off state. It offers helper functions to
* turn on/off different types of tethering interfaces 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 class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListener,
DataSaverBackend.Listener, LifecycleObserver,
SharedPreferences.OnSharedPreferenceChangeListener {
private OnTetherStateUpdateListener mListener;
DataSaverBackend.Listener, LifecycleObserver {
/**
* Interface definition for a callback to be invoked when the tethering has been updated.
@@ -74,9 +71,9 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
/**
* Called when the tethering state has changed.
*
* @param isTethering The new tethering state.
* @param state The new tethering state.
*/
void onTetherStateUpdated(boolean isTethering);
void onTetherStateUpdated(@TetheringState int state);
}
private static final String TAG = "TetherEnabler";
@@ -89,12 +86,14 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
value = {TETHERING_OFF, TETHERING_WIFI_ON, TETHERING_USB_ON, TETHERING_BLUETOOTH_ON}
)
@interface TetheringState {}
private static final int TETHERING_OFF = 0;
private static final int TETHERING_WIFI_ON = 1;
private static final int TETHERING_USB_ON = 1 << 1;
private static final int TETHERING_BLUETOOTH_ON = 1 << 2;
public static final String SHARED_PREF = "tether_options";
@VisibleForTesting
static final int TETHERING_OFF = 0;
@VisibleForTesting
static final int TETHERING_WIFI_ON = 1;
@VisibleForTesting
static final int TETHERING_USB_ON = 1 << 1;
@VisibleForTesting
static final int TETHERING_BLUETOOTH_ON = 1 << 2;
// 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";
@@ -102,19 +101,22 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
public static final String USB_TETHER_KEY = "enable_usb_tethering";
public static final String BLUETOOTH_TETHER_KEY = "enable_bluetooth_tethering" + DEDUP_POSTFIX;
@VisibleForTesting
final List<OnTetherStateUpdateListener> mListeners;
private final SwitchWidgetController mSwitchWidgetController;
private final WifiManager mWifiManager;
private final ConnectivityManager mConnectivityManager;
private final DataSaverBackend mDataSaverBackend;
private boolean mDataSaverEnabled;
@VisibleForTesting
boolean mBluetoothTetheringStoppedByUser;
private final Context mContext;
@VisibleForTesting
ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback;
private final AtomicReference<BluetoothPan> mBluetoothPan;
private final SharedPreferences mSharedPreferences;
private boolean mBluetoothEnableForTether;
private final BluetoothAdapter mBluetoothAdapter;
@@ -123,13 +125,13 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
mContext = context;
mSwitchWidgetController = switchWidgetController;
mDataSaverBackend = new DataSaverBackend(context);
mSharedPreferences = context.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE);
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothPan = bluetoothPan;
mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
mListeners = new ArrayList<>();
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
@@ -148,38 +150,37 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
updateState(null/*tethered*/);
}
@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() {
mBluetoothTetheringStoppedByUser = false;
mDataSaverBackend.remListener(this);
mSwitchWidgetController.stopListening();
mContext.unregisterReceiver(mTetherChangeReceiver);
}
public void setListener(@Nullable OnTetherStateUpdateListener listener) {
mListener = listener;
public void addListener(OnTetherStateUpdateListener listener) {
if (listener != null && !mListeners.contains(listener)) {
listener.onTetherStateUpdated(getTetheringState(null /* tethered */));
mListeners.add(listener);
}
}
public void removeListener(OnTetherStateUpdateListener listener) {
if (listener != null) {
mListeners.remove(listener);
}
}
@VisibleForTesting
void updateState(@Nullable String[] tethered) {
int tetherState = getTetheringState(tethered);
int state = getTetheringState(tethered);
if (DEBUG) {
Log.d(TAG, "updateState: " + tetherState);
Log.d(TAG, "updateState: " + state);
}
setSwitchCheckedInternal(tetherState != TETHERING_OFF);
setSharedPreferencesInternal(tetherState);
setSwitchCheckedInternal(state != TETHERING_OFF);
mSwitchWidgetController.setEnabled(!mDataSaverEnabled);
if (mListener != null) {
mListener.onTetherStateUpdated(tetherState != TETHERING_OFF);
for (int i = 0, size = mListeners.size(); i < size; ++i) {
mListeners.get(i).onTetherStateUpdated(state);
}
}
@@ -189,34 +190,25 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
mSwitchWidgetController.startListening();
}
private void setSharedPreferencesInternal(@TetheringState int tetherState) {
if (tetherState == TETHERING_OFF) {
// We don't override user's preferences when tethering off.
return;
}
mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
final SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(KEY_ENABLE_WIFI_TETHERING, (tetherState & TETHERING_WIFI_ON) != 0);
editor.putBoolean(USB_TETHER_KEY, (tetherState & TETHERING_USB_ON) != 0);
editor.putBoolean(BLUETOOTH_TETHER_KEY, (tetherState & TETHERING_BLUETOOTH_ON) != 0);
editor.commit();
mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
private @TetheringState int getTetheringState(@Nullable String[] tethered) {
@VisibleForTesting
@TetheringState int getTetheringState(@Nullable String[] tethered) {
int tetherState = TETHERING_OFF;
if (tethered == null) {
tethered = mConnectivityManager.getTetheredIfaces();
}
if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
if (mWifiManager.isWifiApEnabled()) {
tetherState |= TETHERING_WIFI_ON;
}
// Only check bluetooth tethering state if not stopped by user already.
if (!mBluetoothTetheringStoppedByUser) {
final BluetoothPan pan = mBluetoothPan.get();
if (pan != null && pan.isTetheringOn()) {
if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON
&& pan != null && pan.isTetheringOn()) {
tetherState |= TETHERING_BLUETOOTH_ON;
}
}
String[] usbRegexs = mConnectivityManager.getTetherableUsbRegexs();
for (String s : tethered) {
@@ -230,79 +222,58 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
return tetherState;
}
@Override
public boolean onSwitchToggled(boolean isChecked) {
if (isChecked && getTetheringState(null /* tethered */) == TETHERING_OFF) {
startTether();
public static boolean isBluetoothTethering(@TetheringState int state) {
return (state & TETHERING_BLUETOOTH_ON) != TETHERING_OFF;
}
if (!isChecked && getTetheringState(null /* tethered */) != TETHERING_OFF) {
stopTether();
public static boolean isUsbTethering(@TetheringState int state) {
return (state & TETHERING_USB_ON) != TETHERING_OFF;
}
public static boolean isWifiTethering(@TetheringState int state) {
return (state & TETHERING_WIFI_ON) != TETHERING_OFF;
}
@Override
public boolean onSwitchToggled(boolean isChecked) {
if (isChecked) {
startTethering(TETHERING_WIFI);
} else {
stopTethering(TETHERING_USB);
stopTethering(TETHERING_WIFI);
stopTethering(TETHERING_BLUETOOTH);
}
return true;
}
private void stopTether() {
// Wi-Fi tether is selected by default.
if (mSharedPreferences.getBoolean(KEY_ENABLE_WIFI_TETHERING, true)) {
stopTethering(TETHERING_WIFI);
}
if (mSharedPreferences.getBoolean(USB_TETHER_KEY, false)) {
stopTethering(TETHERING_USB);
}
if (mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)) {
stopTethering(TETHERING_BLUETOOTH);
}
}
/**
* Use this method to stop a single choice of tethering.
*
* @param choice The choice of tethering to stop.
*/
public void stopTethering(int choice) {
mConnectivityManager.stopTethering(choice);
}
@VisibleForTesting
void startTether() {
// Wi-Fi tether is selected by default.
if (mSharedPreferences.getBoolean(KEY_ENABLE_WIFI_TETHERING, true)) {
startTethering(TETHERING_WIFI);
}
if (mSharedPreferences.getBoolean(USB_TETHER_KEY, false)) {
startTethering(TETHERING_USB);
}
if (mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)) {
startTethering(TETHERING_BLUETOOTH);
}
}
/**
* Use this method to start a single choice of tethering.
* For bluetooth tethering, it will first turn on bluetooth if bluetooth is off.
* For Wi-Fi tethering, it will be no-op if Wi-Fi tethering already active.
*
* @param choice The choice of tethering to start.
*/
public void startTethering(int choice) {
int state = getTetheringState(null /* tethered */);
if ((choice == TETHERING_WIFI && isWifiTethering(state))
|| (choice == TETHERING_USB && isUsbTethering(state))
|| (choice == TETHERING_BLUETOOTH && isBluetoothTethering(state))) {
mSwitchWidgetController.setEnabled(false);
if (choice == TETHERING_WIFI && mWifiManager.isWifiApEnabled()) {
if (DEBUG) {
Log.d(TAG, "Wifi tether already active!");
mConnectivityManager.stopTethering(choice);
if (choice == TETHERING_BLUETOOTH) {
// Stop bluetooth tether won't invoke tether state changed callback, so we need this
// boolean to remember the user action and update UI state immediately.
mBluetoothTetheringStoppedByUser = true;
updateState(null /* tethered */);
}
}
}
public void startTethering(int choice) {
int state = getTetheringState(null /* tethered */);
if ((choice == TETHERING_WIFI && isWifiTethering(state))
|| (choice == TETHERING_USB && isUsbTethering(state))) {
return;
}
if (choice == TETHERING_BLUETOOTH) {
if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
mBluetoothTetheringStoppedByUser = false;
if (isBluetoothTethering(state)) {
return;
} else if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
if (DEBUG) {
Log.d(TAG, "Turn on bluetooth first.");
}
@@ -312,6 +283,7 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
}
}
mSwitchWidgetController.setEnabled(false);
mConnectivityManager.startTethering(choice, true /* showProvisioningUi */,
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
}
@@ -392,32 +364,6 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
// 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(KEY_ENABLE_WIFI_TETHERING, 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);
}
}
}
private static final class OnStartTetheringCallback extends
ConnectivityManager.OnStartTetheringCallback {
final WeakReference<TetherEnabler> mTetherEnabler;

View File

@@ -20,60 +20,52 @@ 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.net.TetheringManager;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.Utils;
import com.android.settings.core.TogglePreferenceController;
/**
* This controller helps to manage the switch state and visibility of USB tether switch
* preference. It stores preference values when preference changed.
*
*/
public final class UsbTetherPreferenceController extends TogglePreferenceController implements
LifecycleObserver, SharedPreferences.OnSharedPreferenceChangeListener {
public final class UsbTetherPreferenceController extends TetherBasePreferenceController implements
LifecycleObserver {
private static final String TAG = "UsbTetherPrefController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final ConnectivityManager mCm;
private boolean mUsbConnected;
private boolean mMassStorageActive;
private Preference mPreference;
private final SharedPreferences mSharedPreferences;
private boolean mUsbTethering;
public UsbTetherPreferenceController(Context context, String prefKey) {
super(context, prefKey);
mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mSharedPreferences =
context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
}
@Override
public boolean isChecked() {
return mSharedPreferences.getBoolean(mPreferenceKey, false);
return mUsbTethering;
}
@Override
public boolean setChecked(boolean isChecked) {
if (DEBUG) {
Log.d(TAG, "preference changing to " + isChecked);
if (mTetherEnabler == null) {
return false;
}
if (isChecked) {
mTetherEnabler.startTethering(TetheringManager.TETHERING_USB);
} else {
mTetherEnabler.stopTethering(TetheringManager.TETHERING_USB);
}
final SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(mPreferenceKey, isChecked);
editor.apply();
return true;
}
@@ -86,17 +78,6 @@ public final class UsbTetherPreferenceController extends TogglePreferenceControl
mContext.registerReceiver(mUsbChangeReceiver, filter);
}
@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() {
mContext.unregisterReceiver(mUsbChangeReceiver);
@@ -112,12 +93,6 @@ public final class UsbTetherPreferenceController extends TogglePreferenceControl
}
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(mPreferenceKey);
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
@@ -126,6 +101,12 @@ public final class UsbTetherPreferenceController extends TogglePreferenceControl
}
}
@Override
public void onTetherStateUpdated(int state) {
mUsbTethering = TetherEnabler.isUsbTethering(state);
updateState(mPreference);
}
@VisibleForTesting
final BroadcastReceiver mUsbChangeReceiver = new BroadcastReceiver() {
@Override
@@ -141,11 +122,4 @@ public final class UsbTetherPreferenceController extends TogglePreferenceControl
updateState(mPreference);
}
};
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (TextUtils.equals(mPreferenceKey, key)) {
updateState(mPreference);
}
}
}

View File

@@ -17,21 +17,14 @@
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 android.net.TetheringManager;
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.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.TetherUtil;
/**
@@ -43,61 +36,41 @@ import com.android.settingslib.TetherUtil;
* @see BluetoothTetherPreferenceController
* @see UsbTetherPreferenceController
*/
public final class WifiTetherDisablePreferenceController extends TogglePreferenceController
implements LifecycleObserver, SharedPreferences.OnSharedPreferenceChangeListener {
public final class WifiTetherDisablePreferenceController extends TetherBasePreferenceController
implements LifecycleObserver {
private static final String TAG = "WifiTetherDisablePreferenceController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final ConnectivityManager mCm;
private boolean mBluetoothTetherEnabled;
private boolean mUSBTetherEnabled;
private boolean mBluetoothTethering;
private boolean mUsbTethering;
private boolean mWifiTethering;
private PreferenceScreen mScreen;
private Preference mPreference;
private final SharedPreferences mSharedPreferences;
public WifiTetherDisablePreferenceController(Context context, String prefKey) {
super(context, prefKey);
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);
}
@Override
public boolean isChecked() {
return !mSharedPreferences.getBoolean(TetherEnabler.KEY_ENABLE_WIFI_TETHERING, true);
return !mWifiTethering;
}
@Override
public boolean setChecked(boolean isChecked) {
// The shared preference's value is in the opposite of this preference's value.
final boolean enableWifi = !isChecked;
if (DEBUG) {
Log.d(TAG, "check state changing to " + isChecked);
if (mTetherEnabler == null) {
return false;
}
if (isChecked) {
mTetherEnabler.stopTethering(TetheringManager.TETHERING_WIFI);
} else {
mTetherEnabler.startTethering(TetheringManager.TETHERING_WIFI);
}
final SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(TetherEnabler.KEY_ENABLE_WIFI_TETHERING, enableWifi);
editor.apply();
return true;
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
}
@VisibleForTesting
boolean shouldShow() {
return mBluetoothTetherEnabled || mUSBTetherEnabled;
return mBluetoothTethering || mUsbTethering;
}
@Override
@@ -113,11 +86,11 @@ public final class WifiTetherDisablePreferenceController extends TogglePreferenc
@Override
public CharSequence getSummary() {
if (mUSBTetherEnabled && mBluetoothTetherEnabled) {
if (mUsbTethering && mBluetoothTethering) {
return mContext.getString(R.string.disable_wifi_hotspot_when_usb_and_bluetooth_on);
} else if (mUSBTetherEnabled) {
} else if (mUsbTethering) {
return mContext.getString(R.string.disable_wifi_hotspot_when_usb_on);
} else if (mBluetoothTetherEnabled) {
} else if (mBluetoothTethering) {
return mContext.getString(R.string.disable_wifi_hotspot_when_bluetooth_on);
}
return mContext.getString(R.string.summary_placeholder);
@@ -127,7 +100,6 @@ public final class WifiTetherDisablePreferenceController extends TogglePreferenc
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mScreen = screen;
mPreference = screen.findPreference(mPreferenceKey);
if (mPreference != null) {
mPreference.setOnPreferenceChangeListener(this);
}
@@ -141,42 +113,10 @@ public final class WifiTetherDisablePreferenceController extends TogglePreferenc
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
final boolean shouldShowBefore = shouldShow();
if (TextUtils.equals(TetherEnabler.KEY_ENABLE_WIFI_TETHERING, key) && shouldShowBefore) {
public void onTetherStateUpdated(int state) {
mUsbTethering = TetherEnabler.isUsbTethering(state);
mBluetoothTethering = TetherEnabler.isBluetoothTethering(state);
mWifiTethering = TetherEnabler.isWifiTethering(state);
updateState(mPreference);
return;
}
boolean shouldUpdateState = false;
if (TextUtils.equals(TetherEnabler.USB_TETHER_KEY, key)) {
mUSBTetherEnabled = sharedPreferences.getBoolean(key, false);
shouldUpdateState = true;
} else if (TextUtils.equals(TetherEnabler.BLUETOOTH_TETHER_KEY, key)) {
mBluetoothTetherEnabled = sharedPreferences.getBoolean(key, false);
shouldUpdateState = true;
}
// 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
&& shouldShowBefore && !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);
}
}
}
if (shouldUpdateState) {
updateState(mPreference);
}
}
}

View File

@@ -26,7 +26,6 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.SharedPreferences;
import com.android.settings.widget.MasterSwitchPreference;
@@ -49,8 +48,6 @@ public class AllInOneTetherPreferenceControllerTest {
private BluetoothAdapter mBluetoothAdapter;
@Mock
private MasterSwitchPreference mPreference;
@Mock
private SharedPreferences mSharedPreferences;
private AllInOneTetherPreferenceController mController;
@@ -61,8 +58,6 @@ public class AllInOneTetherPreferenceControllerTest {
ReflectionHelpers.setField(mController, "mContext", mContext);
ReflectionHelpers.setField(mController, "mBluetoothAdapter", mBluetoothAdapter);
ReflectionHelpers.setField(mController, "mPreference", mPreference);
ReflectionHelpers
.setField(mController, "mTetherEnablerSharedPreferences", mSharedPreferences);
}
@Test

View File

@@ -27,8 +27,8 @@ 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 android.net.TetheringManager;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
@@ -47,7 +47,7 @@ public class BluetoothTetherPreferenceControllerTest {
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
private SharedPreferences mSharedPreferences;
private TetherEnabler mTetherEnabler;
private SwitchPreference mSwitchPreference;
private BluetoothTetherPreferenceController mController;
@@ -61,10 +61,9 @@ public class BluetoothTetherPreferenceControllerTest {
mSwitchPreference = spy(SwitchPreference.class);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
mConnectivityManager);
when(mContext.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE))
.thenReturn(mSharedPreferences);
when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[] {""});
mController = new BluetoothTetherPreferenceController(mContext, BLUETOOTH_TETHER_KEY);
mController.setTetherEnabler(mTetherEnabler);
ReflectionHelpers.setField(mController, "mPreference", mSwitchPreference);
}
@@ -77,6 +76,18 @@ public class BluetoothTetherPreferenceControllerTest {
any());
}
@Test
public void lifecycle_shouldAddListenerOnResume() {
mController.onResume();
verify(mTetherEnabler).addListener(mController);
}
@Test
public void lifecycle_shouldRemoveListenrOnPause() {
mController.onPause();
verify(mTetherEnabler).removeListener(mController);
}
@Test
public void lifecycle_shouldUnregisterReceiverOnStop() {
mController.onStart();
@@ -96,18 +107,26 @@ public class BluetoothTetherPreferenceControllerTest {
}
@Test
public void switch_shouldCheckedWhenSharedPreferenceIsTrue() {
when(mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)).thenReturn(true);
mController.onSharedPreferenceChanged(mSharedPreferences, BLUETOOTH_TETHER_KEY);
verify(mSwitchPreference).setChecked(true);
public void setChecked_shouldStartBluetoothTethering() {
mController.setChecked(true);
verify(mTetherEnabler).startTethering(TetheringManager.TETHERING_BLUETOOTH);
}
@Test
public void switch_shouldUnCheckedWhenSharedPreferenceIsFalse() {
when(mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)).thenReturn(false);
mController.onSharedPreferenceChanged(mSharedPreferences, BLUETOOTH_TETHER_KEY);
public void setUnchecked_shouldStopBluetoothTethering() {
mController.setChecked(false);
verify(mTetherEnabler).stopTethering(TetheringManager.TETHERING_BLUETOOTH);
}
verify(mSwitchPreference).setChecked(false);
@Test
public void switch_shouldCheckedWhenBluetoothTethering() {
mController.onTetherStateUpdated(TetherEnabler.TETHERING_BLUETOOTH_ON);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void switch_shouldUnCheckedWhenBluetoothNotTethering() {
mController.onTetherStateUpdated(TetherEnabler.TETHERING_OFF);
assertThat(mController.isChecked()).isFalse();
}
}

View File

@@ -32,13 +32,14 @@ import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkPolicyManager;
import android.net.TetheringManager;
import android.net.wifi.WifiManager;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.network.TetherEnabler.OnTetherStateUpdateListener;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.SwitchBarController;
import com.android.settings.widget.SwitchWidgetController;
@@ -51,6 +52,8 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@RunWith(RobolectricTestRunner.class)
@@ -64,7 +67,7 @@ public class TetherEnablerTest {
@Mock
private BluetoothPan mBluetoothPan;
@Mock
private SharedPreferences mSharedPreferences;
private BluetoothAdapter mBluetoothAdapter;
private SwitchBar mSwitchBar;
private TetherEnabler mEnabler;
@@ -88,22 +91,8 @@ public class TetherEnablerTest {
when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[0]);
when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(new String[0]);
panReference.set(mBluetoothPan);
when(context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE))
.thenReturn(mSharedPreferences);
SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class);
when(mSharedPreferences.edit()).thenReturn(editor);
mEnabler = spy(new TetherEnabler(context, mSwitchWidgetController, panReference));
}
@Test
public void lifecycle_onPause_unRegisterSharedPreferenceListener() {
mEnabler.onResume();
verify(mSharedPreferences).registerOnSharedPreferenceChangeListener(
eq(mEnabler));
mEnabler.onPause();
verify(mSharedPreferences).unregisterOnSharedPreferenceChangeListener(
eq(mEnabler));
ReflectionHelpers.setField(mEnabler, "mBluetoothAdapter", mBluetoothAdapter);
}
@Test
@@ -115,11 +104,20 @@ public class TetherEnablerTest {
assertThat(mSwitchBar.isChecked()).isTrue();
}
@Test
public void lifecycle_onStop_resetBluetoothTetheringStoppedByUser() {
mEnabler.onStart();
mEnabler.mBluetoothTetheringStoppedByUser = true;
mEnabler.onStop();
assertThat(mEnabler.mBluetoothTetheringStoppedByUser).isFalse();
}
@Test
public void startTether_fail_resetSwitchBar() {
when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false);
mEnabler.onStart();
mEnabler.startTether();
mEnabler.startTethering(TetheringManager.TETHERING_WIFI);
when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[0]);
mEnabler.mOnStartTetheringCallback.onTetheringFailed();
@@ -145,8 +143,6 @@ public class TetherEnablerTest {
@Test
public void onSwitchToggled_onlyStartsWifiTetherWhenNeeded() {
when(mSharedPreferences.getBoolean(TetherEnabler.KEY_ENABLE_WIFI_TETHERING, true))
.thenReturn(true);
when(mWifiManager.isWifiApEnabled()).thenReturn(true);
mEnabler.onSwitchToggled(true);
verify(mConnectivityManager, never()).startTethering(anyInt(), anyBoolean(), any(), any());
@@ -157,36 +153,28 @@ public class TetherEnablerTest {
}
@Test
public void onSwitchToggled_shouldStartUSBTetherWhenSelected() {
SharedPreferences preference = mock(SharedPreferences.class);
ReflectionHelpers.setField(mEnabler, "mSharedPreferences", preference);
when(preference.getBoolean(TetherEnabler.KEY_ENABLE_WIFI_TETHERING, true))
.thenReturn(false);
when(preference.getBoolean(TetherEnabler.USB_TETHER_KEY, false)).thenReturn(true);
when(preference.getBoolean(TetherEnabler.BLUETOOTH_TETHER_KEY, true)).thenReturn(false);
public void startTethering_startsBluetoothTetherWhenOff() {
when(mBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
mEnabler.startTether();
mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
verify(mBluetoothAdapter).enable();
when(mBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
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(
eq(ConnectivityManager.TETHERING_BLUETOOTH), anyBoolean(), any(), any());
}
@Test
public void startTether_startsBluetoothTetherWhenOff() {
BluetoothAdapter adapter = mock(BluetoothAdapter.class);
ReflectionHelpers.setField(mEnabler, "mBluetoothAdapter", adapter);
when(adapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
public void stopTethering_setBluetoothTetheringStoppedByUserAndUpdateState() {
mSwitchWidgetController.setListener(mEnabler);
mSwitchWidgetController.startListening();
int state = TetherEnabler.TETHERING_BLUETOOTH_ON;
doReturn(state).when(mEnabler).getTetheringState(null /* tethered */);
mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
verify(adapter).enable();
when(adapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
verify(mConnectivityManager).startTethering(
eq(ConnectivityManager.TETHERING_BLUETOOTH), anyBoolean(), any(), any());
mEnabler.stopTethering(TetheringManager.TETHERING_BLUETOOTH);
assertThat(mEnabler.mBluetoothTetheringStoppedByUser).isTrue();
verify(mEnabler).updateState(null);
}
@Test
@@ -210,35 +198,44 @@ public class TetherEnablerTest {
@Test
public void updateState_shouldEnableSwitchBarTethering() {
when(mConnectivityManager.getTetheredIfaces()).thenReturn(USB_TETHERED);
when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(USB_TETHERED);
mSwitchWidgetController.setListener(mEnabler);
mSwitchWidgetController.startListening();
ReflectionHelpers.setField(mEnabler, "mDataSaverEnabled", false);
mEnabler.updateState(new String[]{""});
mEnabler.updateState(null/*tethered*/);
verify(mSwitchBar).setEnabled(true);
}
@Test
public void updateState_onSharedPreferencesChangeNeverCalled() {
mSharedPreferences.registerOnSharedPreferenceChangeListener(mEnabler);
public void updateState_shouldCallListener() {
OnTetherStateUpdateListener listener = mock(
OnTetherStateUpdateListener.class);
List<OnTetherStateUpdateListener> listeners = new ArrayList<>();
listeners.add(listener);
ReflectionHelpers.setField(mEnabler, "mListeners", listeners);
mSwitchWidgetController.setListener(mEnabler);
mSwitchWidgetController.startListening();
mEnabler.updateState(null /* tethered */);
verify(mEnabler, never()).onSharedPreferenceChanged(eq(mSharedPreferences), any());
verify(mEnabler, never()).onSharedPreferenceChanged(eq(mSharedPreferences), any());
verify(listener).onTetherStateUpdated(anyInt());
}
@Test
public void updateState_setSharedPreferencesOnlyWhenNeeded() {
mSwitchWidgetController.setListener(mEnabler);
mSwitchWidgetController.startListening();
public void addListener_listenerShouldAdded() {
OnTetherStateUpdateListener listener = mock(
OnTetherStateUpdateListener.class);
mEnabler.addListener(listener);
assertThat(mEnabler.mListeners).contains(listener);
}
mEnabler.updateState(null /* tethered */);
verify(mSharedPreferences, never()).edit();
when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(USB_TETHERED);
mSharedPreferences.registerOnSharedPreferenceChangeListener(mEnabler);
mEnabler.updateState(USB_TETHERED);
@Test
public void remListener_listenerShouldBeRemoved() {
OnTetherStateUpdateListener listener = mock(
OnTetherStateUpdateListener.class);
mEnabler.removeListener(listener);
assertThat(mEnabler.mListeners).doesNotContain(listener);
}
}

View File

@@ -27,8 +27,8 @@ 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 android.net.TetheringManager;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
@@ -47,7 +47,7 @@ public class UsbTetherPreferenceControllerTest {
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
private SharedPreferences mSharedPreferences;
private TetherEnabler mTetherEnabler;
private Context mContext;
private UsbTetherPreferenceController mController;
@@ -61,9 +61,8 @@ public class UsbTetherPreferenceControllerTest {
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
mConnectivityManager);
when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(new String[]{""});
when(mContext.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE))
.thenReturn(mSharedPreferences);
mController = new UsbTetherPreferenceController(mContext, USB_TETHER_KEY);
mController.setTetherEnabler(mTetherEnabler);
mSwitchPreference = spy(SwitchPreference.class);
ReflectionHelpers.setField(mController, "mPreference", mSwitchPreference);
}
@@ -75,6 +74,18 @@ public class UsbTetherPreferenceControllerTest {
verify(mContext).registerReceiver(eq(mController.mUsbChangeReceiver), any());
}
@Test
public void lifecycle_shouldAddListenerOnResume() {
mController.onResume();
verify(mTetherEnabler).addListener(mController);
}
@Test
public void lifecycle_shouldRemoveListenrOnPause() {
mController.onPause();
verify(mTetherEnabler).removeListener(mController);
}
@Test
public void lifecycle_shouldUnregisterReceiverOnStop() {
mController.onStart();
@@ -93,18 +104,26 @@ public class UsbTetherPreferenceControllerTest {
}
@Test
public void switch_shouldCheckedWhenSharedPreferencesIsTrue() {
when(mSharedPreferences.getBoolean(USB_TETHER_KEY, false)).thenReturn(true);
mController.onSharedPreferenceChanged(mSharedPreferences, USB_TETHER_KEY);
verify(mSwitchPreference).setChecked(true);
public void setChecked_shouldStartUsbTethering() {
mController.setChecked(true);
verify(mTetherEnabler).startTethering(TetheringManager.TETHERING_USB);
}
@Test
public void switch_shouldUnCheckedWhenSharedPreferencesIsFalse() {
when(mSharedPreferences.getBoolean(USB_TETHER_KEY, false)).thenReturn(false);
mController.onSharedPreferenceChanged(mSharedPreferences, USB_TETHER_KEY);
public void setUnchecked_shouldStopUsbTethering() {
mController.setChecked(false);
verify(mTetherEnabler).stopTethering(TetheringManager.TETHERING_USB);
}
verify(mSwitchPreference).setChecked(false);
@Test
public void switch_shouldCheckedWhenUsbTethering() {
mController.onTetherStateUpdated(TetherEnabler.TETHERING_USB_ON);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void switch_shouldUnCheckedWhenUsbNotTethering() {
mController.onTetherStateUpdated(TetherEnabler.TETHERING_OFF);
assertThat(mController.isChecked()).isFalse();
}
}

View File

@@ -16,20 +16,16 @@
package com.android.settings.network;
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.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.preference.PreferenceScreen;
@@ -50,9 +46,9 @@ public class WifiTetherDisablePreferenceControllerTest {
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
private SharedPreferences mSharedPreferences;
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock
private TetherEnabler mTetherEnabler;
private SwitchPreference mPreference;
private Context mContext;
@@ -67,60 +63,40 @@ public class WifiTetherDisablePreferenceControllerTest {
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, WIFI_TETHER_DISABLE_KEY);
mController.setTetherEnabler(mTetherEnabler);
ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
ReflectionHelpers.setField(mController, "mPreference", mPreference);
when(mPreferenceScreen.findPreference(WIFI_TETHER_DISABLE_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);
ReflectionHelpers.setField(mController, "mBluetoothTethering", false);
ReflectionHelpers.setField(mController, "mUsbTethering", false);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void switch_shouldListenToUsbAndBluetooth() {
when(mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)).thenReturn(true);
mController.onSharedPreferenceChanged(mSharedPreferences, BLUETOOTH_TETHER_KEY);
int state = TetherEnabler.TETHERING_BLUETOOTH_ON;
mController.onTetherStateUpdated(state);
verify(mPreference).setVisible(eq(true));
when(mSharedPreferences.getBoolean(USB_TETHER_KEY, false)).thenReturn(true);
mController.onSharedPreferenceChanged(mSharedPreferences, USB_TETHER_KEY);
state |= TetherEnabler.TETHERING_USB_ON;
mController.onTetherStateUpdated(state);
assertThat(mController.shouldShow()).isTrue();
when(mSharedPreferences.getBoolean(USB_TETHER_KEY, false)).thenReturn(false);
mController.onSharedPreferenceChanged(mSharedPreferences, USB_TETHER_KEY);
state = TetherEnabler.TETHERING_USB_ON;
mController.onTetherStateUpdated(state);
assertThat(mController.shouldShow()).isTrue();
when(mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)).thenReturn(false);
when(mSharedPreferences.edit()).thenReturn(mock(SharedPreferences.Editor.class));
when(mPreference.isChecked()).thenReturn(true);
mController.onSharedPreferenceChanged(mSharedPreferences, BLUETOOTH_TETHER_KEY);
verify(mPreference).setChecked(eq(false));
state = TetherEnabler.TETHERING_OFF;
mController.onTetherStateUpdated(state);
verify(mPreference).setVisible(eq(false));
}
}