/* * 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 android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHERING_ETHERNET; import static com.android.settings.network.TetherEnabler.TETHERING_BLUETOOTH_ON; import static com.android.settings.network.TetherEnabler.TETHERING_ETHERNET_ON; import static com.android.settings.network.TetherEnabler.TETHERING_OFF; import static com.android.settings.network.TetherEnabler.TETHERING_USB_ON; import static com.android.settings.network.TetherEnabler.TETHERING_WIFI_ON; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothPan; import android.content.Context; 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; 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; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @RunWith(RobolectricTestRunner.class) public class TetherEnablerTest { @Mock private WifiManager mWifiManager; @Mock private ConnectivityManager mConnectivityManager; @Mock private TetheringManager mTetheringManager; @Mock private NetworkPolicyManager mNetworkPolicyManager; @Mock private BluetoothPan mBluetoothPan; @Mock private BluetoothAdapter mBluetoothAdapter; private SwitchBar mSwitchBar; private TetherEnabler mEnabler; private SwitchWidgetController mSwitchWidgetController; private static final String[] USB_TETHERED = {"usb"}; @Before public void setUp() { MockitoAnnotations.initMocks(this); Context context = spy(ApplicationProvider.getApplicationContext()); AtomicReference panReference = spy(AtomicReference.class); mSwitchBar = spy(new SwitchBar(context)); mSwitchWidgetController = spy(new SwitchBarController(mSwitchBar)); when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager); when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn( mConnectivityManager); when(context.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager); when(context.getSystemService(Context.NETWORK_POLICY_SERVICE)).thenReturn( mNetworkPolicyManager); when(mTetheringManager.getTetherableIfaces()).thenReturn(new String[0]); when(mTetheringManager.getTetheredIfaces()).thenReturn(new String[0]); when(mTetheringManager.getTetherableUsbRegexs()).thenReturn(new String[0]); panReference.set(mBluetoothPan); mEnabler = spy(new TetherEnabler(context, mSwitchWidgetController, panReference)); ReflectionHelpers.setField(mEnabler, "mBluetoothAdapter", mBluetoothAdapter); } @Test public void lifecycle_onStart_setCheckedCorrectly() { when(mTetheringManager.getTetheredIfaces()).thenReturn(USB_TETHERED); when(mTetheringManager.getTetherableUsbRegexs()).thenReturn(USB_TETHERED); mEnabler.onStart(); assertThat(mSwitchBar.isChecked()).isTrue(); } @Test public void lifecycle_onStart_shoudRegisterTetheringEventCallback() { mEnabler.onStart(); verify(mTetheringManager).registerTetheringEventCallback(any(), eq(mEnabler.mTetheringEventCallback)); } @Test public void lifecycle_onStop_shouldUnregisterTetheringEventCallback() { mEnabler.onStart(); TetheringManager.TetheringEventCallback callback = mEnabler.mTetheringEventCallback; mEnabler.onStop(); verify(mTetheringManager).unregisterTetheringEventCallback(callback); assertThat(mEnabler.mTetheringEventCallback).isNull(); } @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.startTethering(TetheringManager.TETHERING_WIFI); when(mTetheringManager.getTetheredIfaces()).thenReturn(new String[0]); mEnabler.mOnStartTetheringCallback.onTetheringFailed(); assertThat(mSwitchBar.isChecked()).isFalse(); assertThat(mSwitchBar.isEnabled()).isTrue(); } @Test public void onDataSaverChanged_setsEnabledCorrectly() { mSwitchBar.setEnabled(true); // try to turn data saver on when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(true); mEnabler.onDataSaverChanged(true); assertThat(mSwitchBar.isEnabled()).isFalse(); // lets turn data saver off again when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false); mEnabler.onDataSaverChanged(false); assertThat(mSwitchBar.isEnabled()).isTrue(); } @Test public void onSwitchToggled_onlyStartsWifiTetherWhenNeeded() { doReturn(TETHERING_WIFI_ON).when(mEnabler).getTetheringState(null /* tethered */); mEnabler.onSwitchToggled(true); verify(mConnectivityManager, never()).startTethering(anyInt(), anyBoolean(), any(), any()); doReturn(TETHERING_OFF).when(mEnabler).getTetheringState(null /* tethered */); mEnabler.onSwitchToggled(true); verify(mConnectivityManager).startTethering(eq(TETHERING_WIFI), anyBoolean(), any(), any()); verify(mConnectivityManager, never()).startTethering(eq(TETHERING_USB), anyBoolean(), any(), any()); verify(mConnectivityManager, never()).startTethering(eq(TETHERING_BLUETOOTH), anyBoolean(), any(), any()); verify(mConnectivityManager, never()).startTethering(eq(TETHERING_ETHERNET), anyBoolean(), any(), any()); } @Test public void onSwitchToggled_stopAllTetheringInterfaces() { mEnabler.onStart(); doReturn(TETHERING_WIFI_ON).when(mEnabler).getTetheringState(null /* tethered */); mEnabler.onSwitchToggled(false); verify(mConnectivityManager).stopTethering(TETHERING_WIFI); doReturn(TETHERING_USB_ON).when(mEnabler).getTetheringState(null /* tethered */); mEnabler.onSwitchToggled(false); verify(mConnectivityManager).stopTethering(TETHERING_USB); doReturn(TETHERING_BLUETOOTH_ON).when(mEnabler).getTetheringState(null /* tethered */); mEnabler.onSwitchToggled(false); verify(mConnectivityManager).stopTethering(TETHERING_BLUETOOTH); doReturn(TETHERING_ETHERNET_ON).when(mEnabler).getTetheringState(null /* tethered */); mEnabler.onSwitchToggled(false); verify(mConnectivityManager).stopTethering(TETHERING_ETHERNET); } @Test public void startTethering_startsBluetoothTetherWhenOff() { when(mBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF); 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_BLUETOOTH), anyBoolean(), any(), any()); } @Test public void stopTethering_setBluetoothTetheringStoppedByUserAndUpdateState() { mSwitchWidgetController.setListener(mEnabler); mSwitchWidgetController.startListening(); doReturn(TETHERING_BLUETOOTH_ON).when(mEnabler).getTetheringState(null /* tethered */); mEnabler.stopTethering(TetheringManager.TETHERING_BLUETOOTH); assertThat(mEnabler.mBluetoothTetheringStoppedByUser).isTrue(); verify(mEnabler).updateState(null); } @Test public void updateState_onSwitchToggleNeverCalled() { mSwitchWidgetController.setListener(mEnabler); mSwitchWidgetController.startListening(); mEnabler.updateState(null /* tethered */); verify(mEnabler, never()).onSwitchToggled(anyBoolean()); } @Test public void updateState_shouldEnableSwitchBarNotTethering() { mSwitchWidgetController.setListener(mEnabler); mSwitchWidgetController.startListening(); ReflectionHelpers.setField(mEnabler, "mDataSaverEnabled", false); mEnabler.updateState(null/*tethered*/); verify(mSwitchBar).setEnabled(true); } @Test public void updateState_shouldEnableSwitchBarTethering() { when(mTetheringManager.getTetheredIfaces()).thenReturn(USB_TETHERED); when(mTetheringManager.getTetherableUsbRegexs()).thenReturn(USB_TETHERED); mSwitchWidgetController.setListener(mEnabler); mSwitchWidgetController.startListening(); ReflectionHelpers.setField(mEnabler, "mDataSaverEnabled", false); mEnabler.updateState(null/*tethered*/); verify(mSwitchBar).setEnabled(true); } @Test public void updateState_shouldCallListener() { OnTetherStateUpdateListener listener = mock( OnTetherStateUpdateListener.class); List listeners = new ArrayList<>(); listeners.add(listener); ReflectionHelpers.setField(mEnabler, "mListeners", listeners); mSwitchWidgetController.setListener(mEnabler); mSwitchWidgetController.startListening(); mEnabler.updateState(null /* tethered */); verify(listener).onTetherStateUpdated(anyInt()); } @Test public void addListener_listenerShouldAdded() { OnTetherStateUpdateListener listener = mock( OnTetherStateUpdateListener.class); mEnabler.addListener(listener); assertThat(mEnabler.mListeners).contains(listener); } @Test public void remListener_listenerShouldBeRemoved() { OnTetherStateUpdateListener listener = mock( OnTetherStateUpdateListener.class); mEnabler.removeListener(listener); assertThat(mEnabler.mListeners).doesNotContain(listener); } @Test public void isTethering_shouldReturnCorrectly() { assertThat(TetherEnabler.isTethering(TETHERING_WIFI_ON, TETHERING_WIFI)).isTrue(); assertThat(TetherEnabler.isTethering(~TETHERING_WIFI_ON, TETHERING_WIFI)).isFalse(); assertThat(TetherEnabler.isTethering(TETHERING_USB_ON, TETHERING_USB)).isTrue(); assertThat(TetherEnabler.isTethering(~TETHERING_USB_ON, TETHERING_USB)).isFalse(); assertThat(TetherEnabler.isTethering(TETHERING_BLUETOOTH_ON, TETHERING_BLUETOOTH)).isTrue(); assertThat(TetherEnabler.isTethering(~TETHERING_BLUETOOTH_ON, TETHERING_BLUETOOTH)) .isFalse(); assertThat(TetherEnabler.isTethering(TETHERING_ETHERNET_ON, TETHERING_ETHERNET)).isTrue(); assertThat(TetherEnabler.isTethering(~TETHERING_ETHERNET_ON, TETHERING_ETHERNET)).isFalse(); } }