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
This commit is contained in:
Ted Wang
2020-09-01 14:45:46 +08:00
parent e8b877e3ee
commit 47f2ebb1af
2 changed files with 150 additions and 33 deletions

View File

@@ -154,9 +154,7 @@ public class TetherSettings extends RestrictedSettingsFragment
BluetoothProfile.PAN); BluetoothProfile.PAN);
} }
mUsbTether = (SwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS); setupTetherPreference();
mBluetoothTether = (SwitchPreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING);
mEthernetTether = (SwitchPreference) findPreference(KEY_ENABLE_ETHERNET_TETHERING);
setFooterPreferenceTitle(); setFooterPreferenceTitle();
mDataSaverBackend.addListener(this); mDataSaverBackend.addListener(this);
@@ -208,6 +206,13 @@ public class TetherSettings extends RestrictedSettingsFragment
super.onDestroy(); 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 @Override
public void onDataSaverChanged(boolean isDataSaving) { public void onDataSaverChanged(boolean isDataSaving) {
mDataSaverEnabled = isDataSaving; mDataSaverEnabled = isDataSaving;
@@ -281,6 +286,8 @@ public class TetherSettings extends RestrictedSettingsFragment
} }
} }
updateState(); updateState();
} else if (action.equals(BluetoothPan.ACTION_TETHERING_STATE_CHANGED)) {
updateState();
} }
} }
} }
@@ -297,32 +304,13 @@ public class TetherSettings extends RestrictedSettingsFragment
return; return;
} }
final Activity activity = getActivity();
mStartTetheringCallback = new OnStartTetheringCallback(this); mStartTetheringCallback = new OnStartTetheringCallback(this);
mTetheringEventCallback = new TetheringEventCallback(); mTetheringEventCallback = new TetheringEventCallback();
mTm.registerTetheringEventCallback(new HandlerExecutor(mHandler), mTetheringEventCallback); mTm.registerTetheringEventCallback(new HandlerExecutor(mHandler), mTetheringEventCallback);
mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState()); mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState());
mTetherChangeReceiver = new TetherChangeReceiver(); registerReceiver();
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);
mEthernetListener = new EthernetListener(); mEthernetListener = new EthernetListener();
if (mEm != null) if (mEm != null)
@@ -348,10 +336,38 @@ public class TetherSettings extends RestrictedSettingsFragment
mEthernetListener = null; 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() { private void updateState() {
String[] available = mCm.getTetherableIfaces(); final ConnectivityManager cm =
String[] tethered = mCm.getTetheredIfaces(); (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
String[] errored = mCm.getTetheringErroredIfaces(); final String[] available = cm.getTetherableIfaces();
final String[] tethered = cm.getTetheredIfaces();
final String[] errored = cm.getTetheringErroredIfaces();
updateState(available, tethered, errored); updateState(available, tethered, errored);
} }
@@ -362,7 +378,8 @@ public class TetherSettings extends RestrictedSettingsFragment
updateEthernetState(available, tethered); updateEthernetState(available, tethered);
} }
private void updateUsbState(String[] available, String[] tethered, @VisibleForTesting
void updateUsbState(String[] available, String[] tethered,
String[] errored) { String[] errored) {
boolean usbAvailable = mUsbConnected && !mMassStorageActive; boolean usbAvailable = mUsbConnected && !mMassStorageActive;
int usbError = ConnectivityManager.TETHER_ERROR_NO_ERROR; 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(); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null) { 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; return;
} }
int btState = adapter.getState();
if (btState == BluetoothAdapter.STATE_TURNING_OFF) { if (btState == BluetoothAdapter.STATE_TURNING_OFF) {
mBluetoothTether.setEnabled(false); mBluetoothTether.setEnabled(false);
} else if (btState == BluetoothAdapter.STATE_TURNING_ON) { } else if (btState == BluetoothAdapter.STATE_TURNING_ON) {
mBluetoothTether.setEnabled(false); mBluetoothTether.setEnabled(false);
} else { } else {
BluetoothPan bluetoothPan = mBluetoothPan.get(); if (btState == BluetoothAdapter.STATE_ON && isBluetoothTetheringOn()) {
if (btState == BluetoothAdapter.STATE_ON && bluetoothPan != null
&& bluetoothPan.isTetheringOn()) {
mBluetoothTether.setChecked(true); mBluetoothTether.setChecked(true);
mBluetoothTether.setEnabled(!mDataSaverEnabled); mBluetoothTether.setEnabled(!mDataSaverEnabled);
} else { } 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 isAvailable = false;
boolean isTethered = false; boolean isTethered = false;

View File

@@ -18,6 +18,8 @@ package com.android.settings;
import static com.google.common.truth.Truth.assertThat; 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.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; 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.verify;
import static org.mockito.Mockito.when; 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.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.util.FeatureFlagUtils; import android.util.FeatureFlagUtils;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
import com.android.settings.core.FeatureFlags; import com.android.settings.core.FeatureFlags;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
@@ -160,6 +170,82 @@ public class TetherSettingsTest {
verify(mockPreference).setTitle(R.string.tethering_footer_info_sta_ap_concurrency); 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<BroadcastReceiver> 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<BroadcastReceiver> 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) { private void setupIsTetherAvailable(boolean returnValue) {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true); when(mConnectivityManager.isTetheringSupported()).thenReturn(true);