Merge "Fix the Hearing Aids connected state in Settings App" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
aef6efeef5
@@ -505,5 +505,6 @@ public class BluetoothEventManager {
|
||||
callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
|
||||
}
|
||||
}
|
||||
mDeviceManager.onProfileConnectionStateChanged(device, state, bluetoothProfile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settingslib.bluetooth;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothHearingAid;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -323,16 +324,31 @@ public class CachedBluetoothDeviceManager {
|
||||
if (cachedDevice.getHiSyncId() == hiSyncId) {
|
||||
if (firstMatchedIndex != -1) {
|
||||
/* Found the second one */
|
||||
mCachedDevices.remove(i);
|
||||
mHearingAidDevicesNotAddedInCache.add(cachedDevice);
|
||||
int indexToRemoveFromUi;
|
||||
CachedBluetoothDevice deviceToRemoveFromUi;
|
||||
|
||||
// Since the hiSyncIds have been updated for a connected pair of hearing aids,
|
||||
// we remove the entry of one the hearing aids from the UI. Unless the
|
||||
// hiSyncId get updated, the system does not know its a hearing aid, so we add
|
||||
// hiSyncId get updated, the system does not know it is a hearing aid, so we add
|
||||
// both the hearing aids as separate entries in the UI first, then remove one
|
||||
// of them after the hiSyncId is populated.
|
||||
log("onHiSyncIdChanged: removed device=" + cachedDevice + ", with hiSyncId="
|
||||
+ hiSyncId);
|
||||
mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
|
||||
// of them after the hiSyncId is populated. We will choose the device that
|
||||
// is not connected to be removed.
|
||||
if (cachedDevice.isConnected()) {
|
||||
indexToRemoveFromUi = firstMatchedIndex;
|
||||
deviceToRemoveFromUi = mCachedDevices.get(firstMatchedIndex);
|
||||
mCachedDevicesMapForHearingAids.put(hiSyncId, cachedDevice);
|
||||
} else {
|
||||
indexToRemoveFromUi = i;
|
||||
deviceToRemoveFromUi = cachedDevice;
|
||||
mCachedDevicesMapForHearingAids.put(hiSyncId,
|
||||
mCachedDevices.get(firstMatchedIndex));
|
||||
}
|
||||
|
||||
mCachedDevices.remove(indexToRemoveFromUi);
|
||||
mHearingAidDevicesNotAddedInCache.add(deviceToRemoveFromUi);
|
||||
log("onHiSyncIdChanged: removed from UI device=" + deviceToRemoveFromUi
|
||||
+ ", with hiSyncId=" + hiSyncId);
|
||||
mBtManager.getEventManager().dispatchDeviceRemoved(deviceToRemoveFromUi);
|
||||
break;
|
||||
} else {
|
||||
mCachedDevicesMapForHearingAids.put(hiSyncId, cachedDevice);
|
||||
@@ -342,6 +358,72 @@ public class CachedBluetoothDeviceManager {
|
||||
}
|
||||
}
|
||||
|
||||
private CachedBluetoothDevice getHearingAidOtherDevice(CachedBluetoothDevice thisDevice,
|
||||
long hiSyncId) {
|
||||
if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Searched the lists for the other side device with the matching hiSyncId.
|
||||
for (CachedBluetoothDevice notCachedDevice : mHearingAidDevicesNotAddedInCache) {
|
||||
if ((hiSyncId == notCachedDevice.getHiSyncId()) &&
|
||||
(!Objects.equals(notCachedDevice, thisDevice))) {
|
||||
return notCachedDevice;
|
||||
}
|
||||
}
|
||||
|
||||
CachedBluetoothDevice cachedDevice = mCachedDevicesMapForHearingAids.get(hiSyncId);
|
||||
if (!Objects.equals(cachedDevice, thisDevice)) {
|
||||
return cachedDevice;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void hearingAidSwitchDisplayDevice(CachedBluetoothDevice toDisplayDevice,
|
||||
CachedBluetoothDevice toHideDevice, long hiSyncId)
|
||||
{
|
||||
log("hearingAidSwitchDisplayDevice: toDisplayDevice=" + toDisplayDevice
|
||||
+ ", toHideDevice=" + toHideDevice);
|
||||
|
||||
// Remove the "toHideDevice" device from the UI.
|
||||
mHearingAidDevicesNotAddedInCache.add(toHideDevice);
|
||||
mCachedDevices.remove(toHideDevice);
|
||||
mBtManager.getEventManager().dispatchDeviceRemoved(toHideDevice);
|
||||
|
||||
// Add the "toDisplayDevice" device to the UI.
|
||||
mHearingAidDevicesNotAddedInCache.remove(toDisplayDevice);
|
||||
mCachedDevices.add(toDisplayDevice);
|
||||
mCachedDevicesMapForHearingAids.put(hiSyncId, toDisplayDevice);
|
||||
mBtManager.getEventManager().dispatchDeviceAdded(toDisplayDevice);
|
||||
}
|
||||
|
||||
public synchronized void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice,
|
||||
int state, int bluetoothProfile) {
|
||||
if (bluetoothProfile == BluetoothProfile.HEARING_AID
|
||||
&& cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
|
||||
&& cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
|
||||
|
||||
long hiSyncId = cachedDevice.getHiSyncId();
|
||||
|
||||
CachedBluetoothDevice otherDevice = getHearingAidOtherDevice(cachedDevice, hiSyncId);
|
||||
if (otherDevice == null) {
|
||||
// no other side device. Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == BluetoothProfile.STATE_CONNECTED &&
|
||||
mHearingAidDevicesNotAddedInCache.contains(cachedDevice)) {
|
||||
hearingAidSwitchDisplayDevice(cachedDevice, otherDevice, hiSyncId);
|
||||
} else if (state == BluetoothProfile.STATE_DISCONNECTED
|
||||
&& otherDevice.isConnected()) {
|
||||
CachedBluetoothDevice mapDevice = mCachedDevicesMapForHearingAids.get(hiSyncId);
|
||||
if ((mapDevice != null) && (Objects.equals(cachedDevice, mapDevice))) {
|
||||
hearingAidSwitchDisplayDevice(otherDevice, cachedDevice, hiSyncId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void onDeviceUnpaired(CachedBluetoothDevice device) {
|
||||
final long hiSyncId = device.getHiSyncId();
|
||||
|
||||
@@ -353,9 +435,16 @@ public class CachedBluetoothDeviceManager {
|
||||
// TODO: Look for more cleanups on unpairing the device.
|
||||
mHearingAidDevicesNotAddedInCache.remove(i);
|
||||
if (device == cachedDevice) continue;
|
||||
log("onDeviceUnpaired: Unpair device=" + cachedDevice);
|
||||
cachedDevice.unpair();
|
||||
}
|
||||
}
|
||||
|
||||
CachedBluetoothDevice mappedDevice = mCachedDevicesMapForHearingAids.get(hiSyncId);
|
||||
if ((mappedDevice != null) && (!Objects.equals(device, mappedDevice))) {
|
||||
log("onDeviceUnpaired: Unpair mapped device=" + mappedDevice);
|
||||
mappedDevice.unpair();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void dispatchAudioModeChanged() {
|
||||
|
||||
@@ -98,5 +98,8 @@ public class BluetoothEventManagerTest {
|
||||
|
||||
verify(mBluetoothCallback).onProfileConnectionStateChanged(mCachedBluetoothDevice,
|
||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
|
||||
|
||||
verify(mCachedDeviceManager).onProfileConnectionStateChanged(mCachedBluetoothDevice,
|
||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ public class CachedBluetoothDeviceManagerTest {
|
||||
* Test to verify onHiSyncIdChanged() for hearing aid devices with same HiSyncId.
|
||||
*/
|
||||
@Test
|
||||
public void testOnDeviceAdded_sameHiSyncId_populateInDifferentLists() {
|
||||
public void testOnHiSyncIdChanged_sameHiSyncId_populateInDifferentLists() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
|
||||
mLocalProfileManager, mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
@@ -261,16 +261,53 @@ public class CachedBluetoothDeviceManagerTest {
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
|
||||
Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
|
||||
assertThat(devices).contains(cachedDevice2);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
|
||||
.contains(cachedDevice2);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids)
|
||||
.containsKey(HISYNCID1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify onHiSyncIdChanged() for 2 hearing aid devices with same HiSyncId but one
|
||||
* device is connected and other is disconnected. The connected device should be chosen.
|
||||
*/
|
||||
@Test
|
||||
public void testOnHiSyncIdChanged_sameHiSyncIdAndOneConnected_chooseConnectedDevice() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
|
||||
mLocalProfileManager, mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
|
||||
mLocalProfileManager, mDevice2);
|
||||
assertThat(cachedDevice2).isNotNull();
|
||||
cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
|
||||
cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
|
||||
|
||||
/* Device 1 is connected and Device 2 is disconnected */
|
||||
when(mHearingAidProfile.getConnectionStatus(mDevice1)).
|
||||
thenReturn(BluetoothProfile.STATE_CONNECTED);
|
||||
when(mHearingAidProfile.getConnectionStatus(mDevice2)).
|
||||
thenReturn(BluetoothProfile.STATE_DISCONNECTED);
|
||||
|
||||
// Since both devices do not have hiSyncId, they should be added in mCachedDevices.
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
|
||||
|
||||
cachedDevice1.setHiSyncId(HISYNCID1);
|
||||
cachedDevice2.setHiSyncId(HISYNCID1);
|
||||
mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
|
||||
|
||||
// Only the connected device, device 1, should be visible to UI.
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
|
||||
containsExactly(HISYNCID1, cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).
|
||||
containsExactly(cachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify onHiSyncIdChanged() for hearing aid devices with different HiSyncId.
|
||||
*/
|
||||
@Test
|
||||
public void testOnDeviceAdded_differentHiSyncId_populateInSameList() {
|
||||
public void testOnHiSyncIdChanged_differentHiSyncId_populateInSameList() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
|
||||
mLocalProfileManager, mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
@@ -302,6 +339,153 @@ public class CachedBluetoothDeviceManagerTest {
|
||||
.contains(cachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify onProfileConnectionStateChanged() for single hearing aid device connection.
|
||||
*/
|
||||
@Test
|
||||
public void testOnProfileConnectionStateChanged_singleDeviceConnected_visible() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
|
||||
mLocalProfileManager, mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
|
||||
|
||||
// Since both devices do not have hiSyncId, they should be added in mCachedDevices.
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
|
||||
|
||||
cachedDevice1.setHiSyncId(HISYNCID1);
|
||||
mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
|
||||
|
||||
// Connect the Device 1
|
||||
mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
|
||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
|
||||
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
|
||||
containsExactly(HISYNCID1, cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
|
||||
|
||||
// Disconnect the Device 1
|
||||
mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
|
||||
BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.HEARING_AID);
|
||||
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
|
||||
containsExactly(HISYNCID1, cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify onProfileConnectionStateChanged() for two hearing aid devices where both
|
||||
* devices are disconnected and they get connected.
|
||||
*/
|
||||
@Test
|
||||
public void testOnProfileConnectionStateChanged_twoDevicesConnected_oneDeviceVisible() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
|
||||
mLocalProfileManager, mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
|
||||
mLocalProfileManager, mDevice2);
|
||||
assertThat(cachedDevice2).isNotNull();
|
||||
cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
|
||||
cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
|
||||
when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
|
||||
// Since both devices do not have hiSyncId, they should be added in mCachedDevices.
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
|
||||
|
||||
cachedDevice1.setHiSyncId(HISYNCID1);
|
||||
cachedDevice2.setHiSyncId(HISYNCID1);
|
||||
mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
|
||||
|
||||
// There should be one cached device but can be either one.
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
|
||||
|
||||
// Connect the Device 1
|
||||
mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
|
||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
|
||||
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
|
||||
containsExactly(HISYNCID1, cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice2);
|
||||
assertThat(mCachedDeviceManager.mCachedDevices).contains(cachedDevice1);
|
||||
|
||||
when(mHearingAidProfile.getConnectionStatus(mDevice1)).
|
||||
thenReturn(BluetoothProfile.STATE_CONNECTED);
|
||||
when(mHearingAidProfile.getConnectionStatus(mDevice2)).
|
||||
thenReturn(BluetoothProfile.STATE_DISCONNECTED);
|
||||
|
||||
// Connect the Device 2
|
||||
mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice2,
|
||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
|
||||
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevices).hasSize(1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify onProfileConnectionStateChanged() for two hearing aid devices where both
|
||||
* devices are connected and they get disconnected.
|
||||
*/
|
||||
@Test
|
||||
public void testOnProfileConnectionStateChanged_twoDevicesDisconnected_oneDeviceVisible() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
|
||||
mLocalProfileManager, mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
|
||||
mLocalProfileManager, mDevice2);
|
||||
assertThat(cachedDevice2).isNotNull();
|
||||
cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
|
||||
cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
|
||||
|
||||
when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mHearingAidProfile.getConnectionStatus(mDevice1)).
|
||||
thenReturn(BluetoothProfile.STATE_CONNECTED);
|
||||
when(mHearingAidProfile.getConnectionStatus(mDevice2)).
|
||||
thenReturn(BluetoothProfile.STATE_CONNECTED);
|
||||
|
||||
// Since both devices do not have hiSyncId, they should be added in mCachedDevices.
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
|
||||
|
||||
cachedDevice1.setHiSyncId(HISYNCID1);
|
||||
cachedDevice2.setHiSyncId(HISYNCID1);
|
||||
mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
|
||||
|
||||
/* Disconnect the Device 1 */
|
||||
mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
|
||||
BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.HEARING_AID);
|
||||
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice2);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevices).contains(cachedDevice2);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids)
|
||||
.containsExactly(HISYNCID1, cachedDevice2);
|
||||
|
||||
when(mHearingAidProfile.getConnectionStatus(mDevice1)).
|
||||
thenReturn(BluetoothProfile.STATE_DISCONNECTED);
|
||||
when(mHearingAidProfile.getConnectionStatus(mDevice2)).
|
||||
thenReturn(BluetoothProfile.STATE_CONNECTED);
|
||||
|
||||
/* Disconnect the Device 2 */
|
||||
mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice2,
|
||||
BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.HEARING_AID);
|
||||
|
||||
assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevices).hasSize(1);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify OnDeviceUnpaired() for a paired hearing Aid device pair.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user