Skip to content
Snippets Groups Projects
Commit f3d300b0 authored by SongFerngWang's avatar SongFerngWang
Browse files

[LE Unicast] Using the active device as main device after grouping

After onGroupIdChanged, the CsipDeviceManager assigns the first
device with the same groupId as main device. It is not correct
since the main device shouble be the active device. This issue
causes the summary can't shows 'Active' at the Settings.

Bug: 232892046
Test: Build pass
Change-Id: I00e5471b9315c896b8c16723ad37d66a922c27e4
Merged-In: I00e5471b9315c896b8c16723ad37d66a922c27e4
parent 2be0e5e3
No related branches found
No related tags found
No related merge requests found
......@@ -20,15 +20,19 @@ import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.os.Build;
import android.os.ParcelUuid;
import android.util.Log;
import androidx.annotation.ChecksSdkIntAtLeast;
import com.android.internal.annotations.VisibleForTesting;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* CsipDeviceManager manages the set of remote CSIP Bluetooth devices.
......@@ -126,32 +130,84 @@ public class CsipDeviceManager {
}
}
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
private static boolean isAtLeastT() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
}
// Group devices by groupId
@VisibleForTesting
void onGroupIdChanged(int groupId) {
int firstMatchedIndex = -1;
CachedBluetoothDevice mainDevice = null;
if (!isValidGroupId(groupId)) {
log("onGroupIdChanged: groupId is invalid");
return;
}
log("onGroupIdChanged: mCachedDevices list =" + mCachedDevices.toString());
final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
final CachedBluetoothDeviceManager deviceManager = mBtManager.getCachedDeviceManager();
final LeAudioProfile leAudioProfile = profileManager.getLeAudioProfile();
final BluetoothDevice mainBluetoothDevice = (leAudioProfile != null && isAtLeastT()) ?
leAudioProfile.getConnectedGroupLeadDevice(groupId) : null;
CachedBluetoothDevice newMainDevice =
mainBluetoothDevice != null ? deviceManager.findDevice(mainBluetoothDevice) : null;
if (newMainDevice != null) {
final CachedBluetoothDevice finalNewMainDevice = newMainDevice;
final List<CachedBluetoothDevice> memberDevices = mCachedDevices.stream()
.filter(cachedDevice -> !cachedDevice.equals(finalNewMainDevice)
&& cachedDevice.getGroupId() == groupId)
.collect(Collectors.toList());
if (memberDevices == null || memberDevices.isEmpty()) {
log("onGroupIdChanged: There is no member device in list.");
return;
}
log("onGroupIdChanged: removed from UI device =" + memberDevices
+ ", with groupId=" + groupId + " mainDevice= " + newMainDevice);
for (CachedBluetoothDevice memberDeviceItem : memberDevices) {
Set<CachedBluetoothDevice> memberSet = memberDeviceItem.getMemberDevice();
if (!memberSet.isEmpty()) {
log("onGroupIdChanged: Transfer the member list into new main device.");
for (CachedBluetoothDevice memberListItem : memberSet) {
if (!memberListItem.equals(newMainDevice)) {
newMainDevice.addMemberDevice(memberListItem);
}
}
memberSet.clear();
}
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
final CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
if (cachedDevice.getGroupId() != groupId) {
continue;
newMainDevice.addMemberDevice(memberDeviceItem);
mCachedDevices.remove(memberDeviceItem);
mBtManager.getEventManager().dispatchDeviceRemoved(memberDeviceItem);
}
if (firstMatchedIndex == -1) {
// Found the first one
firstMatchedIndex = i;
mainDevice = cachedDevice;
continue;
if (!mCachedDevices.contains(newMainDevice)) {
mCachedDevices.add(newMainDevice);
mBtManager.getEventManager().dispatchDeviceAdded(newMainDevice);
}
} else {
log("onGroupIdChanged: There is no main device from the LE profile.");
int firstMatchedIndex = -1;
log("onGroupIdChanged: removed from UI device =" + cachedDevice
+ ", with groupId=" + groupId + " firstMatchedIndex=" + firstMatchedIndex);
for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
final CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
if (cachedDevice.getGroupId() != groupId) {
continue;
}
if (firstMatchedIndex == -1) {
// Found the first one
firstMatchedIndex = i;
newMainDevice = cachedDevice;
continue;
}
log("onGroupIdChanged: removed from UI device =" + cachedDevice
+ ", with groupId=" + groupId + " firstMatchedIndex=" + firstMatchedIndex);
mainDevice.addMemberDevice(cachedDevice);
mCachedDevices.remove(i);
mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
break;
newMainDevice.addMemberDevice(cachedDevice);
mCachedDevices.remove(i);
mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
break;
}
}
}
......
......@@ -21,6 +21,7 @@ import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_ALL;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothCodecConfig;
......@@ -183,6 +184,37 @@ public class LeAudioProfile implements LocalBluetoothProfile {
return mBluetoothAdapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
}
/**
* Get Lead device for the group.
*
* Lead device is the device that can be used as an active device in the system.
* Active devices points to the Audio Device for the Le Audio group.
* This method returns the Lead devices for the connected LE Audio
* group and this device should be used in the setActiveDevice() method by other parts
* of the system, which wants to set to active a particular Le Audio group.
*
* Note: getActiveDevice() returns the Lead device for the currently active LE Audio group.
* Note: When Lead device gets disconnected while Le Audio group is active and has more devices
* in the group, then Lead device will not change. If Lead device gets disconnected, for the
* Le Audio group which is not active, a new Lead device will be chosen
*
* @param groupId The group id.
* @return group lead device.
*
* @hide
*/
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public @Nullable BluetoothDevice getConnectedGroupLeadDevice(int groupId) {
if (DEBUG) {
Log.d(TAG,"getConnectedGroupLeadDevice");
}
if (mService == null) {
Log.e(TAG,"No service.");
return null;
}
return mService.getConnectedGroupLeadDevice(groupId);
}
@Override
public boolean isEnabled(BluetoothDevice device) {
if (mService == null || device == null) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment