From 47f2ebb1af7c9268bed98cb9381b51db36a56c2d Mon Sep 17 00:00:00 2001 From: Ted Wang Date: Tue, 1 Sep 2020 14:45:46 +0800 Subject: [PATCH] Update state when there is Bluetooth tethering state changed Monitor Bluetooth Tethering state and update preference when there is Bluetooth tethering state change. Add test case to verify when recieve BluetoothPan.TETHERING_STATE_CHANGED will update bluetooth state Bug: 138688805 Test: make RunSettingsRoboTests Change-Id: I8f468d1d99ed6d87f6cd8305ef56b0d7a5dec95b --- src/com/android/settings/TetherSettings.java | 97 ++++++++++++------- .../android/settings/TetherSettingsTest.java | 86 ++++++++++++++++ 2 files changed, 150 insertions(+), 33 deletions(-) diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index 812ab41bf23..74a0897fc7a 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -154,9 +154,7 @@ public class TetherSettings extends RestrictedSettingsFragment BluetoothProfile.PAN); } - mUsbTether = (SwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS); - mBluetoothTether = (SwitchPreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING); - mEthernetTether = (SwitchPreference) findPreference(KEY_ENABLE_ETHERNET_TETHERING); + setupTetherPreference(); setFooterPreferenceTitle(); mDataSaverBackend.addListener(this); @@ -208,6 +206,13 @@ public class TetherSettings extends RestrictedSettingsFragment super.onDestroy(); } + @VisibleForTesting + void setupTetherPreference() { + mUsbTether = (SwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS); + mBluetoothTether = (SwitchPreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING); + mEthernetTether = (SwitchPreference) findPreference(KEY_ENABLE_ETHERNET_TETHERING); + } + @Override public void onDataSaverChanged(boolean isDataSaving) { mDataSaverEnabled = isDataSaving; @@ -281,6 +286,8 @@ public class TetherSettings extends RestrictedSettingsFragment } } updateState(); + } else if (action.equals(BluetoothPan.ACTION_TETHERING_STATE_CHANGED)) { + updateState(); } } } @@ -297,32 +304,13 @@ public class TetherSettings extends RestrictedSettingsFragment return; } - final Activity activity = getActivity(); mStartTetheringCallback = new OnStartTetheringCallback(this); mTetheringEventCallback = new TetheringEventCallback(); mTm.registerTetheringEventCallback(new HandlerExecutor(mHandler), mTetheringEventCallback); mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState()); - mTetherChangeReceiver = new TetherChangeReceiver(); - IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); - Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter); - - filter = new IntentFilter(); - filter.addAction(UsbManager.ACTION_USB_STATE); - activity.registerReceiver(mTetherChangeReceiver, filter); - - filter = new IntentFilter(); - filter.addAction(Intent.ACTION_MEDIA_SHARED); - filter.addAction(Intent.ACTION_MEDIA_UNSHARED); - filter.addDataScheme("file"); - activity.registerReceiver(mTetherChangeReceiver, filter); - - filter = new IntentFilter(); - filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - activity.registerReceiver(mTetherChangeReceiver, filter); - - if (intent != null) mTetherChangeReceiver.onReceive(activity, intent); + registerReceiver(); mEthernetListener = new EthernetListener(); if (mEm != null) @@ -348,10 +336,38 @@ public class TetherSettings extends RestrictedSettingsFragment mEthernetListener = null; } + @VisibleForTesting + void registerReceiver() { + final Activity activity = getActivity(); + + mTetherChangeReceiver = new TetherChangeReceiver(); + IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); + final Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter); + + filter = new IntentFilter(); + filter.addAction(UsbManager.ACTION_USB_STATE); + activity.registerReceiver(mTetherChangeReceiver, filter); + + filter = new IntentFilter(); + filter.addAction(Intent.ACTION_MEDIA_SHARED); + filter.addAction(Intent.ACTION_MEDIA_UNSHARED); + filter.addDataScheme("file"); + activity.registerReceiver(mTetherChangeReceiver, filter); + + filter = new IntentFilter(); + filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + filter.addAction(BluetoothPan.ACTION_TETHERING_STATE_CHANGED); + activity.registerReceiver(mTetherChangeReceiver, filter); + + if (intent != null) mTetherChangeReceiver.onReceive(activity, intent); + } + private void updateState() { - String[] available = mCm.getTetherableIfaces(); - String[] tethered = mCm.getTetheredIfaces(); - String[] errored = mCm.getTetheringErroredIfaces(); + final ConnectivityManager cm = + (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); + final String[] available = cm.getTetherableIfaces(); + final String[] tethered = cm.getTetheredIfaces(); + final String[] errored = cm.getTetheringErroredIfaces(); updateState(available, tethered, errored); } @@ -362,7 +378,8 @@ public class TetherSettings extends RestrictedSettingsFragment updateEthernetState(available, tethered); } - private void updateUsbState(String[] available, String[] tethered, + @VisibleForTesting + void updateUsbState(String[] available, String[] tethered, String[] errored) { boolean usbAvailable = mUsbConnected && !mMassStorageActive; int usbError = ConnectivityManager.TETHER_ERROR_NO_ERROR; @@ -400,20 +417,33 @@ public class TetherSettings extends RestrictedSettingsFragment } } - private void updateBluetoothState() { + @VisibleForTesting + int getBluetoothState() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter == null) { + return BluetoothAdapter.ERROR; + } + return adapter.getState(); + } + + @VisibleForTesting + boolean isBluetoothTetheringOn() { + final BluetoothPan bluetoothPan = mBluetoothPan.get(); + return bluetoothPan != null && bluetoothPan.isTetheringOn(); + } + + private void updateBluetoothState() { + final int btState = getBluetoothState(); + if (btState == BluetoothAdapter.ERROR) { return; } - int btState = adapter.getState(); + if (btState == BluetoothAdapter.STATE_TURNING_OFF) { mBluetoothTether.setEnabled(false); } else if (btState == BluetoothAdapter.STATE_TURNING_ON) { mBluetoothTether.setEnabled(false); } else { - BluetoothPan bluetoothPan = mBluetoothPan.get(); - if (btState == BluetoothAdapter.STATE_ON && bluetoothPan != null - && bluetoothPan.isTetheringOn()) { + if (btState == BluetoothAdapter.STATE_ON && isBluetoothTetheringOn()) { mBluetoothTether.setChecked(true); mBluetoothTether.setEnabled(!mDataSaverEnabled); } else { @@ -423,7 +453,8 @@ public class TetherSettings extends RestrictedSettingsFragment } } - private void updateEthernetState(String[] available, String[] tethered) { + @VisibleForTesting + void updateEthernetState(String[] available, String[] tethered) { boolean isAvailable = false; boolean isTethered = false; diff --git a/tests/robotests/src/com/android/settings/TetherSettingsTest.java b/tests/robotests/src/com/android/settings/TetherSettingsTest.java index f46ca7a1cd1..be14eda9b99 100644 --- a/tests/robotests/src/com/android/settings/TetherSettingsTest.java +++ b/tests/robotests/src/com/android/settings/TetherSettingsTest.java @@ -18,6 +18,8 @@ package com.android.settings; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -25,20 +27,28 @@ 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.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.wifi.WifiManager; import android.os.UserHandle; import android.os.UserManager; import android.util.FeatureFlagUtils; +import androidx.fragment.app.FragmentActivity; import androidx.preference.Preference; +import androidx.preference.SwitchPreference; import com.android.settings.core.FeatureFlags; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; @@ -160,6 +170,82 @@ public class TetherSettingsTest { verify(mockPreference).setTitle(R.string.tethering_footer_info_sta_ap_concurrency); } + @Test + public void testBluetoothState_updateBluetoothState_bluetoothTetheringStateOn() { + final TetherSettings spyTetherSettings = spy(new TetherSettings()); + when(spyTetherSettings.getContext()).thenReturn(mContext); + final SwitchPreference mockSwitchPreference = mock(SwitchPreference.class); + when(spyTetherSettings.findPreference(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING)) + .thenReturn(mockSwitchPreference); + final FragmentActivity mockActivity = mock(FragmentActivity.class); + when(spyTetherSettings.getActivity()).thenReturn(mockActivity); + final ArgumentCaptor captor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + when(mockActivity.registerReceiver(captor.capture(), any(IntentFilter.class))) + .thenReturn(null); + // Bluetooth tethering state is on + when(spyTetherSettings.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); + when(spyTetherSettings.isBluetoothTetheringOn()).thenReturn(true); + + spyTetherSettings.setupTetherPreference(); + spyTetherSettings.registerReceiver(); + updateOnlyBluetoothState(spyTetherSettings); + + // Simulate Bluetooth tethering state changed + final BroadcastReceiver receiver = captor.getValue(); + final Intent bluetoothTetheringOn = new Intent(BluetoothPan.ACTION_TETHERING_STATE_CHANGED); + bluetoothTetheringOn.putExtra(BluetoothPan.EXTRA_TETHERING_STATE, + BluetoothPan.TETHERING_STATE_ON); + receiver.onReceive(mockActivity, bluetoothTetheringOn); + + verify(mockSwitchPreference).setEnabled(true); + verify(mockSwitchPreference).setChecked(true); + } + + @Test + public void testBluetoothState_updateBluetoothState_bluetoothTetheringStateOff() { + final TetherSettings spyTetherSettings = spy(new TetherSettings()); + when(spyTetherSettings.getContext()).thenReturn(mContext); + final SwitchPreference mockSwitchPreference = mock(SwitchPreference.class); + when(spyTetherSettings.findPreference(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING)) + .thenReturn(mockSwitchPreference); + final FragmentActivity mockActivity = mock(FragmentActivity.class); + when(spyTetherSettings.getActivity()).thenReturn(mockActivity); + final ArgumentCaptor captor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + when(mockActivity.registerReceiver(captor.capture(), any(IntentFilter.class))) + .thenReturn(null); + // Bluetooth tethering state is off + when(spyTetherSettings.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); + when(spyTetherSettings.isBluetoothTetheringOn()).thenReturn(false); + + spyTetherSettings.setupTetherPreference(); + spyTetherSettings.registerReceiver(); + updateOnlyBluetoothState(spyTetherSettings); + + // Simulate Bluetooth tethering state changed + final BroadcastReceiver receiver = captor.getValue(); + final Intent bluetoothTetheringOn = new Intent(BluetoothPan.ACTION_TETHERING_STATE_CHANGED); + bluetoothTetheringOn.putExtra(BluetoothPan.EXTRA_TETHERING_STATE, + BluetoothPan.TETHERING_STATE_ON); + receiver.onReceive(mockActivity, bluetoothTetheringOn); + + verify(mockSwitchPreference).setEnabled(true); + verify(mockSwitchPreference).setChecked(false); + } + + private void updateOnlyBluetoothState(TetherSettings tetherSettings) { + doReturn(mConnectivityManager).when(tetherSettings) + .getSystemService(Context.CONNECTIVITY_SERVICE); + when(mConnectivityManager.getTetherableIfaces()).thenReturn(new String[0]); + when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[0]); + when(mConnectivityManager.getTetheringErroredIfaces()).thenReturn(new String[0]); + doNothing().when(tetherSettings).updateUsbState(any(String[].class), any(String[].class), + any(String[].class)); + doNothing().when(tetherSettings).updateEthernetState(any(String[].class), + any(String[].class)); + } + private void setupIsTetherAvailable(boolean returnValue) { when(mConnectivityManager.isTetheringSupported()).thenReturn(true);