From e45897b462b208c8abdf6e74ac7e34421acc731f Mon Sep 17 00:00:00 2001 From: hughchen Date: Thu, 24 Oct 2019 11:53:36 +0800 Subject: [PATCH] Fix BTHS is still in pairing list after BTHS is connected This CL uses onProfileConnectionStateChanged() to handle the case that bonded device is connected in pairing list. 1. Finish BluetoothPairingDetail page if the bonded device is connected and selected. 2. Remove the devices in BluetoothPairingDetail page if the device is connected. Bug: 142519901 Test: make -j42 RunSettingsRoboTests Change-Id: I51a9f2ebc0b491edb8ea026ff62ec20ae91eee1d --- .../bluetooth/BluetoothPairingDetail.java | 19 ++-- .../DeviceListPreferenceFragment.java | 5 +- .../bluetooth/BluetoothPairingDetailTest.java | 87 +++++++++++++++++-- 3 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java index 45da8f31256..2e0e9b5c2ff 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java @@ -29,9 +29,9 @@ import android.widget.Toast; import androidx.annotation.VisibleForTesting; import com.android.settings.R; -import com.android.settingslib.search.Indexable; import com.android.settingslib.bluetooth.BluetoothDeviceFilter; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.search.Indexable; import com.android.settingslib.widget.FooterPreference; /** @@ -191,12 +191,19 @@ public class BluetoothPairingDetail extends DeviceListPreferenceFragment impleme } @Override - public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { - if (mSelectedDevice != null) { - BluetoothDevice device = cachedDevice.getDevice(); - if (device != null && mSelectedDevice.equals(device) - && state == BluetoothAdapter.STATE_CONNECTED) { + public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state, + int bluetoothProfile) { + // This callback is used to handle the case that bonded device is connected in pairing list. + // 1. If user selected multiple bonded devices in pairing list, after connected + // finish this page. + // 2. If the bonded devices auto connected in paring list, after connected it will be + // removed from paring list. + if (cachedDevice != null && cachedDevice.isConnected()) { + final BluetoothDevice device = cachedDevice.getDevice(); + if (device != null && mSelectedList.contains(device)) { finish(); + } else if (mDevicePreferenceMap.containsKey(cachedDevice)) { + onDeviceDeleted(cachedDevice); } } } diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java index 8a286e411ca..1ad322aab97 100644 --- a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java +++ b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java @@ -35,9 +35,10 @@ import com.android.settingslib.bluetooth.BluetoothDeviceFilter; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.WeakHashMap; +import java.util.List; /** * Parent class for settings fragments that contain a list of Bluetooth @@ -72,6 +73,7 @@ public abstract class DeviceListPreferenceFragment extends final HashMap mDevicePreferenceMap = new HashMap<>(); + final List mSelectedList = new ArrayList<>(); boolean mShowDevicesWithoutNames; @@ -154,6 +156,7 @@ public abstract class DeviceListPreferenceFragment extends BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference; CachedBluetoothDevice device = btPreference.getCachedDevice(); mSelectedDevice = device.getDevice(); + mSelectedList.add(mSelectedDevice); onDevicePreferenceClick(btPreference); return true; } diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java index ac89b5b0027..34bb069f6e8 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java @@ -23,13 +23,16 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doNothing; 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.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.res.Resources; @@ -57,6 +60,7 @@ import org.robolectric.shadow.api.Shadow; @Config(shadows = {ShadowBluetoothAdapter.class}) public class BluetoothPairingDetailTest { private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1"; + private static final String TEST_DEVICE_ADDRESS_B = "00:B1:B1:B1:B1:B1"; @Mock private Resources mResource; @@ -82,6 +86,7 @@ public class BluetoothPairingDetailTest { mFragment = spy(new BluetoothPairingDetail()); doReturn(mContext).when(mFragment).getContext(); doReturn(mResource).when(mFragment).getResources(); + when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS); mAvailableDevicesCategory = spy(new BluetoothProgressCategory(mContext)); mFooterPreference = new FooterPreference(mContext); @@ -218,13 +223,85 @@ public class BluetoothPairingDetailTest { } @Test - public void onConnectionStateChanged_connected_finish() { - mFragment.mSelectedDevice = mBluetoothDevice; - doReturn(mBluetoothDevice).when(mCachedBluetoothDevice).getDevice(); + public void onProfileConnectionStateChanged_deviceInSelectedListAndConnected_finish() { + final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); + mFragment.mSelectedList.add(mBluetoothDevice); + mFragment.mSelectedList.add(device); - mFragment.onConnectionStateChanged(mCachedBluetoothDevice, - BluetoothAdapter.STATE_CONNECTED); + when(mCachedBluetoothDevice.isConnected()).thenReturn(true); + when(mCachedBluetoothDevice.getDevice()).thenReturn(device); + + mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, + BluetoothProfile.A2DP, BluetoothAdapter.STATE_CONNECTED); verify(mFragment).finish(); } + + @Test + public void onProfileConnectionStateChanged_deviceNotInSelectedList_doNothing() { + final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); + mFragment.mSelectedList.add(device); + + when(mCachedBluetoothDevice.isConnected()).thenReturn(true); + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + + mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, + BluetoothProfile.A2DP, BluetoothAdapter.STATE_CONNECTED); + + // not crash + } + + @Test + public void onProfileConnectionStateChanged_deviceDisconnected_doNothing() { + final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); + mFragment.mSelectedList.add(mBluetoothDevice); + mFragment.mSelectedList.add(device); + + when(mCachedBluetoothDevice.isConnected()).thenReturn(false); + when(mCachedBluetoothDevice.getDevice()).thenReturn(device); + + mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, + BluetoothProfile.A2DP, BluetoothAdapter.STATE_DISCONNECTED); + + // not crash + } + + @Test + public void onProfileConnectionStateChanged_deviceInPreferenceMapAndConnected_removed() { + final BluetoothDevicePreference preference = + new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, + true, BluetoothDevicePreference.SortType.TYPE_FIFO); + final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS); + mFragment.mDevicePreferenceMap.put(mCachedBluetoothDevice, preference); + + when(mCachedBluetoothDevice.isConnected()).thenReturn(true); + when(mCachedBluetoothDevice.getDevice()).thenReturn(device); + + mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, + BluetoothProfile.A2DP, BluetoothAdapter.STATE_CONNECTED); + + assertThat(mFragment.mDevicePreferenceMap.size()).isEqualTo(0); + } + + @Test + public void onProfileConnectionStateChanged_deviceNotInPreferenceMap_doNothing() { + final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class); + final BluetoothDevicePreference preference = + new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, + true, BluetoothDevicePreference.SortType.TYPE_FIFO); + final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS); + final BluetoothDevice device2 = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); + mFragment.mDevicePreferenceMap.put(mCachedBluetoothDevice, preference); + + when(mCachedBluetoothDevice.isConnected()).thenReturn(true); + when(mCachedBluetoothDevice.getDevice()).thenReturn(device); + when(cachedDevice.isConnected()).thenReturn(true); + when(cachedDevice.getDevice()).thenReturn(device2); + when(cachedDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS_B); + + mFragment.onProfileConnectionStateChanged(cachedDevice, BluetoothProfile.A2DP, + BluetoothAdapter.STATE_CONNECTED); + + // not crash + } } \ No newline at end of file