Merge "[Audiosharing] Returns BluetoothDevice when fetchConnectedDevicesByGroupId" into main
This commit is contained in:
@@ -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,17 +210,18 @@ 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,
|
||||||
"Set fallback active device: "
|
"Set fallback active device: "
|
||||||
+ lead.getDevice()
|
+ lead.getDevice()
|
||||||
.getAnonymizedAddress());
|
.getAnonymizedAddress());
|
||||||
lead.setActive();
|
lead.setActive();
|
||||||
logCallAudioDeviceChange(currentGroupId, lead);
|
logCallAudioDeviceChange(currentGroupId, lead);
|
||||||
} else {
|
} else {
|
||||||
@@ -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) {
|
||||||
|
@@ -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(
|
||||||
|
@@ -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;
|
||||||
@@ -341,8 +338,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
|||||||
// FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST is always true in
|
// FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST is always true in
|
||||||
// prod. We can turn off the flag for debug purpose.
|
// prod. We can turn off the flag for debug purpose.
|
||||||
if (FeatureFlagUtils.isEnabled(
|
if (FeatureFlagUtils.isEnabled(
|
||||||
mContext,
|
mContext,
|
||||||
FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST)
|
FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST)
|
||||||
&& mAssistant.getAllConnectedDevices().isEmpty()) {
|
&& mAssistant.getAllConnectedDevices().isEmpty()) {
|
||||||
// Pop up dialog to ask users to connect at least one lea buds before audio sharing.
|
// Pop up dialog to ask users to connect at least one lea buds before audio sharing.
|
||||||
AudioSharingUtils.postOnMainThread(
|
AudioSharingUtils.postOnMainThread(
|
||||||
@@ -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 :
|
// If active device exists for audio sharing, share to it
|
||||||
|
// automatically once the broadcast is started.
|
||||||
|
mTargetActiveSinks =
|
||||||
mGroupedConnectedDevices.getOrDefault(
|
mGroupedConnectedDevices.getOrDefault(
|
||||||
deviceItems.get(0).getGroupId(), ImmutableList.of())) {
|
deviceItems.get(0).getGroupId(), ImmutableList.of());
|
||||||
// If active device exists for audio sharing, share to it
|
|
||||||
// automatically once the broadcast is started.
|
|
||||||
mTargetActiveSinks.add(device.getDevice());
|
|
||||||
}
|
|
||||||
mDeviceItemsForSharing.remove(0);
|
mDeviceItemsForSharing.remove(0);
|
||||||
}
|
}
|
||||||
if (mBroadcast != null) {
|
if (mBroadcast != null) {
|
||||||
@@ -488,7 +483,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
|||||||
boolean isStateReady =
|
boolean isStateReady =
|
||||||
isBluetoothOn()
|
isBluetoothOn()
|
||||||
&& AudioSharingUtils.isAudioSharingProfileReady(
|
&& AudioSharingUtils.isAudioSharingProfileReady(
|
||||||
mProfileManager);
|
mProfileManager);
|
||||||
AudioSharingUtils.postOnMainThread(
|
AudioSharingUtils.postOnMainThread(
|
||||||
mContext,
|
mContext,
|
||||||
() -> {
|
() -> {
|
||||||
@@ -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();
|
||||||
@@ -575,8 +566,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
|
|||||||
@NonNull ViewGroup host, @NonNull View view, @NonNull AccessibilityEvent event) {
|
@NonNull ViewGroup host, @NonNull View view, @NonNull AccessibilityEvent event) {
|
||||||
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
|
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
|
||||||
&& (event.getContentChangeTypes()
|
&& (event.getContentChangeTypes()
|
||||||
& AccessibilityEvent.CONTENT_CHANGE_TYPE_ENABLED)
|
& AccessibilityEvent.CONTENT_CHANGE_TYPE_ENABLED)
|
||||||
!= 0) {
|
!= 0) {
|
||||||
Log.d(TAG, "Skip accessibility event for CONTENT_CHANGE_TYPE_ENABLED");
|
Log.d(TAG, "Skip accessibility event for CONTENT_CHANGE_TYPE_ENABLED");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -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());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user