From 0c02d3381873e839efc0081a65d8e4f2e38d766c Mon Sep 17 00:00:00 2001 From: Zhen Zhang Date: Wed, 26 Feb 2020 15:53:34 -0800 Subject: [PATCH] Update SharedPreference values based on tethering state TetherEnabler need to update tethering state of each tethering interfaces to make sure other preferences that depends on these SharedPreferences be consistent with UI. Bug: 148968321 Test: TetherEnablerTest; CodeInspectionTest. Manully test, built and flashed to crosshatch device. Change-Id: Ie0be7748adf20e6fb0ff5489795b0ca0664b6323 --- .../settings/network/TetherEnabler.java | 67 +++++++++++++++---- .../settings/network/TetherEnablerTest.java | 34 +++++++++- 2 files changed, 85 insertions(+), 16 deletions(-) diff --git a/src/com/android/settings/network/TetherEnabler.java b/src/com/android/settings/network/TetherEnabler.java index e17dcd11cbb..9c689bc6668 100644 --- a/src/com/android/settings/network/TetherEnabler.java +++ b/src/com/android/settings/network/TetherEnabler.java @@ -22,6 +22,9 @@ import static android.net.ConnectivityManager.TETHERING_WIFI; import static com.android.settings.AllInOneTetherSettings.DEDUP_POSTFIX; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothPan; import android.content.BroadcastReceiver; @@ -45,6 +48,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.settings.datausage.DataSaverBackend; import com.android.settings.widget.SwitchWidgetController; +import java.lang.annotation.Retention; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicReference; @@ -78,6 +82,18 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe private static final String TAG = "TetherEnabler"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + @Retention(SOURCE) + @IntDef( + flag = true, + 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"; // This KEY is used for a shared preference value, not for any displayed preferences. @@ -155,14 +171,15 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe @VisibleForTesting void updateState(@Nullable String[] tethered) { - boolean isTethering = tethered == null ? isTethering() : isTethering(tethered); + int tetherState = getTetheringState(tethered); if (DEBUG) { - Log.d(TAG, "updateState: " + isTethering); + Log.d(TAG, "updateState: " + tetherState); } - setSwitchCheckedInternal(isTethering); + setSwitchCheckedInternal(tetherState != TETHERING_OFF); + setSharedPreferencesInternal(tetherState); mSwitchWidgetController.setEnabled(!mDataSaverEnabled); if (mListener != null) { - mListener.onTetherStateUpdated(isTethering); + mListener.onTetherStateUpdated(tetherState != TETHERING_OFF); } } @@ -172,32 +189,54 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe mSwitchWidgetController.startListening(); } - private boolean isTethering() { - String[] tethered = mConnectivityManager.getTetheredIfaces(); - return isTethering(tethered); + 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 boolean isTethering(String[] tethered) { - if (tethered != null && tethered.length != 0) { - return true; + private @TetheringState int getTetheringState(@Nullable String[] tethered) { + int tetherState = TETHERING_OFF; + if (tethered == null) { + tethered = mConnectivityManager.getTetheredIfaces(); } if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) { - return true; + tetherState |= TETHERING_WIFI_ON; } final BluetoothPan pan = mBluetoothPan.get(); + if (pan != null && pan.isTetheringOn()) { + tetherState |= TETHERING_BLUETOOTH_ON; + } - return pan != null && pan.isTetheringOn(); + String[] usbRegexs = mConnectivityManager.getTetherableUsbRegexs(); + for (String s : tethered) { + for (String regex : usbRegexs) { + if (s.matches(regex)) { + return tetherState | TETHERING_USB_ON; + } + } + } + + return tetherState; } @Override public boolean onSwitchToggled(boolean isChecked) { - if (isChecked && !isTethering()) { + if (isChecked && getTetheringState(null /* tethered */) == TETHERING_OFF) { startTether(); } - if (!isChecked && isTethering()) { + if (!isChecked && getTetheringState(null /* tethered */) != TETHERING_OFF) { stopTether(); } return true; diff --git a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java index 3aa82fe7c9a..22e35fdd550 100644 --- a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java +++ b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java @@ -69,6 +69,7 @@ public class TetherEnablerTest { private SwitchBar mSwitchBar; private TetherEnabler mEnabler; private SwitchWidgetController mSwitchWidgetController; + private static final String[] USB_TETHERED = {"usb"}; @Before public void setUp() { @@ -84,9 +85,13 @@ public class TetherEnablerTest { when(context.getSystemService(Context.NETWORK_POLICY_SERVICE)).thenReturn( mNetworkPolicyManager); when(mConnectivityManager.getTetherableIfaces()).thenReturn(new String[0]); + 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)); } @@ -103,7 +108,8 @@ public class TetherEnablerTest { @Test public void lifecycle_onStart_setCheckedCorrectly() { - when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{""}); + when(mConnectivityManager.getTetheredIfaces()).thenReturn(USB_TETHERED); + when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(USB_TETHERED); mEnabler.onStart(); assertThat(mSwitchBar.isChecked()).isTrue(); @@ -188,7 +194,7 @@ public class TetherEnablerTest { mSwitchWidgetController.setListener(mEnabler); mSwitchWidgetController.startListening(); - mEnabler.updateState(null/*tethered*/); + mEnabler.updateState(null /* tethered */); verify(mEnabler, never()).onSwitchToggled(anyBoolean()); } @@ -211,4 +217,28 @@ public class TetherEnablerTest { mEnabler.updateState(new String[]{""}); verify(mSwitchBar).setEnabled(true); } + + @Test + public void updateState_onSharedPreferencesChangeNeverCalled() { + mSharedPreferences.registerOnSharedPreferenceChangeListener(mEnabler); + mSwitchWidgetController.setListener(mEnabler); + mSwitchWidgetController.startListening(); + + mEnabler.updateState(null /* tethered */); + verify(mEnabler, never()).onSharedPreferenceChanged(eq(mSharedPreferences), any()); + verify(mEnabler, never()).onSharedPreferenceChanged(eq(mSharedPreferences), any()); + } + + @Test + public void updateState_setSharedPreferencesOnlyWhenNeeded() { + mSwitchWidgetController.setListener(mEnabler); + mSwitchWidgetController.startListening(); + + mEnabler.updateState(null /* tethered */); + verify(mSharedPreferences, never()).edit(); + + when(mConnectivityManager.getTetherableUsbRegexs()).thenReturn(USB_TETHERED); + mSharedPreferences.registerOnSharedPreferenceChangeListener(mEnabler); + mEnabler.updateState(USB_TETHERED); + } }