Make HearingAid code more generic
-group hearingAid code into HearingAidDeviceManager -add subDevice in CachedBluetoothDevice to store second hearingAid device -add test case Bug: 112735753 Test: make -j42 RunSettingsLibRoboTests Change-Id: I6f554076b3e4e525959aba84e735b15f0e55d9d3
This commit is contained in:
@@ -171,7 +171,6 @@ public class BluetoothEventManager {
|
||||
callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
|
||||
}
|
||||
}
|
||||
mDeviceManager.onProfileConnectionStateChanged(device, state, bluetoothProfile);
|
||||
}
|
||||
|
||||
private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
|
||||
|
||||
@@ -29,6 +29,8 @@ import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -36,8 +38,6 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* CachedBluetoothDevice represents a remote Bluetooth device. It contains
|
||||
* attributes of the device (such as the address, name, RSSI, etc.) and
|
||||
@@ -54,11 +54,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
|
||||
private final Context mContext;
|
||||
private final BluetoothAdapter mLocalAdapter;
|
||||
private final LocalBluetoothProfileManager mProfileManager;
|
||||
private final BluetoothDevice mDevice;
|
||||
BluetoothDevice mDevice;
|
||||
private long mHiSyncId;
|
||||
// Need this since there is no method for getting RSSI
|
||||
private short mRssi;
|
||||
|
||||
short mRssi;
|
||||
// mProfiles and mRemovedProfiles does not do swap() between main and sub device. It is
|
||||
// because current sub device is only for HearingAid and its profile is the same.
|
||||
private final List<LocalBluetoothProfile> mProfiles =
|
||||
Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
@@ -69,7 +70,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
|
||||
// Device supports PANU but not NAP: remove PanProfile after device disconnects from NAP
|
||||
private boolean mLocalNapRoleConnected;
|
||||
|
||||
private boolean mJustDiscovered;
|
||||
boolean mJustDiscovered;
|
||||
|
||||
private int mMessageRejectionCount;
|
||||
|
||||
@@ -92,6 +93,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
|
||||
private boolean mIsActiveDeviceA2dp = false;
|
||||
private boolean mIsActiveDeviceHeadset = false;
|
||||
private boolean mIsActiveDeviceHearingAid = false;
|
||||
// Group second device for Hearing Aid
|
||||
private CachedBluetoothDevice mSubDevice;
|
||||
|
||||
CachedBluetoothDevice(Context context, LocalBluetoothProfileManager profileManager,
|
||||
BluetoothDevice device) {
|
||||
@@ -1064,4 +1067,28 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
|
||||
return hearingAidProfile != null && hearingAidProfile.getConnectionStatus(mDevice) ==
|
||||
BluetoothProfile.STATE_CONNECTED;
|
||||
}
|
||||
|
||||
public CachedBluetoothDevice getSubDevice() {
|
||||
return mSubDevice;
|
||||
}
|
||||
|
||||
public void setSubDevice(CachedBluetoothDevice subDevice) {
|
||||
mSubDevice = subDevice;
|
||||
}
|
||||
|
||||
public void switchSubDeviceContent() {
|
||||
// Backup from main device
|
||||
BluetoothDevice tmpDevice = mDevice;
|
||||
short tmpRssi = mRssi;
|
||||
boolean tmpJustDiscovered = mJustDiscovered;
|
||||
// Set main device from sub device
|
||||
mDevice = mSubDevice.mDevice;
|
||||
mRssi = mSubDevice.mRssi;
|
||||
mJustDiscovered = mSubDevice.mJustDiscovered;
|
||||
// Set sub device from backup
|
||||
mSubDevice.mDevice = tmpDevice;
|
||||
mSubDevice.mRssi = tmpRssi;
|
||||
mSubDevice.mJustDiscovered = tmpJustDiscovered;
|
||||
fetchActiveDevices();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ 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;
|
||||
|
||||
@@ -27,12 +25,8 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
|
||||
@@ -45,20 +39,14 @@ public class CachedBluetoothDeviceManager {
|
||||
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.
|
||||
final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
|
||||
@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>();
|
||||
HearingAidDeviceManager mHearingAidDeviceManager;
|
||||
|
||||
CachedBluetoothDeviceManager(Context context, LocalBluetoothManager localBtManager) {
|
||||
mContext = context;
|
||||
mBtManager = localBtManager;
|
||||
mHearingAidDeviceManager = new HearingAidDeviceManager(localBtManager, mCachedDevices);
|
||||
}
|
||||
|
||||
public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
|
||||
@@ -92,12 +80,13 @@ public class CachedBluetoothDeviceManager {
|
||||
if (cachedDevice.getDevice().equals(device)) {
|
||||
return cachedDevice;
|
||||
}
|
||||
}
|
||||
for (CachedBluetoothDevice notCachedDevice : mHearingAidDevicesNotAddedInCache) {
|
||||
if (notCachedDevice.getDevice().equals(device)) {
|
||||
return notCachedDevice;
|
||||
// Check sub devices if it exists
|
||||
CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
|
||||
if (subDevice != null && subDevice.getDevice().equals(device)) {
|
||||
return subDevice;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -111,24 +100,10 @@ public class CachedBluetoothDeviceManager {
|
||||
LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
|
||||
CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, profileManager,
|
||||
device);
|
||||
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) {
|
||||
mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(newDevice);
|
||||
synchronized (this) {
|
||||
if (!mHearingAidDeviceManager.setSubDeviceIfNeeded(newDevice)) {
|
||||
mCachedDevices.add(newDevice);
|
||||
if (newDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
|
||||
&& !mCachedDevicesMapForHearingAids.containsKey(newDevice.getHiSyncId())) {
|
||||
mCachedDevicesMapForHearingAids.put(newDevice.getHiSyncId(), newDevice);
|
||||
}
|
||||
mBtManager.getEventManager().dispatchDeviceAdded(newDevice);
|
||||
}
|
||||
}
|
||||
@@ -136,50 +111,19 @@ public class CachedBluetoothDeviceManager {
|
||||
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,
|
||||
* @return Device summary, or if the pair does not exist or if it is 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();
|
||||
}
|
||||
}
|
||||
public synchronized String getSubDeviceSummary(CachedBluetoothDevice device) {
|
||||
CachedBluetoothDevice subDevice = device.getSubDevice();
|
||||
if (subDevice != null && subDevice.isConnected()) {
|
||||
return subDevice.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);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,28 +131,8 @@ public class CachedBluetoothDeviceManager {
|
||||
* 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;
|
||||
}
|
||||
final Set<Long> syncIdChangedSet = new HashSet<Long>();
|
||||
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);
|
||||
syncIdChangedSet.add(newHiSyncId);
|
||||
}
|
||||
}
|
||||
for (Long syncId : syncIdChangedSet) {
|
||||
onHiSyncIdChanged(syncId);
|
||||
}
|
||||
public synchronized void updateHearingAidsDevices() {
|
||||
mHearingAidDeviceManager.updateHearingAidsDevices();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,15 +156,21 @@ public class CachedBluetoothDeviceManager {
|
||||
}
|
||||
|
||||
public synchronized void clearNonBondedDevices() {
|
||||
|
||||
mCachedDevicesMapForHearingAids.entrySet().removeIf(entries
|
||||
-> entries.getValue().getBondState() == BluetoothDevice.BOND_NONE);
|
||||
|
||||
clearNonBondedSubDevices();
|
||||
mCachedDevices.removeIf(cachedDevice
|
||||
-> cachedDevice.getBondState() == BluetoothDevice.BOND_NONE);
|
||||
}
|
||||
|
||||
mHearingAidDevicesNotAddedInCache.removeIf(hearingAidDevice
|
||||
-> hearingAidDevice.getBondState() == BluetoothDevice.BOND_NONE);
|
||||
private void clearNonBondedSubDevices() {
|
||||
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
|
||||
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
|
||||
CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
|
||||
if (subDevice != null
|
||||
&& subDevice.getDevice().getBondState() == BluetoothDevice.BOND_NONE) {
|
||||
// Sub device exists and it is not bonded
|
||||
cachedDevice.setSubDevice(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void onScanningStateChanged(boolean started) {
|
||||
@@ -250,10 +180,10 @@ public class CachedBluetoothDeviceManager {
|
||||
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);
|
||||
final CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
|
||||
if (subDevice != null) {
|
||||
subDevice.setJustDiscovered(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,162 +207,45 @@ public class CachedBluetoothDeviceManager {
|
||||
if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) {
|
||||
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
|
||||
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
|
||||
CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
|
||||
if (subDevice != null) {
|
||||
if (subDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
|
||||
cachedDevice.setSubDevice(null);
|
||||
}
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void onActiveDeviceChanged(CachedBluetoothDevice activeDevice,
|
||||
int bluetoothProfile) {
|
||||
int bluetoothProfile) {
|
||||
for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
|
||||
boolean isActive = Objects.equals(cachedDevice, activeDevice);
|
||||
cachedDevice.onActiveDeviceChanged(isActive, bluetoothProfile);
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
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 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. 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);
|
||||
firstMatchedIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 boolean onProfileConnectionStateChangedIfProcessed(CachedBluetoothDevice
|
||||
cachedDevice, int state) {
|
||||
return mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice,
|
||||
state);
|
||||
}
|
||||
|
||||
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;
|
||||
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();
|
||||
CachedBluetoothDevice mainDevice = mHearingAidDeviceManager.findMainDevice(device);
|
||||
CachedBluetoothDevice subDevice = device.getSubDevice();
|
||||
if (subDevice != null) {
|
||||
// Main device is unpaired, to unpair sub device
|
||||
subDevice.unpair();
|
||||
device.setSubDevice(null);
|
||||
} else if (mainDevice != null) {
|
||||
// Sub device unpaired, to unpair main device
|
||||
mainDevice.unpair();
|
||||
mainDevice.setSubDevice(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settingslib.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothHearingAid;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* HearingAidDeviceManager manages the set of remote HearingAid Bluetooth devices.
|
||||
*/
|
||||
public class HearingAidDeviceManager {
|
||||
private static final String TAG = "HearingAidDeviceManager";
|
||||
private static final boolean DEBUG = BluetoothUtils.D;
|
||||
|
||||
private final LocalBluetoothManager mBtManager;
|
||||
private final List<CachedBluetoothDevice> mCachedDevices;
|
||||
HearingAidDeviceManager(LocalBluetoothManager localBtManager,
|
||||
List<CachedBluetoothDevice> CachedDevices) {
|
||||
mBtManager = localBtManager;
|
||||
mCachedDevices = CachedDevices;
|
||||
}
|
||||
|
||||
void initHearingAidDeviceIfNeeded(CachedBluetoothDevice newDevice) {
|
||||
long hiSyncId = getHiSyncId(newDevice.getDevice());
|
||||
if (isValidHiSyncId(hiSyncId)) {
|
||||
// Once hiSyncId is valid, assign hiSyncId
|
||||
newDevice.setHiSyncId(hiSyncId);
|
||||
}
|
||||
}
|
||||
|
||||
private long getHiSyncId(BluetoothDevice device) {
|
||||
LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
|
||||
HearingAidProfile profileProxy = profileManager.getHearingAidProfile();
|
||||
if (profileProxy != null) {
|
||||
return profileProxy.getHiSyncId(device);
|
||||
}
|
||||
return BluetoothHearingAid.HI_SYNC_ID_INVALID;
|
||||
}
|
||||
|
||||
boolean setSubDeviceIfNeeded(CachedBluetoothDevice newDevice) {
|
||||
final long hiSyncId = newDevice.getHiSyncId();
|
||||
if (isValidHiSyncId(hiSyncId)) {
|
||||
final CachedBluetoothDevice hearingAidDevice = getCachedDevice(hiSyncId);
|
||||
// Just add one of the hearing aids from a pair in the list that is shown in the UI.
|
||||
// Once there is another device with the same hiSyncId, to add new device as sub
|
||||
// device.
|
||||
if (hearingAidDevice != null) {
|
||||
hearingAidDevice.setSubDevice(newDevice);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isValidHiSyncId(long hiSyncId) {
|
||||
return hiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID;
|
||||
}
|
||||
|
||||
private CachedBluetoothDevice getCachedDevice(long hiSyncId) {
|
||||
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
|
||||
CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
|
||||
if (cachedDevice.getHiSyncId() == hiSyncId) {
|
||||
return cachedDevice;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// To collect all HearingAid devices and call #onHiSyncIdChanged to group device by HiSyncId
|
||||
void updateHearingAidsDevices() {
|
||||
final Set<Long> newSyncIdSet = new HashSet<Long>();
|
||||
for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
|
||||
// Do nothing if HiSyncId has been assigned
|
||||
if (!isValidHiSyncId(cachedDevice.getHiSyncId())) {
|
||||
final long newHiSyncId = getHiSyncId(cachedDevice.getDevice());
|
||||
// Do nothing if there is no HiSyncId on Bluetooth device
|
||||
if (isValidHiSyncId(newHiSyncId)) {
|
||||
cachedDevice.setHiSyncId(newHiSyncId);
|
||||
newSyncIdSet.add(newHiSyncId);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Long syncId : newSyncIdSet) {
|
||||
onHiSyncIdChanged(syncId);
|
||||
}
|
||||
}
|
||||
|
||||
// Group devices by hiSyncId
|
||||
@VisibleForTesting
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
if (firstMatchedIndex == -1) {
|
||||
// Found the first one
|
||||
firstMatchedIndex = i;
|
||||
continue;
|
||||
}
|
||||
// Found the second one
|
||||
int indexToRemoveFromUi;
|
||||
CachedBluetoothDevice subDevice;
|
||||
CachedBluetoothDevice mainDevice;
|
||||
// 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 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. We will choose the device that
|
||||
// is not connected to be removed.
|
||||
if (cachedDevice.isConnected()) {
|
||||
mainDevice = cachedDevice;
|
||||
indexToRemoveFromUi = firstMatchedIndex;
|
||||
subDevice = mCachedDevices.get(firstMatchedIndex);
|
||||
} else {
|
||||
mainDevice = mCachedDevices.get(firstMatchedIndex);
|
||||
indexToRemoveFromUi = i;
|
||||
subDevice = cachedDevice;
|
||||
}
|
||||
|
||||
mainDevice.setSubDevice(subDevice);
|
||||
mCachedDevices.remove(indexToRemoveFromUi);
|
||||
log("onHiSyncIdChanged: removed from UI device =" + subDevice
|
||||
+ ", with hiSyncId=" + hiSyncId);
|
||||
mBtManager.getEventManager().dispatchDeviceRemoved(subDevice);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// @return {@code true}, the event is processed inside the method. It is for updating
|
||||
// hearing aid device on main-sub relationship when receiving connected or disconnected.
|
||||
// @return {@code false}, it is not hearing aid device or to process it same as other profiles
|
||||
boolean onProfileConnectionStateChangedIfProcessed(CachedBluetoothDevice cachedDevice,
|
||||
int state) {
|
||||
switch (state) {
|
||||
case BluetoothProfile.STATE_CONNECTED:
|
||||
onHiSyncIdChanged(cachedDevice.getHiSyncId());
|
||||
CachedBluetoothDevice mainDevice = findMainDevice(cachedDevice);
|
||||
if (mainDevice != null){
|
||||
if (mainDevice.isConnected()) {
|
||||
// When main device exists and in connected state, receiving sub device
|
||||
// connection. To refresh main device UI
|
||||
mainDevice.refresh();
|
||||
return true;
|
||||
} else {
|
||||
// When both Hearing Aid devices are disconnected, receiving sub device
|
||||
// connection. To switch content and dispatch to notify UI change
|
||||
mBtManager.getEventManager().dispatchDeviceRemoved(mainDevice);
|
||||
mainDevice.switchSubDeviceContent();
|
||||
mainDevice.refresh();
|
||||
// It is necessary to do remove and add for updating the mapping on
|
||||
// preference and device
|
||||
mBtManager.getEventManager().dispatchDeviceAdded(mainDevice);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BluetoothProfile.STATE_DISCONNECTED:
|
||||
mainDevice = findMainDevice(cachedDevice);
|
||||
if (mainDevice != null) {
|
||||
// When main device exists, receiving sub device disconnection
|
||||
// To update main device UI
|
||||
mainDevice.refresh();
|
||||
return true;
|
||||
}
|
||||
CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
|
||||
if (subDevice != null && subDevice.isConnected()) {
|
||||
// Main device is disconnected and sub device is connected
|
||||
// To copy data from sub device to main device
|
||||
mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
|
||||
cachedDevice.switchSubDeviceContent();
|
||||
cachedDevice.refresh();
|
||||
// It is necessary to do remove and add for updating the mapping on
|
||||
// preference and device
|
||||
mBtManager.getEventManager().dispatchDeviceAdded(cachedDevice);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CachedBluetoothDevice findMainDevice(CachedBluetoothDevice device) {
|
||||
for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
|
||||
if (isValidHiSyncId(cachedDevice.getHiSyncId())) {
|
||||
CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
|
||||
if (subDevice != null && subDevice.equals(device)) {
|
||||
return cachedDevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void log(String msg) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public class HearingAidProfile implements LocalBluetoothProfile {
|
||||
}
|
||||
|
||||
// Check current list of CachedDevices to see if any are Hearing Aid devices.
|
||||
mDeviceManager.updateHearingAidsDevices(mProfileManager);
|
||||
mDeviceManager.updateHearingAidsDevices();
|
||||
|
||||
mIsProfileReady=true;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -289,21 +288,21 @@ public class LocalBluetoothProfileManager {
|
||||
(newState == BluetoothProfile.STATE_CONNECTED)) {
|
||||
// Check if the HiSyncID has being initialized
|
||||
if (cachedDevice.getHiSyncId() == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
|
||||
|
||||
long newHiSyncId = getHearingAidProfile().getHiSyncId(cachedDevice.getDevice());
|
||||
|
||||
if (newHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
|
||||
cachedDevice.setHiSyncId(newHiSyncId);
|
||||
mDeviceManager.onHiSyncIdChanged(newHiSyncId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cachedDevice.onProfileStateChanged(mProfile, newState);
|
||||
cachedDevice.refresh();
|
||||
// Dispatch profile changed after device update
|
||||
mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
|
||||
mProfile.getProfileId());
|
||||
if (!(cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
|
||||
&& mDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice,
|
||||
newState))) {
|
||||
cachedDevice.refresh();
|
||||
mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
|
||||
mProfile.getProfileId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,8 +96,5 @@ public class BluetoothEventManagerTest {
|
||||
|
||||
verify(mBluetoothCallback).onProfileConnectionStateChanged(mCachedBluetoothDevice,
|
||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
|
||||
|
||||
verify(mCachedDeviceManager).onProfileConnectionStateChanged(mCachedBluetoothDevice,
|
||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ package com.android.settingslib.bluetooth;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothClass;
|
||||
@@ -80,6 +82,7 @@ public class CachedBluetoothDeviceManagerTest {
|
||||
private CachedBluetoothDevice mCachedDevice2;
|
||||
private CachedBluetoothDevice mCachedDevice3;
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
private HearingAidDeviceManager mHearingAidDeviceManager;
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
@@ -105,13 +108,12 @@ public class CachedBluetoothDeviceManagerTest {
|
||||
when(mA2dpProfile.isProfileReady()).thenReturn(true);
|
||||
when(mPanProfile.isProfileReady()).thenReturn(true);
|
||||
when(mHearingAidProfile.isProfileReady()).thenReturn(true);
|
||||
doAnswer((invocation) -> mHearingAidProfile).
|
||||
when(mLocalProfileManager).getHearingAidProfile();
|
||||
mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
|
||||
mCachedDevice1 = spy(
|
||||
new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1));
|
||||
mCachedDevice2 = spy(
|
||||
new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2));
|
||||
mCachedDevice3 = spy(
|
||||
new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice3));
|
||||
mCachedDevice1 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1));
|
||||
mCachedDevice2 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2));
|
||||
mCachedDevice3 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice3));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,6 +134,76 @@ public class CachedBluetoothDeviceManagerTest {
|
||||
assertThat(mCachedDeviceManager.findDevice(mDevice2)).isEqualTo(cachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify getSubDevice(), new device has the same HiSyncId.
|
||||
*/
|
||||
@Test
|
||||
public void addDevice_sameHiSyncId_validSubDevice() {
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
|
||||
|
||||
assertThat(cachedDevice1.getSubDevice()).isEqualTo(cachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify getSubDevice(), new device has the different HiSyncId.
|
||||
*/
|
||||
@Test
|
||||
public void addDevice_differentHiSyncId_validSubDevice() {
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
|
||||
doAnswer((invocation) -> HISYNCID2).when(mHearingAidProfile).getHiSyncId(mDevice2);
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
|
||||
|
||||
assertThat(cachedDevice1.getSubDevice()).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify addDevice(), new device has the same HiSyncId.
|
||||
*/
|
||||
@Test
|
||||
public void addDevice_sameHiSyncId_validCachedDevices_mainDevicesAdded_subDevicesNotAdded() {
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
|
||||
|
||||
Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
|
||||
assertThat(devices).contains(cachedDevice1);
|
||||
assertThat(devices).doesNotContain(cachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify addDevice(), new device has the different HiSyncId.
|
||||
*/
|
||||
@Test
|
||||
public void addDevice_differentHiSyncId_validCachedDevices_bothAdded() {
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
|
||||
doAnswer((invocation) -> HISYNCID2).when(mHearingAidProfile).getHiSyncId(mDevice2);
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
|
||||
|
||||
Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
|
||||
assertThat(devices).contains(cachedDevice1);
|
||||
assertThat(devices).contains(cachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify findDevice(), new device has the same HiSyncId.
|
||||
*/
|
||||
@Test
|
||||
public void findDevice_sameHiSyncId_foundBothDevice() {
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
|
||||
|
||||
assertThat(mCachedDeviceManager.findDevice(mDevice1)).isEqualTo(cachedDevice1);
|
||||
assertThat(mCachedDeviceManager.findDevice(mDevice2)).isEqualTo(cachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify getName().
|
||||
*/
|
||||
@@ -190,453 +262,89 @@ public class CachedBluetoothDeviceManagerTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify clearNonBondedDevices() for hearing aids.
|
||||
* Test to verify clearNonBondedDevices() for hearing aids sub device.
|
||||
*/
|
||||
@Test
|
||||
public void clearNonBondedDevices_HearingAids_nonBondedHAsClearedFromCachedDevicesMap() {
|
||||
public void clearNonBondedDevices_nonBondedSubDevice() {
|
||||
when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
|
||||
cachedDevice1.setSubDevice(cachedDevice2);
|
||||
|
||||
mCachedDevice1.setHiSyncId(HISYNCID1);
|
||||
mCachedDevice2.setHiSyncId(HISYNCID2);
|
||||
mCachedDeviceManager.mCachedDevicesMapForHearingAids.put(HISYNCID1, mCachedDevice1);
|
||||
mCachedDeviceManager.mCachedDevicesMapForHearingAids.put(HISYNCID2, mCachedDevice2);
|
||||
|
||||
assertThat(cachedDevice1.getSubDevice()).isEqualTo(cachedDevice2);
|
||||
mCachedDeviceManager.clearNonBondedDevices();
|
||||
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
|
||||
.doesNotContain(mCachedDevice2);
|
||||
assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
|
||||
.contains(mCachedDevice1);
|
||||
assertThat(cachedDevice1.getSubDevice()).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify onHiSyncIdChanged() for hearing aid devices with same HiSyncId.
|
||||
* Test to verify OnDeviceUnpaired() for main hearing Aid device unpair.
|
||||
*/
|
||||
@Test
|
||||
public void onHiSyncIdChanged_sameHiSyncId_populateInDifferentLists() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(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)
|
||||
.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 onHiSyncIdChanged_sameHiSyncIdAndOneConnected_chooseConnectedDevice() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(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 onHiSyncIdChanged_differentHiSyncId_populateInSameList() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(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 onProfileConnectionStateChanged() for single hearing aid device connection.
|
||||
*/
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_singleDeviceConnected_visible() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(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 onProfileConnectionStateChanged_twoDevicesConnected_oneDeviceVisible() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
|
||||
assertThat(cachedDevice2).isNotNull();
|
||||
cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
|
||||
cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
|
||||
public void onDeviceUnpaired_unpairMainDevice() {
|
||||
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 onProfileConnectionStateChanged_twoDevicesDisconnected_oneDeviceVisible() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(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.
|
||||
*/
|
||||
@Test
|
||||
public void onDeviceUnpaired_bothHearingAidsPaired_removesItsPairFromList() {
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(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);
|
||||
cachedDevice1.setSubDevice(cachedDevice2);
|
||||
|
||||
// Call onDeviceUnpaired for the one in mCachedDevices.
|
||||
mCachedDeviceManager.onDeviceUnpaired(cachedDevice2);
|
||||
|
||||
// Check if its pair is removed from mHearingAidDevicesNotAddedInCache.
|
||||
assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
|
||||
.doesNotContain(cachedDevice1);
|
||||
verify(mDevice1).removeBond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify OnDeviceUnpaired() for paired hearing Aid devices which are not a pair.
|
||||
* Test to verify OnDeviceUnpaired() for sub hearing Aid device unpair.
|
||||
*/
|
||||
@Test
|
||||
public void onDeviceUnpaired_bothHearingAidsNotPaired_doesNotRemoveAnyDeviceFromList() {
|
||||
public void onDeviceUnpaired_unpairSubDevice() {
|
||||
when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
|
||||
assertThat(cachedDevice1).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
|
||||
assertThat(cachedDevice2).isNotNull();
|
||||
CachedBluetoothDevice cachedDevice3 = mCachedDeviceManager.addDevice(mDevice3);
|
||||
assertThat(cachedDevice2).isNotNull();
|
||||
cachedDevice1.setSubDevice(cachedDevice2);
|
||||
|
||||
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);
|
||||
// Call onDeviceUnpaired for the one in mCachedDevices.
|
||||
mCachedDeviceManager.onDeviceUnpaired(cachedDevice1);
|
||||
verify(mDevice2).removeBond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify addDevice() for hearing aid devices with same HiSyncId.
|
||||
* Test to verify getSubDeviceSummary() for disconnected sub device
|
||||
*/
|
||||
@Test
|
||||
public void addDevice_hearingAidDevicesWithSameHiSyncId_populateInDifferentLists() {
|
||||
doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
|
||||
.getHearingAidProfile();
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
|
||||
public void getSubDeviceSummary_SubDeviceDisconnected() {
|
||||
when(mCachedDevice2.isConnected()).thenReturn(false);
|
||||
mCachedDevice1.setSubDevice(mCachedDevice2);
|
||||
mCachedDeviceManager.getSubDeviceSummary(mCachedDevice1);
|
||||
|
||||
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(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(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);
|
||||
verify(mCachedDevice2, never()).getConnectionSummary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify addDevice() for hearing aid devices with different HiSyncId.
|
||||
* Test to verify getSubDeviceSummary() for connected sub device
|
||||
*/
|
||||
@Test
|
||||
public void addDevice_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(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);
|
||||
public void getSubDeviceSummary_SubDeviceConnected() {
|
||||
when(mCachedDevice2.isConnected()).thenReturn(true);
|
||||
mCachedDevice1.setSubDevice(mCachedDevice2);
|
||||
mCachedDeviceManager.getSubDeviceSummary(mCachedDevice1);
|
||||
|
||||
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(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 getHearingAidPairDeviceSummary_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 getHearingAidPairDeviceSummary_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);
|
||||
verify(mCachedDevice2).getConnectionSummary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to verify updateHearingAidsDevices().
|
||||
*/
|
||||
@Test
|
||||
public void updateHearingAidDevices_hiSyncIdAvailable_setsHiSyncId() {
|
||||
doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
|
||||
.getHearingAidProfile();
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
|
||||
doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
|
||||
mCachedDeviceManager.updateHearingAidsDevices(mLocalProfileManager);
|
||||
public void updateHearingAidDevices_directToHearingAidDeviceManager() {
|
||||
mHearingAidDeviceManager = spy(new HearingAidDeviceManager(mLocalBluetoothManager,
|
||||
mCachedDeviceManager.mCachedDevices));
|
||||
mCachedDeviceManager.mHearingAidDeviceManager = mHearingAidDeviceManager;
|
||||
mCachedDeviceManager.updateHearingAidsDevices();
|
||||
|
||||
// Assert that the mCachedDevice1 and mCachedDevice2 have an updated HiSyncId.
|
||||
assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1);
|
||||
assertThat(mCachedDevice2.getHiSyncId()).isEqualTo(HISYNCID1);
|
||||
verify(mHearingAidDeviceManager).updateHearingAidsDevices();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,6 +48,10 @@ public class CachedBluetoothDeviceTest {
|
||||
private final static String DEVICE_ALIAS = "TestAlias";
|
||||
private final static String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF";
|
||||
private final static String DEVICE_ALIAS_NEW = "TestAliasNew";
|
||||
private final static short RSSI_1 = 10;
|
||||
private final static short RSSI_2 = 11;
|
||||
private final static boolean JUSTDISCOVERED_1 = true;
|
||||
private final static boolean JUSTDISCOVERED_2 = false;
|
||||
@Mock
|
||||
private LocalBluetoothProfileManager mProfileManager;
|
||||
@Mock
|
||||
@@ -60,6 +64,8 @@ public class CachedBluetoothDeviceTest {
|
||||
private HearingAidProfile mHearingAidProfile;
|
||||
@Mock
|
||||
private BluetoothDevice mDevice;
|
||||
@Mock
|
||||
private BluetoothDevice mSubDevice;
|
||||
private CachedBluetoothDevice mCachedDevice;
|
||||
private ShadowAudioManager mShadowAudioManager;
|
||||
private Context mContext;
|
||||
@@ -657,4 +663,39 @@ public class CachedBluetoothDeviceTest {
|
||||
doReturn(status).when(profile).getConnectionStatus(mDevice);
|
||||
mCachedDevice.onProfileStateChanged(profile, status);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSubDevice_setSubDevice() {
|
||||
CachedBluetoothDevice subCachedDevice = new CachedBluetoothDevice(mContext, mProfileManager,
|
||||
mSubDevice);
|
||||
mCachedDevice.setSubDevice(subCachedDevice);
|
||||
|
||||
assertThat(mCachedDevice.getSubDevice()).isEqualTo(subCachedDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void switchSubDeviceContent() {
|
||||
CachedBluetoothDevice subCachedDevice = new CachedBluetoothDevice(mContext, mProfileManager,
|
||||
mSubDevice);
|
||||
mCachedDevice.mRssi = RSSI_1;
|
||||
mCachedDevice.mJustDiscovered = JUSTDISCOVERED_1;
|
||||
subCachedDevice.mRssi = RSSI_2;
|
||||
subCachedDevice.mJustDiscovered = JUSTDISCOVERED_2;
|
||||
mCachedDevice.setSubDevice(subCachedDevice);
|
||||
|
||||
assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_1);
|
||||
assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
|
||||
assertThat(mCachedDevice.mDevice).isEqualTo(mDevice);
|
||||
assertThat(subCachedDevice.mRssi).isEqualTo(RSSI_2);
|
||||
assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
|
||||
assertThat(subCachedDevice.mDevice).isEqualTo(mSubDevice);
|
||||
mCachedDevice.switchSubDeviceContent();
|
||||
|
||||
assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_2);
|
||||
assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
|
||||
assertThat(mCachedDevice.mDevice).isEqualTo(mSubDevice);
|
||||
assertThat(subCachedDevice.mRssi).isEqualTo(RSSI_1);
|
||||
assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
|
||||
assertThat(subCachedDevice.mDevice).isEqualTo(mDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settingslib.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothHearingAid;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settingslib.SettingsLibRobolectricTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(SettingsLibRobolectricTestRunner.class)
|
||||
public class HearingAidDeviceManagerTest {
|
||||
private final static long HISYNCID1 = 10;
|
||||
private final static long HISYNCID2 = 11;
|
||||
private final static String DEVICE_NAME_1 = "TestName_1";
|
||||
private final static String DEVICE_NAME_2 = "TestName_2";
|
||||
private final static String DEVICE_ALIAS_1 = "TestAlias_1";
|
||||
private final static String DEVICE_ALIAS_2 = "TestAlias_2";
|
||||
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 BluetoothClass DEVICE_CLASS =
|
||||
new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
|
||||
@Mock
|
||||
private LocalBluetoothProfileManager mLocalProfileManager;
|
||||
@Mock
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
@Mock
|
||||
private BluetoothEventManager mBluetoothEventManager;
|
||||
@Mock
|
||||
private HearingAidProfile mHearingAidProfile;
|
||||
@Mock
|
||||
private BluetoothDevice mDevice1;
|
||||
@Mock
|
||||
private BluetoothDevice mDevice2;
|
||||
private CachedBluetoothDevice mCachedDevice1;
|
||||
private CachedBluetoothDevice mCachedDevice2;
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
private HearingAidDeviceManager mHearingAidDeviceManager;
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
|
||||
when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
|
||||
when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
|
||||
when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
|
||||
when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
|
||||
when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
|
||||
when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS);
|
||||
when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS);
|
||||
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
|
||||
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalProfileManager);
|
||||
when(mLocalProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
|
||||
|
||||
mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
|
||||
mHearingAidDeviceManager = spy(new HearingAidDeviceManager(mLocalBluetoothManager,
|
||||
mCachedDeviceManager.mCachedDevices));
|
||||
mCachedDevice1 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1));
|
||||
mCachedDevice2 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test initHearingAidDeviceIfNeeded, a valid HiSyncId will be assigned
|
||||
*/
|
||||
@Test
|
||||
public void initHearingAidDeviceIfNeeded_validHiSyncId_verifyHiSyncId() {
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
|
||||
|
||||
assertThat(mCachedDevice1.getHiSyncId()).isNotEqualTo(HISYNCID1);
|
||||
mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(mCachedDevice1);
|
||||
|
||||
assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test initHearingAidDeviceIfNeeded, an invalid HiSyncId will not be assigned
|
||||
*/
|
||||
@Test
|
||||
public void initHearingAidDeviceIfNeeded_invalidHiSyncId_notToSetHiSyncId() {
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(
|
||||
BluetoothHearingAid.HI_SYNC_ID_INVALID);
|
||||
mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(mCachedDevice1);
|
||||
|
||||
verify(mCachedDevice1, never()).setHiSyncId(anyLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setSubDeviceIfNeeded, a device with same HiSyncId will be set as sub device
|
||||
*/
|
||||
@Test
|
||||
public void setSubDeviceIfNeeded_sameHiSyncId_setSubDevice() {
|
||||
mCachedDevice1.setHiSyncId(HISYNCID1);
|
||||
mCachedDevice2.setHiSyncId(HISYNCID1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mHearingAidDeviceManager.setSubDeviceIfNeeded(mCachedDevice2);
|
||||
|
||||
assertThat(mCachedDevice1.getSubDevice()).isEqualTo(mCachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setSubDeviceIfNeeded, a device with different HiSyncId will not be set as sub device
|
||||
*/
|
||||
@Test
|
||||
public void setSubDeviceIfNeeded_differentHiSyncId_notSetSubDevice() {
|
||||
mCachedDevice1.setHiSyncId(HISYNCID1);
|
||||
mCachedDevice2.setHiSyncId(HISYNCID2);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mHearingAidDeviceManager.setSubDeviceIfNeeded(mCachedDevice2);
|
||||
|
||||
assertThat(mCachedDevice1.getSubDevice()).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test updateHearingAidsDevices, to link two devices with the same HiSyncId.
|
||||
* When first paired devices is connected and second paired device is disconnected, first
|
||||
* paired device would be set as main device and second device will be removed from
|
||||
* CachedDevices list.
|
||||
*/
|
||||
@Test
|
||||
public void updateHearingAidsDevices_firstPairedDevicesConnected_verifySubDevice() {
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice2)).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice1.isConnected()).thenReturn(true);
|
||||
when(mCachedDevice2.isConnected()).thenReturn(false);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
|
||||
|
||||
assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isTrue();
|
||||
assertThat(mCachedDevice1.getSubDevice()).isNull();
|
||||
mHearingAidDeviceManager.updateHearingAidsDevices();
|
||||
|
||||
assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isFalse();
|
||||
assertThat(mCachedDevice1.getSubDevice()).isEqualTo(mCachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test updateHearingAidsDevices, to link two devices with the same HiSyncId.
|
||||
* When second paired devices is connected and first paired device is disconnected, second
|
||||
* paired device would be set as main device and first device will be removed from
|
||||
* CachedDevices list.
|
||||
*/
|
||||
@Test
|
||||
public void updateHearingAidsDevices_secondPairedDeviceConnected_verifySubDevice() {
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice2)).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice1.isConnected()).thenReturn(false);
|
||||
when(mCachedDevice2.isConnected()).thenReturn(true);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
|
||||
|
||||
assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice1)).isTrue();
|
||||
assertThat(mCachedDevice2.getSubDevice()).isNull();
|
||||
mHearingAidDeviceManager.updateHearingAidsDevices();
|
||||
|
||||
assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice1)).isFalse();
|
||||
assertThat(mCachedDevice2.getSubDevice()).isEqualTo(mCachedDevice1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test updateHearingAidsDevices, to link two devices with the same HiSyncId.
|
||||
* When both devices are connected, to build up main and sub relationship and to remove sub
|
||||
* device from CachedDevices list.
|
||||
*/
|
||||
@Test
|
||||
public void updateHearingAidsDevices_BothConnected_verifySubDevice() {
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice2)).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice1.isConnected()).thenReturn(true);
|
||||
when(mCachedDevice2.isConnected()).thenReturn(true);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
|
||||
|
||||
assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isTrue();
|
||||
assertThat(mCachedDevice1.getSubDevice()).isNull();
|
||||
mHearingAidDeviceManager.updateHearingAidsDevices();
|
||||
|
||||
assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isFalse();
|
||||
assertThat(mCachedDevice1.getSubDevice()).isEqualTo(mCachedDevice2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test updateHearingAidsDevices, dispatch callback
|
||||
*/
|
||||
@Test
|
||||
public void updateHearingAidsDevices_dispatchDeviceRemovedCallback() {
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice2)).thenReturn(HISYNCID1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
|
||||
mHearingAidDeviceManager.updateHearingAidsDevices();
|
||||
|
||||
verify(mBluetoothEventManager).dispatchDeviceRemoved(mCachedDevice1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test updateHearingAidsDevices, do nothing when HiSyncId is invalid
|
||||
*/
|
||||
@Test
|
||||
public void updateHearingAidsDevices_invalidHiSyncId_doNothing() {
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice1)).
|
||||
thenReturn(BluetoothHearingAid.HI_SYNC_ID_INVALID);
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice2)).
|
||||
thenReturn(BluetoothHearingAid.HI_SYNC_ID_INVALID);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
|
||||
mHearingAidDeviceManager.updateHearingAidsDevices();
|
||||
|
||||
verify(mHearingAidDeviceManager, never()).onHiSyncIdChanged(anyLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test onProfileConnectionStateChangedIfProcessed.
|
||||
* When first hearing aid device is connected, to process it same as other generic devices.
|
||||
* No need to process it.
|
||||
*/
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_connected_singleDevice_returnFalse() {
|
||||
when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
|
||||
|
||||
assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
|
||||
mCachedDevice1, BluetoothProfile.STATE_CONNECTED)).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test onProfileConnectionStateChangedIfProcessed.
|
||||
* When a new hearing aid device is connected, to set it as sub device by onHiSyncIdChanged().
|
||||
* And, to verify new device is not in CachedDevices list.
|
||||
*/
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_connected_newDevice_verifySubDevice() {
|
||||
when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice1.isConnected()).thenReturn(true);
|
||||
when(mCachedDevice2.isConnected()).thenReturn(true);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
|
||||
|
||||
assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isTrue();
|
||||
assertThat(mCachedDevice1.getSubDevice()).isNull();
|
||||
mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(mCachedDevice1,
|
||||
BluetoothProfile.STATE_CONNECTED);
|
||||
|
||||
assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isFalse();
|
||||
assertThat(mCachedDevice1.getSubDevice()).isEqualTo(mCachedDevice2);
|
||||
verify(mHearingAidDeviceManager).onHiSyncIdChanged(anyLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test onProfileConnectionStateChangedIfProcessed.
|
||||
* When sub device is disconnected, do nothing and return False for main device connected event
|
||||
*/
|
||||
@Test
|
||||
public void
|
||||
onProfileConnectionStateChanged_connected_mainDevice_subDeviceDisconnected_returnFalse() {
|
||||
when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.isConnected()).thenReturn(false);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDevice1.setSubDevice(mCachedDevice2);
|
||||
|
||||
assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
|
||||
mCachedDevice1, BluetoothProfile.STATE_CONNECTED)).isFalse();
|
||||
verify(mHearingAidDeviceManager).onHiSyncIdChanged(anyLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test onProfileConnectionStateChangedIfProcessed.
|
||||
* When main device is connected, do main device refresh() for sub device connected event
|
||||
*/
|
||||
@Test
|
||||
public void
|
||||
onProfileConnectionStateChanged_connected_subDevice_mainDeviceConnected_verifyRefresh() {
|
||||
when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice1.isConnected()).thenReturn(true);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDevice1.setSubDevice(mCachedDevice2);
|
||||
|
||||
assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
|
||||
mCachedDevice2, BluetoothProfile.STATE_CONNECTED)).isTrue();
|
||||
verify(mHearingAidDeviceManager).onHiSyncIdChanged(anyLong());
|
||||
verify(mCachedDevice1).refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test onProfileConnectionStateChangedIfProcessed.
|
||||
* When main device is disconnected, to verify switch() result for sub device connected
|
||||
* event
|
||||
*/
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_connected_subDevice_mainDeviceDisconnected_switch()
|
||||
{
|
||||
when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice1.isConnected()).thenReturn(false);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDevice1.setSubDevice(mCachedDevice2);
|
||||
|
||||
assertThat(mCachedDevice1.mDevice).isEqualTo(mDevice1);
|
||||
assertThat(mCachedDevice2.mDevice).isEqualTo(mDevice2);
|
||||
assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
|
||||
mCachedDevice2, BluetoothProfile.STATE_CONNECTED)).isTrue();
|
||||
|
||||
assertThat(mCachedDevice1.mDevice).isEqualTo(mDevice2);
|
||||
assertThat(mCachedDevice2.mDevice).isEqualTo(mDevice1);
|
||||
verify(mHearingAidDeviceManager).onHiSyncIdChanged(anyLong());
|
||||
verify(mCachedDevice1).refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test onProfileConnectionStateChangedIfProcessed.
|
||||
* When sub device is connected, to verify switch() result for main device disconnected
|
||||
* event
|
||||
*/
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_disconnected_mainDevice_subDeviceConnected_switch()
|
||||
{
|
||||
when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.isConnected()).thenReturn(true);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDevice1.setSubDevice(mCachedDevice2);
|
||||
|
||||
assertThat(mCachedDevice1.mDevice).isEqualTo(mDevice1);
|
||||
assertThat(mCachedDevice2.mDevice).isEqualTo(mDevice2);
|
||||
assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
|
||||
mCachedDevice1, BluetoothProfile.STATE_DISCONNECTED)).isTrue();
|
||||
|
||||
assertThat(mCachedDevice1.mDevice).isEqualTo(mDevice2);
|
||||
assertThat(mCachedDevice2.mDevice).isEqualTo(mDevice1);
|
||||
verify(mCachedDevice1).refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test onProfileConnectionStateChangedIfProcessed.
|
||||
* When sub device is disconnected, do nothing and return False for main device disconnected
|
||||
* event
|
||||
*/
|
||||
@Test
|
||||
public void
|
||||
onProfileConnectionStateChanged_disconnected_mainDevice_subDeviceDisconnected_returnFalse() {
|
||||
when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.isConnected()).thenReturn(false);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDevice1.setSubDevice(mCachedDevice2);
|
||||
|
||||
assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
|
||||
mCachedDevice1, BluetoothProfile.STATE_DISCONNECTED)).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test onProfileConnectionStateChangedIfProcessed.
|
||||
* Refresh main device UI for sub device disconnected event
|
||||
*/
|
||||
@Test
|
||||
public void onProfileConnectionStateChanged_disconnected_subDevice_verifyRefresh() {
|
||||
when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDevice1.setSubDevice(mCachedDevice2);
|
||||
|
||||
assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
|
||||
mCachedDevice2, BluetoothProfile.STATE_DISCONNECTED)).isTrue();
|
||||
verify(mCachedDevice1).refresh();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findMainDevice() {
|
||||
when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
|
||||
mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
|
||||
mCachedDevice1.setSubDevice(mCachedDevice2);
|
||||
|
||||
assertThat(mHearingAidDeviceManager.findMainDevice(mCachedDevice2)).
|
||||
isEqualTo(mCachedDevice1);
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,8 @@ import java.util.List;
|
||||
@RunWith(SettingsLibRobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowBluetoothAdapter.class})
|
||||
public class LocalBluetoothProfileManagerTest {
|
||||
private final static long HISYNCID = 10;
|
||||
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mDeviceManager;
|
||||
@Mock
|
||||
@@ -79,6 +81,7 @@ public class LocalBluetoothProfileManagerTest {
|
||||
mContext, null));
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice);
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mDevice);
|
||||
mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
|
||||
mDeviceManager, mEventManager);
|
||||
}
|
||||
@@ -186,13 +189,14 @@ public class LocalBluetoothProfileManagerTest {
|
||||
|
||||
/**
|
||||
* Verify BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to
|
||||
* profile connection state changed callback
|
||||
* CachedBluetoothDeviceManager method
|
||||
*/
|
||||
@Test
|
||||
public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldDispatchCallback() {
|
||||
public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldDispatchDeviceManager() {
|
||||
mShadowBluetoothAdapter.setSupportedProfiles(generateList(
|
||||
new int[] {BluetoothProfile.HEARING_AID}));
|
||||
mProfileManager.updateLocalProfiles();
|
||||
when(mCachedBluetoothDevice.getHiSyncId()).thenReturn(HISYNCID);
|
||||
|
||||
mIntent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
|
||||
mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
|
||||
@@ -201,8 +205,8 @@ public class LocalBluetoothProfileManagerTest {
|
||||
|
||||
mContext.sendBroadcast(mIntent);
|
||||
|
||||
verify(mEventManager).dispatchProfileConnectionStateChanged(mCachedBluetoothDevice,
|
||||
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
|
||||
verify(mDeviceManager).onProfileConnectionStateChangedIfProcessed(mCachedBluetoothDevice,
|
||||
BluetoothProfile.STATE_CONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user