Loading src/com/android/settings/network/TetherEnabler.java +53 −14 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); } } Loading @@ -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; } String[] usbRegexs = mConnectivityManager.getTetherableUsbRegexs(); for (String s : tethered) { for (String regex : usbRegexs) { if (s.matches(regex)) { return tetherState | TETHERING_USB_ON; } } } return pan != null && pan.isTetheringOn(); 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; Loading tests/robotests/src/com/android/settings/network/TetherEnablerTest.java +32 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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)); } Loading @@ -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(); Loading Loading @@ -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); } } Loading
src/com/android/settings/network/TetherEnabler.java +53 −14 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); } } Loading @@ -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; } String[] usbRegexs = mConnectivityManager.getTetherableUsbRegexs(); for (String s : tethered) { for (String regex : usbRegexs) { if (s.matches(regex)) { return tetherState | TETHERING_USB_ON; } } } return pan != null && pan.isTetheringOn(); 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; Loading
tests/robotests/src/com/android/settings/network/TetherEnablerTest.java +32 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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)); } Loading @@ -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(); Loading Loading @@ -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); } }