import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
import android.content.Context;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
/**
private static final boolean DEBUG = Utils.D;
private Context mContext;
- private final List<CachedBluetoothDevice> mCachedDevices =
- new ArrayList<CachedBluetoothDevice>();
private final LocalBluetoothManager mBtManager;
+ @VisibleForTesting
+ final List<CachedBluetoothDevice> mCachedDevices =
+ new ArrayList<CachedBluetoothDevice>();
+ // Contains the list of hearing aid devices that should not be shown in the UI.
+ @VisibleForTesting
+ final List<CachedBluetoothDevice> mHearingAidDevicesNotAddedInCache
+ = new ArrayList<CachedBluetoothDevice>();
+ // Maintains a list of devices which are added in mCachedDevices and have hiSyncIds.
+ @VisibleForTesting
+ final Map<Long, CachedBluetoothDevice> mCachedDevicesMapForHearingAids
+ = new HashMap<Long, CachedBluetoothDevice>();
+
CachedBluetoothDeviceManager(Context context, LocalBluetoothManager localBtManager) {
mContext = context;
mBtManager = localBtManager;
return cachedDevice;
}
}
+ for (CachedBluetoothDevice notCachedDevice : mHearingAidDevicesNotAddedInCache) {
+ if (notCachedDevice.getDevice().equals(device)) {
+ return notCachedDevice;
+ }
+ }
return null;
}
BluetoothDevice device) {
CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter,
profileManager, device);
- synchronized (mCachedDevices) {
- mCachedDevices.add(newDevice);
- mBtManager.getEventManager().dispatchDeviceAdded(newDevice);
+ if (profileManager.getHearingAidProfile() != null
+ && profileManager.getHearingAidProfile().getHiSyncId(newDevice.getDevice())
+ != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+ newDevice.setHiSyncId(profileManager.getHearingAidProfile()
+ .getHiSyncId(newDevice.getDevice()));
}
+ // Just add one of the hearing aids from a pair in the list that is shown in the UI.
+ if (isPairAddedInCache(newDevice.getHiSyncId())) {
+ synchronized (this) {
+ mHearingAidDevicesNotAddedInCache.add(newDevice);
+ }
+ } else {
+ synchronized (this) {
+ mCachedDevices.add(newDevice);
+ if (newDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
+ && !mCachedDevicesMapForHearingAids.containsKey(newDevice.getHiSyncId())) {
+ mCachedDevicesMapForHearingAids.put(newDevice.getHiSyncId(), newDevice);
+ }
+ mBtManager.getEventManager().dispatchDeviceAdded(newDevice);
+ }
+ }
+
return newDevice;
}
/**
+ * Returns true if the one of the two hearing aid devices is already cached for UI.
+ *
+ * @param long hiSyncId
+ * @return {@code True} if one of the two hearing aid devices is is already cached for UI.
+ */
+ private synchronized boolean isPairAddedInCache(long hiSyncId) {
+ if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+ return false;
+ }
+ if(mCachedDevicesMapForHearingAids.containsKey(hiSyncId)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns device summary of the pair of the hearing aid passed as the parameter.
+ *
+ * @param CachedBluetoothDevice device
+ * @return Device summary, or if the pair does not exist or if its not a hearing aid,
+ * then {@code null}.
+ */
+ public synchronized String getHearingAidPairDeviceSummary(CachedBluetoothDevice device) {
+ String pairDeviceSummary = null;
+ if (device.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+ for (CachedBluetoothDevice hearingAidDevice : mHearingAidDevicesNotAddedInCache) {
+ if (hearingAidDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
+ && hearingAidDevice.getHiSyncId() == device.getHiSyncId()) {
+ pairDeviceSummary = hearingAidDevice.getConnectionSummary();
+ }
+ }
+ }
+ return pairDeviceSummary;
+ }
+
+ /**
+ * Adds the 2nd hearing aid in a pair in a list that maintains the hearing aids that are
+ * not dispalyed in the UI.
+ *
+ * @param CachedBluetoothDevice device
+ */
+ public synchronized void addDeviceNotaddedInMap(CachedBluetoothDevice device) {
+ mHearingAidDevicesNotAddedInCache.add(device);
+ }
+
+ /**
+ * Updates the Hearing Aid devices; specifically the HiSyncId's. This routine is called when the
+ * Hearing Aid Service is connected and the HiSyncId's are now available.
+ * @param LocalBluetoothProfileManager profileManager
+ */
+ public synchronized void updateHearingAidsDevices(LocalBluetoothProfileManager profileManager) {
+ HearingAidProfile profileProxy = profileManager.getHearingAidProfile();
+ if (profileProxy == null) {
+ log("updateHearingAidsDevices: getHearingAidProfile() is null");
+ return;
+ }
+ for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+ if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+ continue;
+ }
+
+ long newHiSyncId = profileProxy.getHiSyncId(cachedDevice.getDevice());
+
+ if (newHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+ cachedDevice.setHiSyncId(newHiSyncId);
+ onHiSyncIdChanged(newHiSyncId);
+ }
+ }
+ }
+
+ /**
* Attempts to get the name of a remote device, otherwise returns the address.
*
* @param device The remote device.
}
public synchronized void clearNonBondedDevices() {
- for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
- CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
- if (cachedDevice.getBondState() == BluetoothDevice.BOND_NONE) {
- mCachedDevices.remove(i);
- }
- }
+
+ mCachedDevicesMapForHearingAids.entrySet().removeIf(entries
+ -> entries.getValue().getBondState() == BluetoothDevice.BOND_NONE);
+
+ mCachedDevices.removeIf(cachedDevice
+ -> cachedDevice.getBondState() == BluetoothDevice.BOND_NONE);
+
+ mHearingAidDevicesNotAddedInCache.removeIf(hearingAidDevice
+ -> hearingAidDevice.getBondState() == BluetoothDevice.BOND_NONE);
}
public synchronized void onScanningStateChanged(boolean started) {
if (!started) return;
-
// If starting a new scan, clear old visibility
// Iterate in reverse order since devices may be removed.
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
cachedDevice.setJustDiscovered(false);
}
+ for (int i = mHearingAidDevicesNotAddedInCache.size() - 1; i >= 0; i--) {
+ CachedBluetoothDevice notCachedDevice = mHearingAidDevicesNotAddedInCache.get(i);
+ notCachedDevice.setJustDiscovered(false);
+ }
}
public synchronized void onBtClassChanged(BluetoothDevice device) {
if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
cachedDevice.setJustDiscovered(false);
mCachedDevices.remove(i);
+ if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
+ && mCachedDevicesMapForHearingAids.containsKey(cachedDevice.getHiSyncId()))
+ {
+ mCachedDevicesMapForHearingAids.remove(cachedDevice.getHiSyncId());
+ }
} else {
// For bonded devices, we need to clear the connection status so that
// when BT is enabled next time, device connection status shall be retrieved
cachedDevice.clearProfileConnectionState();
}
}
+ for (int i = mHearingAidDevicesNotAddedInCache.size() - 1; i >= 0; i--) {
+ CachedBluetoothDevice notCachedDevice = mHearingAidDevicesNotAddedInCache.get(i);
+ if (notCachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
+ notCachedDevice.setJustDiscovered(false);
+ mHearingAidDevicesNotAddedInCache.remove(i);
+ } else {
+ // For bonded devices, we need to clear the connection status so that
+ // when BT is enabled next time, device connection status shall be retrieved
+ // by making a binder call.
+ notCachedDevice.clearProfileConnectionState();
+ }
+ }
}
}
}
}
+ public synchronized void onHiSyncIdChanged(long hiSyncId) {
+ int firstMatchedIndex = -1;
+
+ for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+ CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+ if (cachedDevice.getHiSyncId() == hiSyncId) {
+ if (firstMatchedIndex != -1) {
+ /* Found the second one */
+ mCachedDevices.remove(i);
+ mHearingAidDevicesNotAddedInCache.add(cachedDevice);
+ // 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
+ // 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);
+ break;
+ } else {
+ mCachedDevicesMapForHearingAids.put(hiSyncId, cachedDevice);
+ firstMatchedIndex = i;
+ }
+ }
+ }
+ }
+
+ public synchronized void onDeviceUnpaired(CachedBluetoothDevice device) {
+ final long hiSyncId = device.getHiSyncId();
+
+ if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID) return;
+
+ for (int i = mHearingAidDevicesNotAddedInCache.size() - 1; i >= 0; i--) {
+ CachedBluetoothDevice cachedDevice = mHearingAidDevicesNotAddedInCache.get(i);
+ if (cachedDevice.getHiSyncId() == hiSyncId) {
+ // TODO: Look for more cleanups on unpairing the device.
+ mHearingAidDevicesNotAddedInCache.remove(i);
+ if (device == cachedDevice) continue;
+ cachedDevice.unpair();
+ }
+ }
+ }
+
private void log(String msg) {
if (DEBUG) {
Log.d(TAG, msg);
public class CachedBluetoothDeviceManagerTest {
private final static String DEVICE_NAME_1 = "TestName_1";
private final static String DEVICE_NAME_2 = "TestName_2";
+ private final static String DEVICE_NAME_3 = "TestName_3";
private final static String DEVICE_ALIAS_1 = "TestAlias_1";
private final static String DEVICE_ALIAS_2 = "TestAlias_2";
+ private final static String DEVICE_ALIAS_3 = "TestAlias_3";
private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
+ private final static String DEVICE_ADDRESS_3 = "AA:BB:CC:DD:EE:33";
+ private final static String DEVICE_SUMMARY_1 = "summary 1";
+ private final static String DEVICE_SUMMARY_2 = "summary 2";
+ private final static String DEVICE_SUMMARY_3 = "summary 3";
+ private final static long HISYNCID1 = 10;
+ private final static long HISYNCID2 = 11;
private final BluetoothClass DEVICE_CLASS_1 =
new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
private final BluetoothClass DEVICE_CLASS_2 =
private BluetoothDevice mDevice1;
@Mock
private BluetoothDevice mDevice2;
+ @Mock
+ private BluetoothDevice mDevice3;
+ private CachedBluetoothDevice mCachedDevice1;
+ private CachedBluetoothDevice mCachedDevice2;
+ private CachedBluetoothDevice mCachedDevice3;
private CachedBluetoothDeviceManager mCachedDeviceManager;
private Context mContext;
private String[] mActiveDeviceStringsArray;
mContext = RuntimeEnvironment.application;
when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
+ when(mDevice3.getAddress()).thenReturn(DEVICE_ADDRESS_3);
when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
+ when(mDevice3.getName()).thenReturn(DEVICE_NAME_3);
when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
+ when(mDevice3.getAliasName()).thenReturn(DEVICE_ALIAS_3);
when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS_1);
when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
+ when(mDevice3.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
when(mLocalAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
when(mPanProfile.isProfileReady()).thenReturn(true);
when(mHearingAidProfile.isProfileReady()).thenReturn(true);
mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
+ mCachedDevice1 = spy(
+ new CachedBluetoothDevice(mContext, mLocalAdapter, mLocalProfileManager, mDevice1));
+ mCachedDevice2 = spy(
+ new CachedBluetoothDevice(mContext, mLocalAdapter, mLocalProfileManager, mDevice2));
+ mCachedDevice3 = spy(
+ new CachedBluetoothDevice(mContext, mLocalAdapter, mLocalProfileManager, mDevice3));
}
/**
}
/**
+ * Test to verify clearNonBondedDevices() for hearing aids.
+ */
+ @Test
+ public void testClearNonBondedDevices_HearingAids_nonBondedHAsClearedFromCachedDevicesMap() {
+ when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+
+ mCachedDevice1.setHiSyncId(HISYNCID1);
+ mCachedDevice2.setHiSyncId(HISYNCID2);
+ mCachedDeviceManager.mCachedDevicesMapForHearingAids.put(HISYNCID1, mCachedDevice1);
+ mCachedDeviceManager.mCachedDevicesMapForHearingAids.put(HISYNCID2, mCachedDevice2);
+
+ mCachedDeviceManager.clearNonBondedDevices();
+
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
+ .doesNotContain(mCachedDevice2);
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
+ .contains(mCachedDevice1);
+ }
+
+ /**
+ * Test to verify onHiSyncIdChanged() for hearing aid devices with same HiSyncId.
+ */
+ @Test
+ public void testOnDeviceAdded_sameHiSyncId_populateInDifferentLists() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice2);
+ assertThat(cachedDevice2).isNotNull();
+
+ // 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);
+
+ // Since both devices have the same hiSyncId, one should remain in mCachedDevices
+ // and the other should be removed from mCachedDevices and get added in
+ // mHearingAidDevicesNotAddedInCache. The one that is in mCachedDevices should also be
+ // added in mCachedDevicesMapForHearingAids.
+ assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
+ 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);
+ }
+
+ /**
+ * Test to verify onHiSyncIdChanged() for hearing aid devices with different HiSyncId.
+ */
+ @Test
+ public void testOnDeviceAdded_differentHiSyncId_populateInSameList() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice2);
+ assertThat(cachedDevice2).isNotNull();
+
+ // 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(HISYNCID2);
+ mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
+ mCachedDeviceManager.onHiSyncIdChanged(HISYNCID2);
+
+ // Since both devices do not have same hiSyncId, they should remain in mCachedDevices and
+ // also be added in mCachedDevicesMapForHearingAids.
+ assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(2);
+ Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+ assertThat(devices).contains(cachedDevice2);
+ assertThat(devices).contains(cachedDevice1);
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
+ .contains(cachedDevice1);
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
+ .contains(cachedDevice2);
+ }
+
+ /**
+ * Test to verify OnDeviceUnpaired() for a paired hearing Aid device pair.
+ */
+ @Test
+ public void testOnDeviceUnpaired_bothHearingAidsPaired_removesItsPairFromList() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice2);
+ assertThat(cachedDevice2).isNotNull();
+
+ cachedDevice1.setHiSyncId(HISYNCID1);
+ cachedDevice2.setHiSyncId(HISYNCID1);
+ mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
+
+ // Check if one device is in mCachedDevices and one in mHearingAidDevicesNotAddedInCache.
+ Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+ assertThat(devices).contains(cachedDevice2);
+ assertThat(devices).doesNotContain(cachedDevice1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
+ .doesNotContain(cachedDevice2);
+
+ // Call onDeviceUnpaired for the one in mCachedDevices.
+ mCachedDeviceManager.onDeviceUnpaired(cachedDevice2);
+
+ // Check if its pair is removed from mHearingAidDevicesNotAddedInCache.
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
+ .doesNotContain(cachedDevice1);
+ }
+
+ /**
+ * Test to verify OnDeviceUnpaired() for paired hearing Aid devices which are not a pair.
+ */
+ @Test
+ public void testOnDeviceUnpaired_bothHearingAidsNotPaired_doesNotRemoveAnyDeviceFromList() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice2);
+ assertThat(cachedDevice2).isNotNull();
+ CachedBluetoothDevice cachedDevice3 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice3);
+ assertThat(cachedDevice2).isNotNull();
+
+ cachedDevice1.setHiSyncId(HISYNCID1);
+ cachedDevice2.setHiSyncId(HISYNCID1);
+ cachedDevice3.setHiSyncId(HISYNCID2);
+ mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
+ mCachedDeviceManager.onHiSyncIdChanged(HISYNCID2);
+
+ // Check if one device is in mCachedDevices and one in mHearingAidDevicesNotAddedInCache.
+ Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+ assertThat(devices).contains(cachedDevice2);
+ assertThat(devices).contains(cachedDevice3);
+ assertThat(devices).doesNotContain(cachedDevice1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
+ .doesNotContain(cachedDevice2);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
+ .doesNotContain(cachedDevice3);
+
+ // Call onDeviceUnpaired for the one in mCachedDevices with no pair.
+ mCachedDeviceManager.onDeviceUnpaired(cachedDevice3);
+
+ // Check if no list is changed.
+ devices = mCachedDeviceManager.getCachedDevicesCopy();
+ assertThat(devices).contains(cachedDevice2);
+ assertThat(devices).contains(cachedDevice3);
+ assertThat(devices).doesNotContain(cachedDevice1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
+ .doesNotContain(cachedDevice2);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
+ .doesNotContain(cachedDevice3);
+ }
+
+ /**
+ * Test to verify addDevice() for hearing aid devices with same HiSyncId.
+ */
+ @Test
+ public void testAddDevice_hearingAidDevicesWithSameHiSyncId_populateInDifferentLists() {
+ doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
+ .getHearingAidProfile();
+ doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
+ doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
+
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ // The first hearing aid device should be populated in mCachedDevice and
+ // mCachedDevicesMapForHearingAids.
+ assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
+ .contains(cachedDevice1);
+
+ CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice2);
+ assertThat(cachedDevice2).isNotNull();
+ // The second hearing aid device should be populated in mHearingAidDevicesNotAddedInCache.
+ assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
+ }
+
+ /**
+ * Test to verify addDevice() for hearing aid devices with different HiSyncId.
+ */
+ @Test
+ public void testAddDevice_hearingAidDevicesWithDifferentHiSyncId_populateInSameList() {
+ doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
+ .getHearingAidProfile();
+ doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
+ doAnswer((invocation) -> HISYNCID2).when(mHearingAidProfile).getHiSyncId(mDevice2);
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ // The first hearing aid device should be populated in mCachedDevice and
+ // mCachedDevicesMapForHearingAids.
+ assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
+ .contains(cachedDevice1);
+
+ CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice2);
+ assertThat(cachedDevice2).isNotNull();
+ // The second hearing aid device should also be populated in mCachedDevice
+ // and mCachedDevicesMapForHearingAids as its not a pair of the first one.
+ assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
+ assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(2);
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
+ .contains(cachedDevice1);
+ assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
+ .contains(cachedDevice2);
+ }
+
+ /**
+ * Test to verify getHearingAidPairDeviceSummary() for hearing aid devices with same HiSyncId.
+ */
+ @Test
+ public void testGetHearingAidPairDeviceSummary_bothHearingAidsPaired_returnsSummaryOfPair() {
+ mCachedDevice1.setHiSyncId(HISYNCID1);
+ mCachedDevice2.setHiSyncId(HISYNCID1);
+ mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+ mCachedDeviceManager.mHearingAidDevicesNotAddedInCache.add(mCachedDevice2);
+ doAnswer((invocation) -> DEVICE_SUMMARY_1).when(mCachedDevice1).getConnectionSummary();
+ doAnswer((invocation) -> DEVICE_SUMMARY_2).when(mCachedDevice2).getConnectionSummary();
+
+ assertThat(mCachedDeviceManager.getHearingAidPairDeviceSummary(mCachedDevice1))
+ .isEqualTo(DEVICE_SUMMARY_2);
+ }
+
+ /**
+ * Test to verify getHearingAidPairDeviceSummary() for hearing aid devices with different
+ * HiSyncId.
+ */
+ @Test
+ public void testGetHearingAidPairDeviceSummary_bothHearingAidsNotPaired_returnsNull() {
+ mCachedDevice1.setHiSyncId(HISYNCID1);
+ mCachedDevice2.setHiSyncId(HISYNCID2);
+ mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+ mCachedDeviceManager.mHearingAidDevicesNotAddedInCache.add(mCachedDevice2);
+ doAnswer((invocation) -> DEVICE_SUMMARY_1).when(mCachedDevice1).getConnectionSummary();
+ doAnswer((invocation) -> DEVICE_SUMMARY_2).when(mCachedDevice2).getConnectionSummary();
+
+ assertThat(mCachedDeviceManager.getHearingAidPairDeviceSummary(mCachedDevice1))
+ .isEqualTo(null);
+ }
+
+ /**
+ * Test to verify updateHearingAidsDevices().
+ */
+ @Test
+ public void testUpdateHearingAidDevices_hiSyncIdAvailable_setsHiSyncId() {
+ doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
+ .getHearingAidProfile();
+ doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
+ mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+ mCachedDeviceManager.updateHearingAidsDevices(mLocalProfileManager);
+
+ // Assert that the mCachedDevice1 has an updated HiSyncId.
+ assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1);
+ }
+
+ /**
* Test to verify onBtClassChanged().
*/
@Test