csip: seamless pair with the coordinated set

1. Handle the set member avaiabler intent, check the group is existing and create bond automatically.
2. Accept the paring request for the ongoing set member

Bug: 150670922
Bug: 178981521
Test: pair with one of the CSIP supported device,and get bonded with the
whole coordinated set

Change-Id: Ia95e1ba6dccde0a4e61a9eafdef746b1415704a4
This commit is contained in:
Alice Kuo
2021-09-17 03:56:37 +08:00
parent e7d2554f18
commit e7cb6bd26f
3 changed files with 126 additions and 0 deletions

View File

@@ -126,6 +126,9 @@ public class BluetoothEventManager {
addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler());
addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler());
addHandler(BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE,
new SetMemberAvailableHandler());
registerAdapterIntentReceiver();
}
@@ -339,6 +342,12 @@ public class BluetoothEventManager {
}
int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
BluetoothDevice.ERROR);
if (mDeviceManager.onBondStateChangedIfProcess(device, bondState)) {
Log.d(TAG, "Should not update UI for the set member");
return;
}
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
if (cachedDevice == null) {
Log.w(TAG, "Got bonding state changed for " + device +
@@ -502,4 +511,29 @@ public class BluetoothEventManager {
dispatchAudioModeChanged();
}
}
private class SetMemberAvailableHandler implements Handler {
@Override
public void onReceive(Context context, Intent intent, BluetoothDevice device) {
final String action = intent.getAction();
if (device == null) {
Log.e(TAG, "SetMemberAvailableHandler: device is null");
return;
}
if (action == null) {
Log.e(TAG, "SetMemberAvailableHandler: action is null");
return;
}
final int groupId = intent.getIntExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID,
BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
Log.e(TAG, "SetMemberAvailableHandler: Invalid group id");
return;
}
mDeviceManager.onSetMemberAppear(device, groupId);
}
}
}

View File

@@ -45,6 +45,7 @@ public class CachedBluetoothDeviceManager {
HearingAidDeviceManager mHearingAidDeviceManager;
@VisibleForTesting
CsipDeviceManager mCsipDeviceManager;
BluetoothDevice mOngoingSetMemberPair;
CachedBluetoothDeviceManager(Context context, LocalBluetoothManager localBtManager) {
mContext = context;
@@ -337,6 +338,74 @@ public class CachedBluetoothDeviceManager {
}
}
/**
* Called when we found a set member of a group. The function will check the {@code groupId} if
* it exists and if there is a ongoing pair, the device would be ignored.
*
* @param device The found device
* @param groupId The group id of the found device
*/
public synchronized void onSetMemberAppear(BluetoothDevice device, int groupId) {
Log.d(TAG, "onSetMemberAppear, groupId: " + groupId + " device: " + device.toString());
if (mOngoingSetMemberPair != null) {
Log.d(TAG, "Ongoing set memberPairing in process, drop it!");
return;
}
if (mCsipDeviceManager.onSetMemberAppear(device, groupId)) {
mOngoingSetMemberPair = device;
}
}
/**
* Called when the bond state change. If the bond state change is related with the
* ongoing set member pair, the cachedBluetoothDevice will be created but the UI
* would not be updated. For the other case, return {@code false} to go through the normal
* flow.
*
* @param device The device
* @param bondState The new bond state
*
* @return {@code true}, if the bond state change for the device is handled inside this
* function, and would not like to update the UI. If not, return {@code false}.
*/
public synchronized boolean onBondStateChangedIfProcess(BluetoothDevice device, int bondState) {
if (mOngoingSetMemberPair == null || !mOngoingSetMemberPair.equals(device)) {
return false;
}
if (bondState == BluetoothDevice.BOND_BONDING) {
return true;
}
mOngoingSetMemberPair = null;
if (bondState != BluetoothDevice.BOND_NONE) {
if (findDevice(device) == null) {
final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
CachedBluetoothDevice newDevice =
new CachedBluetoothDevice(mContext, profileManager, device);
mCachedDevices.add(newDevice);
findDevice(device).connect();
}
}
return true;
}
/**
* Check if the device is the one which is initial paired locally by CSIP. The setting
* would depned on it to accept the pairing request automatically
*
* @param device The device
*
* @return {@code true}, if the device is ongoing pair by CSIP. Otherwise, return
* {@code false}.
*/
public boolean isOngoingPairByCsip(BluetoothDevice device) {
return !(mOngoingSetMemberPair == null) && mOngoingSetMemberPair.equals(device);
}
private void log(String msg) {
if (DEBUG) {
Log.d(TAG, msg);

View File

@@ -239,6 +239,29 @@ public class CsipDeviceManager {
return null;
}
/**
* Called when we found a set member of a group. The function will check bond state, and
* the {@code groupId} if it exists, and then create the bond.
*
* @param device The found device
* @param groupId The group id of the found device
*
* @return {@code true}, if the we create bond with the device. Otherwise, return
* {@code false}.
*/
public boolean onSetMemberAppear(BluetoothDevice device, int groupId) {
if (device.getBondState() != BluetoothDevice.BOND_NONE) {
return false;
}
if (getCachedDevice(groupId) != null) {
device.createBond(BluetoothDevice.TRANSPORT_LE);
return true;
}
return false;
}
private void log(String msg) {
if (DEBUG) {
Log.d(TAG, msg);