Merge "[Audiosharing] Returns BluetoothDevice when fetchConnectedDevicesByGroupId" into main

This commit is contained in:
Yiyi Shen
2024-08-05 06:11:47 +00:00
committed by Android (Google) Code Review
5 changed files with 107 additions and 98 deletions

View File

@@ -66,7 +66,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/** PreferenceController to control the dialog to choose the active device for calls and alarms */ /** PreferenceController to control the dialog to choose the active device for calls and alarms */
public class AudioSharingCallAudioPreferenceController extends AudioSharingBasePreferenceController public class AudioSharingCallAudioPreferenceController extends AudioSharingBasePreferenceController
implements BluetoothCallback { implements BluetoothCallback {
private static final String TAG = "CallsAndAlarmsPreferenceController"; private static final String TAG = "CallAudioPrefController";
private static final String PREF_KEY = "calls_and_alarms"; private static final String PREF_KEY = "calls_and_alarms";
@VisibleForTesting @VisibleForTesting
@@ -85,7 +85,7 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
private final ContentObserver mSettingsObserver; private final ContentObserver mSettingsObserver;
private final MetricsFeatureProvider mMetricsFeatureProvider; private final MetricsFeatureProvider mMetricsFeatureProvider;
@Nullable private Fragment mFragment; @Nullable private Fragment mFragment;
Map<Integer, List<CachedBluetoothDevice>> mGroupedConnectedDevices = new HashMap<>(); Map<Integer, List<BluetoothDevice>> mGroupedConnectedDevices = new HashMap<>();
private List<AudioSharingDeviceItem> mDeviceItemsInSharingSession = new ArrayList<>(); private List<AudioSharingDeviceItem> mDeviceItemsInSharingSession = new ArrayList<>();
private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false); private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
@@ -210,11 +210,12 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
"Skip set fallback active device: unchanged"); "Skip set fallback active device: unchanged");
return; return;
} }
List<CachedBluetoothDevice> devices = List<BluetoothDevice> devices =
mGroupedConnectedDevices.getOrDefault( mGroupedConnectedDevices.getOrDefault(
item.getGroupId(), ImmutableList.of()); item.getGroupId(), ImmutableList.of());
CachedBluetoothDevice lead = CachedBluetoothDevice lead =
AudioSharingUtils.getLeadDevice(devices); AudioSharingUtils.getLeadDevice(
mCacheManager, devices);
if (lead != null) { if (lead != null) {
Log.d( Log.d(
TAG, TAG,
@@ -347,8 +348,8 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
*/ */
private void updateSummary() { private void updateSummary() {
updateDeviceItemsInSharingSession(); updateDeviceItemsInSharingSession();
int fallbackActiveGroupId = BluetoothUtils.getPrimaryGroupIdForBroadcast( int fallbackActiveGroupId =
mContext.getContentResolver()); BluetoothUtils.getPrimaryGroupIdForBroadcast(mContext.getContentResolver());
if (fallbackActiveGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { if (fallbackActiveGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
for (AudioSharingDeviceItem item : mDeviceItemsInSharingSession) { for (AudioSharingDeviceItem item : mDeviceItemsInSharingSession) {
if (item.getGroupId() == fallbackActiveGroupId) { if (item.getGroupId() == fallbackActiveGroupId) {

View File

@@ -16,6 +16,8 @@
package com.android.settings.connecteddevice.audiosharing; package com.android.settings.connecteddevice.audiosharing;
import static java.util.stream.Collectors.toList;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
@@ -38,6 +40,7 @@ import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -49,14 +52,14 @@ import com.google.common.collect.ImmutableList;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
public class AudioSharingDialogHandler { public class AudioSharingDialogHandler {
private static final String TAG = "AudioSharingDialogHandler"; private static final String TAG = "AudioSharingDlgHandler";
private final Context mContext; private final Context mContext;
private final Fragment mHostFragment; private final Fragment mHostFragment;
@Nullable private final LocalBluetoothManager mLocalBtManager; @Nullable private final LocalBluetoothManager mLocalBtManager;
@Nullable private final CachedBluetoothDeviceManager mDeviceManager;
@Nullable private final LocalBluetoothLeBroadcast mBroadcast; @Nullable private final LocalBluetoothLeBroadcast mBroadcast;
@Nullable private final LocalBluetoothLeBroadcastAssistant mAssistant; @Nullable private final LocalBluetoothLeBroadcastAssistant mAssistant;
private final MetricsFeatureProvider mMetricsFeatureProvider; private final MetricsFeatureProvider mMetricsFeatureProvider;
@@ -163,6 +166,7 @@ public class AudioSharingDialogHandler {
mContext = context; mContext = context;
mHostFragment = fragment; mHostFragment = fragment;
mLocalBtManager = Utils.getLocalBluetoothManager(context); mLocalBtManager = Utils.getLocalBluetoothManager(context);
mDeviceManager = mLocalBtManager != null ? mLocalBtManager.getCachedDeviceManager() : null;
mBroadcast = mBroadcast =
mLocalBtManager != null mLocalBtManager != null
? mLocalBtManager.getProfileManager().getLeAudioBroadcastProfile() ? mLocalBtManager.getProfileManager().getLeAudioBroadcastProfile()
@@ -212,7 +216,7 @@ public class AudioSharingDialogHandler {
if (isBroadcasting) { if (isBroadcasting) {
// Show stop audio sharing dialog when an ineligible (non LE audio) remote device // Show stop audio sharing dialog when an ineligible (non LE audio) remote device
// connected during a sharing session. // connected during a sharing session.
Map<Integer, List<CachedBluetoothDevice>> groupedDevices = Map<Integer, List<BluetoothDevice>> groupedDevices =
AudioSharingUtils.fetchConnectedDevicesByGroupId(mLocalBtManager); AudioSharingUtils.fetchConnectedDevicesByGroupId(mLocalBtManager);
List<AudioSharingDeviceItem> deviceItemsInSharingSession = List<AudioSharingDeviceItem> deviceItemsInSharingSession =
AudioSharingUtils.buildOrderedConnectedLeadAudioSharingDeviceItem( AudioSharingUtils.buildOrderedConnectedLeadAudioSharingDeviceItem(
@@ -256,19 +260,19 @@ public class AudioSharingDialogHandler {
@NonNull CachedBluetoothDevice cachedDevice, @NonNull CachedBluetoothDevice cachedDevice,
boolean isBroadcasting, boolean isBroadcasting,
boolean userTriggered) { boolean userTriggered) {
Map<Integer, List<CachedBluetoothDevice>> groupedDevices = Map<Integer, List<BluetoothDevice>> groupedDevices =
AudioSharingUtils.fetchConnectedDevicesByGroupId(mLocalBtManager); AudioSharingUtils.fetchConnectedDevicesByGroupId(mLocalBtManager);
BluetoothDevice btDevice = cachedDevice.getDevice(); BluetoothDevice btDevice = cachedDevice.getDevice();
String deviceAddress = btDevice == null ? "" : btDevice.getAnonymizedAddress(); String deviceAddress = btDevice == null ? "" : btDevice.getAnonymizedAddress();
int groupId = BluetoothUtils.getGroupId(cachedDevice);
if (isBroadcasting) { if (isBroadcasting) {
// If another device within the same is already in the sharing session, add source to // If another device within the same is already in the sharing session, add source to
// the device automatically. // the device automatically.
int groupId = BluetoothUtils.getGroupId(cachedDevice);
if (groupedDevices.containsKey(groupId) if (groupedDevices.containsKey(groupId)
&& groupedDevices.get(groupId).stream() && groupedDevices.get(groupId).stream()
.anyMatch( .anyMatch(
device -> device ->
BluetoothUtils.hasConnectedBroadcastSource( BluetoothUtils.hasConnectedBroadcastSourceForBtDevice(
device, mLocalBtManager))) { device, mLocalBtManager))) {
Log.d( Log.d(
TAG, TAG,
@@ -352,14 +356,17 @@ public class AudioSharingDialogHandler {
} else { } else {
// Build a list of AudioSharingDeviceItem for connected devices other than cachedDevice. // Build a list of AudioSharingDeviceItem for connected devices other than cachedDevice.
List<AudioSharingDeviceItem> deviceItems = new ArrayList<>(); List<AudioSharingDeviceItem> deviceItems = new ArrayList<>();
for (List<CachedBluetoothDevice> devices : groupedDevices.values()) { for (Map.Entry<Integer, List<BluetoothDevice>> entry : groupedDevices.entrySet()) {
if (entry.getKey() == groupId) continue;
// Use random device in the group within the sharing session to represent the group. // Use random device in the group within the sharing session to represent the group.
CachedBluetoothDevice device = devices.get(0); for (BluetoothDevice device : entry.getValue()) {
if (BluetoothUtils.getGroupId(device) CachedBluetoothDevice cDevice =
== BluetoothUtils.getGroupId(cachedDevice)) { mDeviceManager != null ? mDeviceManager.findDevice(device) : null;
continue; if (cDevice != null) {
deviceItems.add(AudioSharingUtils.buildAudioSharingDeviceItem(cDevice));
break;
}
} }
deviceItems.add(AudioSharingUtils.buildAudioSharingDeviceItem(device));
} }
// Show audio sharing join dialog when the second eligible (LE audio) remote // Show audio sharing join dialog when the second eligible (LE audio) remote
// device connect and no sharing session. // device connect and no sharing session.
@@ -368,13 +375,10 @@ public class AudioSharingDialogHandler {
new AudioSharingJoinDialogFragment.DialogEventListener() { new AudioSharingJoinDialogFragment.DialogEventListener() {
@Override @Override
public void onShareClick() { public void onShareClick() {
mTargetSinks = new ArrayList<>(); mTargetSinks =
for (List<CachedBluetoothDevice> devices : groupedDevices.values().stream()
groupedDevices.values()) { .flatMap(items -> items.stream())
for (CachedBluetoothDevice device : devices) { .collect(toList());
mTargetSinks.add(device.getDevice());
}
}
Log.d(TAG, "Start broadcast with sinks = " + mTargetSinks.size()); Log.d(TAG, "Start broadcast with sinks = " + mTargetSinks.size());
if (mBroadcast != null) { if (mBroadcast != null) {
mBroadcast.startPrivateBroadcast(); mBroadcast.startPrivateBroadcast();
@@ -493,7 +497,7 @@ public class AudioSharingDialogHandler {
} }
private void removeSourceForGroup( private void removeSourceForGroup(
int groupId, Map<Integer, List<CachedBluetoothDevice>> groupedDevices) { int groupId, Map<Integer, List<BluetoothDevice>> groupedDevices) {
if (mAssistant == null) { if (mAssistant == null) {
Log.d(TAG, "Fail to add source due to null profiles, group = " + groupId); Log.d(TAG, "Fail to add source due to null profiles, group = " + groupId);
return; return;
@@ -503,8 +507,6 @@ public class AudioSharingDialogHandler {
return; return;
} }
groupedDevices.getOrDefault(groupId, ImmutableList.of()).stream() groupedDevices.getOrDefault(groupId, ImmutableList.of()).stream()
.map(CachedBluetoothDevice::getDevice)
.filter(Objects::nonNull)
.forEach( .forEach(
device -> { device -> {
for (BluetoothLeBroadcastReceiveState source : for (BluetoothLeBroadcastReceiveState source :
@@ -515,7 +517,7 @@ public class AudioSharingDialogHandler {
} }
private void addSourceForGroup( private void addSourceForGroup(
int groupId, Map<Integer, List<CachedBluetoothDevice>> groupedDevices) { int groupId, Map<Integer, List<BluetoothDevice>> groupedDevices) {
if (mBroadcast == null || mAssistant == null) { if (mBroadcast == null || mAssistant == null) {
Log.d(TAG, "Fail to add source due to null profiles, group = " + groupId); Log.d(TAG, "Fail to add source due to null profiles, group = " + groupId);
return; return;
@@ -525,8 +527,6 @@ public class AudioSharingDialogHandler {
return; return;
} }
groupedDevices.getOrDefault(groupId, ImmutableList.of()).stream() groupedDevices.getOrDefault(groupId, ImmutableList.of()).stream()
.map(CachedBluetoothDevice::getDevice)
.filter(Objects::nonNull)
.forEach( .forEach(
device -> device ->
mAssistant.addSource( mAssistant.addSource(

View File

@@ -48,7 +48,6 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.SettingsMainSwitchBar; import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -63,17 +62,15 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
public class AudioSharingSwitchBarController extends BasePreferenceController public class AudioSharingSwitchBarController extends BasePreferenceController
implements DefaultLifecycleObserver, implements DefaultLifecycleObserver,
OnCheckedChangeListener, OnCheckedChangeListener,
LocalBluetoothProfileManager.ServiceListener { LocalBluetoothProfileManager.ServiceListener {
private static final String TAG = "AudioSharingSwitchBarCtl"; private static final String TAG = "AudioSharingSwitchCtlr";
private static final String PREF_KEY = "audio_sharing_main_switch"; private static final String PREF_KEY = "audio_sharing_main_switch";
interface OnAudioSharingStateChangedListener { interface OnAudioSharingStateChangedListener {
@@ -103,7 +100,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
private final Executor mExecutor; private final Executor mExecutor;
private final MetricsFeatureProvider mMetricsFeatureProvider; private final MetricsFeatureProvider mMetricsFeatureProvider;
private final OnAudioSharingStateChangedListener mListener; private final OnAudioSharingStateChangedListener mListener;
private Map<Integer, List<CachedBluetoothDevice>> mGroupedConnectedDevices = new HashMap<>(); private Map<Integer, List<BluetoothDevice>> mGroupedConnectedDevices = new HashMap<>();
private List<BluetoothDevice> mTargetActiveSinks = new ArrayList<>(); private List<BluetoothDevice> mTargetActiveSinks = new ArrayList<>();
private List<AudioSharingDeviceItem> mDeviceItemsForSharing = new ArrayList<>(); private List<AudioSharingDeviceItem> mDeviceItemsForSharing = new ArrayList<>();
@VisibleForTesting IntentFilter mIntentFilter; @VisibleForTesting IntentFilter mIntentFilter;
@@ -454,13 +451,11 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
mDeviceItemsForSharing = new ArrayList<>(deviceItems); mDeviceItemsForSharing = new ArrayList<>(deviceItems);
mTargetActiveSinks = new ArrayList<>(); mTargetActiveSinks = new ArrayList<>();
if (!deviceItems.isEmpty() && deviceItems.get(0).isActive()) { if (!deviceItems.isEmpty() && deviceItems.get(0).isActive()) {
for (CachedBluetoothDevice device :
mGroupedConnectedDevices.getOrDefault(
deviceItems.get(0).getGroupId(), ImmutableList.of())) {
// If active device exists for audio sharing, share to it // If active device exists for audio sharing, share to it
// automatically once the broadcast is started. // automatically once the broadcast is started.
mTargetActiveSinks.add(device.getDevice()); mTargetActiveSinks =
} mGroupedConnectedDevices.getOrDefault(
deviceItems.get(0).getGroupId(), ImmutableList.of());
mDeviceItemsForSharing.remove(0); mDeviceItemsForSharing.remove(0);
} }
if (mBroadcast != null) { if (mBroadcast != null) {
@@ -541,12 +536,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
@Override @Override
public void onItemClick(@NonNull AudioSharingDeviceItem item) { public void onItemClick(@NonNull AudioSharingDeviceItem item) {
AudioSharingUtils.addSourceToTargetSinks( AudioSharingUtils.addSourceToTargetSinks(
mGroupedConnectedDevices mGroupedConnectedDevices.getOrDefault(
.getOrDefault(item.getGroupId(), ImmutableList.of()) item.getGroupId(), ImmutableList.of()),
.stream()
.map(CachedBluetoothDevice::getDevice)
.filter(Objects::nonNull)
.collect(Collectors.toList()),
mBtManager); mBtManager);
mGroupedConnectedDevices.clear(); mGroupedConnectedDevices.clear();
mDeviceItemsForSharing.clear(); mDeviceItemsForSharing.clear();

View File

@@ -22,6 +22,8 @@ import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtil
import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtils.MetricKey.METRIC_KEY_SOURCE_PAGE_ID; import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtils.MetricKey.METRIC_KEY_SOURCE_PAGE_ID;
import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtils.MetricKey.METRIC_KEY_USER_TRIGGERED; import static com.android.settings.connecteddevice.audiosharing.AudioSharingUtils.MetricKey.METRIC_KEY_USER_TRIGGERED;
import static java.util.stream.Collectors.toList;
import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastMetadata;
@@ -44,10 +46,11 @@ import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.bluetooth.VolumeControlProfile; import com.android.settingslib.bluetooth.VolumeControlProfile;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.Objects;
public class AudioSharingUtils { public class AudioSharingUtils {
private static final String TAG = "AudioSharingUtils"; private static final String TAG = "AudioSharingUtils";
@@ -62,15 +65,15 @@ public class AudioSharingUtils {
} }
/** /**
* Fetch {@link CachedBluetoothDevice}s connected to the broadcast assistant. The devices are * Fetch {@link BluetoothDevice}s connected to the broadcast assistant. The devices are grouped
* grouped by CSIP group id. * by CSIP group id.
* *
* @param localBtManager The BT manager to provide BT functions. * @param localBtManager The BT manager to provide BT functions.
* @return A map of connected devices grouped by CSIP group id. * @return A map of connected devices grouped by CSIP group id.
*/ */
public static Map<Integer, List<CachedBluetoothDevice>> fetchConnectedDevicesByGroupId( public static Map<Integer, List<BluetoothDevice>> fetchConnectedDevicesByGroupId(
@Nullable LocalBluetoothManager localBtManager) { @Nullable LocalBluetoothManager localBtManager) {
Map<Integer, List<CachedBluetoothDevice>> groupedDevices = new HashMap<>(); Map<Integer, List<BluetoothDevice>> groupedDevices = new HashMap<>();
if (localBtManager == null) { if (localBtManager == null) {
Log.d(TAG, "Skip fetchConnectedDevicesByGroupId due to bt manager is null"); Log.d(TAG, "Skip fetchConnectedDevicesByGroupId due to bt manager is null");
return groupedDevices; return groupedDevices;
@@ -99,7 +102,7 @@ public class AudioSharingUtils {
if (!groupedDevices.containsKey(groupId)) { if (!groupedDevices.containsKey(groupId)) {
groupedDevices.put(groupId, new ArrayList<>()); groupedDevices.put(groupId, new ArrayList<>());
} }
groupedDevices.get(groupId).add(cachedDevice); groupedDevices.get(groupId).add(device);
} }
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "fetchConnectedDevicesByGroupId: " + groupedDevices); Log.d(TAG, "fetchConnectedDevicesByGroupId: " + groupedDevices);
@@ -122,11 +125,16 @@ public class AudioSharingUtils {
*/ */
public static List<CachedBluetoothDevice> buildOrderedConnectedLeadDevices( public static List<CachedBluetoothDevice> buildOrderedConnectedLeadDevices(
@Nullable LocalBluetoothManager localBtManager, @Nullable LocalBluetoothManager localBtManager,
Map<Integer, List<CachedBluetoothDevice>> groupedConnectedDevices, Map<Integer, List<BluetoothDevice>> groupedConnectedDevices,
boolean filterByInSharing) { boolean filterByInSharing) {
List<CachedBluetoothDevice> orderedDevices = new ArrayList<>(); List<CachedBluetoothDevice> orderedDevices = new ArrayList<>();
for (List<CachedBluetoothDevice> devices : groupedConnectedDevices.values()) { if (localBtManager == null) {
CachedBluetoothDevice leadDevice = getLeadDevice(devices); Log.d(TAG, "Skip buildOrderedConnectedLeadDevices due to bt manager is null");
return orderedDevices;
}
CachedBluetoothDeviceManager deviceManager = localBtManager.getCachedDeviceManager();
for (List<BluetoothDevice> devices : groupedConnectedDevices.values()) {
CachedBluetoothDevice leadDevice = getLeadDevice(deviceManager, devices);
if (leadDevice == null) { if (leadDevice == null) {
Log.d(TAG, "Skip due to no lead device"); Log.d(TAG, "Skip due to no lead device");
continue; continue;
@@ -141,52 +149,39 @@ public class AudioSharingUtils {
} }
orderedDevices.add(leadDevice); orderedDevices.add(leadDevice);
} }
orderedDevices.sort( orderedDevices.sort(sCachedDeviceComparator);
(CachedBluetoothDevice d1, CachedBluetoothDevice d2) -> {
// Active above not inactive
int comparison =
(isActiveLeAudioDevice(d2) ? 1 : 0)
- (isActiveLeAudioDevice(d1) ? 1 : 0);
if (comparison != 0) return comparison;
// Bonded above not bonded
comparison =
(d2.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0)
- (d1.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0);
if (comparison != 0) return comparison;
// Bond timestamp available above unavailable
comparison =
(d2.getBondTimestamp() != null ? 1 : 0)
- (d1.getBondTimestamp() != null ? 1 : 0);
if (comparison != 0) return comparison;
// Order by bond timestamp if it is available
// Otherwise order by device name
return d1.getBondTimestamp() != null
? d1.getBondTimestamp().compareTo(d2.getBondTimestamp())
: d1.getName().compareTo(d2.getName());
});
return orderedDevices; return orderedDevices;
} }
/** /**
* Get the lead device from a list of devices with same group id. * Get the lead device from a list of devices with same group id.
* *
* @param deviceManager CachedBluetoothDeviceManager
* @param devices A list of devices with same group id. * @param devices A list of devices with same group id.
* @return The lead device * @return The lead device
*/ */
@Nullable @Nullable
public static CachedBluetoothDevice getLeadDevice( public static CachedBluetoothDevice getLeadDevice(
@NonNull List<CachedBluetoothDevice> devices) { @Nullable CachedBluetoothDeviceManager deviceManager,
if (devices.isEmpty()) return null; @NonNull List<BluetoothDevice> devices) {
for (CachedBluetoothDevice device : devices) { if (deviceManager == null || devices.isEmpty()) return null;
if (!device.getMemberDevice().isEmpty()) { List<CachedBluetoothDevice> cachedDevices =
return device; devices.stream()
.map(device -> deviceManager.findDevice(device))
.filter(Objects::nonNull)
.collect(toList());
for (CachedBluetoothDevice cachedDevice : cachedDevices) {
if (!cachedDevice.getMemberDevice().isEmpty()) {
return cachedDevice;
} }
} }
CachedBluetoothDevice leadDevice = devices.get(0); CachedBluetoothDevice leadDevice = cachedDevices.isEmpty() ? null : cachedDevices.get(0);
Log.d( Log.d(
TAG, TAG,
"No lead device in the group, pick arbitrary device as the lead: " "No lead device in the group, pick arbitrary device as the lead: "
+ leadDevice.getDevice().getAnonymizedAddress()); + (leadDevice == null
? "null"
: leadDevice.getDevice().getAnonymizedAddress()));
return leadDevice; return leadDevice;
} }
@@ -206,13 +201,13 @@ public class AudioSharingUtils {
@NonNull @NonNull
public static List<AudioSharingDeviceItem> buildOrderedConnectedLeadAudioSharingDeviceItem( public static List<AudioSharingDeviceItem> buildOrderedConnectedLeadAudioSharingDeviceItem(
@Nullable LocalBluetoothManager localBtManager, @Nullable LocalBluetoothManager localBtManager,
Map<Integer, List<CachedBluetoothDevice>> groupedConnectedDevices, Map<Integer, List<BluetoothDevice>> groupedConnectedDevices,
boolean filterByInSharing) { boolean filterByInSharing) {
return buildOrderedConnectedLeadDevices( return buildOrderedConnectedLeadDevices(
localBtManager, groupedConnectedDevices, filterByInSharing) localBtManager, groupedConnectedDevices, filterByInSharing)
.stream() .stream()
.map(AudioSharingUtils::buildAudioSharingDeviceItem) .map(AudioSharingUtils::buildAudioSharingDeviceItem)
.collect(Collectors.toList()); .collect(toList());
} }
/** Build {@link AudioSharingDeviceItem} from {@link CachedBluetoothDevice}. */ /** Build {@link AudioSharingDeviceItem} from {@link CachedBluetoothDevice}. */
@@ -361,4 +356,27 @@ public class AudioSharingUtils {
Pair.create(METRIC_KEY_CANDIDATE_DEVICE_COUNT.ordinal(), candidateDeviceCount) Pair.create(METRIC_KEY_CANDIDATE_DEVICE_COUNT.ordinal(), candidateDeviceCount)
}; };
} }
private static final Comparator<CachedBluetoothDevice> sCachedDeviceComparator =
(CachedBluetoothDevice d1, CachedBluetoothDevice d2) -> {
// Active above not inactive
int comparison =
(isActiveLeAudioDevice(d2) ? 1 : 0) - (isActiveLeAudioDevice(d1) ? 1 : 0);
if (comparison != 0) return comparison;
// Bonded above not bonded
comparison =
(d2.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0)
- (d1.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0);
if (comparison != 0) return comparison;
// Bond timestamp available above unavailable
comparison =
(d2.getBondTimestamp() != null ? 1 : 0)
- (d1.getBondTimestamp() != null ? 1 : 0);
if (comparison != 0) return comparison;
// Order by bond timestamp if it is available
// Otherwise order by device name
return d1.getBondTimestamp() != null
? d1.getBondTimestamp().compareTo(d2.getBondTimestamp())
: d1.getName().compareTo(d2.getName());
};
} }

View File

@@ -23,7 +23,6 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Aud
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;