From 83798bfbc5e3f11fa7c648aecd0dbf06c85e2b84 Mon Sep 17 00:00:00 2001 From: Yiyi Shen Date: Wed, 15 Nov 2023 15:47:03 +0800 Subject: [PATCH] [Audiosharing] Add a util class for audio sharing. Flagged with enable_le_audio_sharing Bug: 305620450 Test: Manual Change-Id: Iea5d4faa83eeef2d7104b9c31679e9226b75f4a6 --- ...udioSharingDevicePreferenceController.java | 59 +-------- .../AudioSharingSwitchBarController.java | 41 +----- .../audiosharing/AudioSharingUtils.java | 125 ++++++++++++++++++ 3 files changed, 134 insertions(+), 91 deletions(-) create mode 100644 src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java index b0f8b8f3ab1..0d2b53add08 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java @@ -17,7 +17,6 @@ package com.android.settings.connecteddevice.audiosharing; import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcast; import android.bluetooth.BluetoothLeBroadcastAssistant; @@ -43,16 +42,12 @@ import com.android.settings.dashboard.DashboardFragment; import com.android.settings.flags.Flags; import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LeAudioProfile; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; -import com.google.common.collect.ImmutableList; - import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; @@ -378,13 +373,14 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro // Do nothing for ineligible (non LE audio) remote device when no sharing session. } else { Map> groupedDevices = - fetchConnectedDevicesByGroupId(); + AudioSharingUtils.fetchConnectedDevicesByGroupId(mLocalBtManager); // Handle connected eligible (LE audio) remote device if (isBroadcasting()) { // Show audio sharing switch or join dialog according to device count in the sharing // session. ArrayList deviceItemsInSharingSession = - buildDeviceItemsInSharingSession(groupedDevices); + AudioSharingUtils.buildOrderedDeviceItemsInSharingSession( + groupedDevices, mLocalBtManager); // Show audio sharing switch dialog when the third eligible (LE audio) remote device // connected during a sharing session. if (deviceItemsInSharingSession.size() >= 2) { @@ -432,8 +428,7 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro if (device.getGroupId() == cachedDevice.getGroupId()) { continue; } - deviceItems.add( - new AudioSharingDeviceItem(device.getName(), device.getGroupId())); + deviceItems.add(AudioSharingUtils.buildAudioSharingDeviceItem(device)); } // Show audio sharing join dialog when the second eligible (LE audio) remote device // connect and no sharing session. @@ -494,52 +489,6 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro return mBroadcast != null && mBroadcast.isEnabled(null); } - private Map> fetchConnectedDevicesByGroupId() { - // TODO: filter out devices with le audio disabled. - List connectedDevices = - mAssistant == null ? ImmutableList.of() : mAssistant.getConnectedDevices(); - Map> groupedDevices = new HashMap<>(); - CachedBluetoothDeviceManager cacheManager = mLocalBtManager.getCachedDeviceManager(); - for (BluetoothDevice device : connectedDevices) { - CachedBluetoothDevice cachedDevice = cacheManager.findDevice(device); - if (cachedDevice == null) { - Log.d(TAG, "Skip device due to not being cached: " + device.getAnonymizedAddress()); - continue; - } - int groupId = cachedDevice.getGroupId(); - if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { - Log.d( - TAG, - "Skip device due to no valid group id: " + device.getAnonymizedAddress()); - continue; - } - if (!groupedDevices.containsKey(groupId)) { - groupedDevices.put(groupId, new ArrayList<>()); - } - groupedDevices.get(groupId).add(cachedDevice); - } - return groupedDevices; - } - - private ArrayList buildDeviceItemsInSharingSession( - Map> groupedDevices) { - ArrayList deviceItems = new ArrayList<>(); - for (List devices : groupedDevices.values()) { - for (CachedBluetoothDevice device : devices) { - List sourceList = - mAssistant.getAllSources(device.getDevice()); - if (!sourceList.isEmpty()) { - // Use random device in the group within the sharing session to - // represent the group. - deviceItems.add( - new AudioSharingDeviceItem(device.getName(), device.getGroupId())); - break; - } - } - } - return deviceItems; - } - private void addSourceToTargetDevices(List sinks) { if (sinks.isEmpty() || mBroadcast == null || mAssistant == null) { Log.d(TAG, "Skip adding source to target."); diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java index 3f9f48e30b8..8b82fe9d4fd 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java @@ -16,13 +16,11 @@ package com.android.settings.connecteddevice.audiosharing; -import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcast; import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastReceiveState; -import android.bluetooth.BluetoothProfile; import android.content.Context; import android.util.Log; import android.widget.CompoundButton; @@ -37,17 +35,14 @@ import com.android.settings.core.BasePreferenceController; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.flags.Flags; import com.android.settings.widget.SettingsMainSwitchBar; +import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.utils.ThreadUtils; -import com.google.common.collect.ImmutableList; - import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -273,18 +268,17 @@ public class AudioSharingSwitchBarController extends BasePreferenceController mSwitchBar.setEnabled(true); return; } - Map> groupedDevices = fetchConnectedDevicesByGroupId(); + Map> groupedDevices = + AudioSharingUtils.fetchConnectedDevicesByGroupId(mBtManager); ArrayList deviceItems = new ArrayList<>(); Optional activeGroupId = Optional.empty(); for (List devices : groupedDevices.values()) { // Use random device in the group to represent the group. CachedBluetoothDevice device = devices.get(0); - // TODO: add BluetoothUtils.isActiveLeAudioDevice to avoid directly using isActiveDevice - if (device.isActiveDevice(BluetoothProfile.LE_AUDIO)) { + if (BluetoothUtils.isActiveLeAudioDevice(device)) { activeGroupId = Optional.of(device.getGroupId()); } else { - AudioSharingDeviceItem item = - new AudioSharingDeviceItem(device.getName(), device.getGroupId()); + AudioSharingDeviceItem item = AudioSharingUtils.buildAudioSharingDeviceItem(device); deviceItems.add(item); } } @@ -347,31 +341,6 @@ public class AudioSharingSwitchBarController extends BasePreferenceController return mBroadcast != null && mBroadcast.isEnabled(null); } - private Map> fetchConnectedDevicesByGroupId() { - // TODO: filter out devices with le audio disabled. - List connectedDevices = - mAssistant == null ? ImmutableList.of() : mAssistant.getConnectedDevices(); - Map> groupedDevices = new HashMap<>(); - CachedBluetoothDeviceManager cacheManager = mBtManager.getCachedDeviceManager(); - for (BluetoothDevice device : connectedDevices) { - CachedBluetoothDevice cachedDevice = cacheManager.findDevice(device); - if (cachedDevice == null) { - Log.d(TAG, "Skip device due to not being cached: " + device.getAnonymizedAddress()); - continue; - } - int groupId = cachedDevice.getGroupId(); - if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { - Log.d(TAG, "Skip device due to no valid group id"); - continue; - } - if (!groupedDevices.containsKey(groupId)) { - groupedDevices.put(groupId, new ArrayList<>()); - } - groupedDevices.get(groupId).add(cachedDevice); - } - return groupedDevices; - } - private void addSourceToTargetDevices(List sinks) { if (sinks.isEmpty() || mBroadcast == null || mAssistant == null) { Log.d(TAG, "Skip adding source to target."); diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java new file mode 100644 index 00000000000..4ece70e00fb --- /dev/null +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2023 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.settings.connecteddevice.audiosharing; + +import android.bluetooth.BluetoothCsipSetCoordinator; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothLeBroadcastReceiveState; +import android.util.Log; + +import com.android.settingslib.bluetooth.BluetoothUtils; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; +import com.android.settingslib.bluetooth.LocalBluetoothManager; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AudioSharingUtils { + private static final String TAG = "AudioSharingUtils"; + + /** + * Fetch {@link CachedBluetoothDevice}s connected to the broadcast assistant. The devices are + * grouped by CSIP group id. + * + * @param localBtManager The BT manager to provide BT functions. + * @return A map of connected devices grouped by CSIP group id. + */ + public static Map> fetchConnectedDevicesByGroupId( + LocalBluetoothManager localBtManager) { + Map> groupedDevices = new HashMap<>(); + LocalBluetoothLeBroadcastAssistant assistant = + localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile(); + if (assistant == null) return groupedDevices; + // TODO: filter out devices with le audio disabled. + List connectedDevices = assistant.getConnectedDevices(); + CachedBluetoothDeviceManager cacheManager = localBtManager.getCachedDeviceManager(); + for (BluetoothDevice device : connectedDevices) { + CachedBluetoothDevice cachedDevice = cacheManager.findDevice(device); + if (cachedDevice == null) { + Log.d(TAG, "Skip device due to not being cached: " + device.getAnonymizedAddress()); + continue; + } + int groupId = cachedDevice.getGroupId(); + if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { + Log.d( + TAG, + "Skip device due to no valid group id: " + device.getAnonymizedAddress()); + continue; + } + if (!groupedDevices.containsKey(groupId)) { + groupedDevices.put(groupId, new ArrayList<>()); + } + groupedDevices.get(groupId).add(cachedDevice); + } + return groupedDevices; + } + + /** + * Fetch a list of {@link AudioSharingDeviceItem}s in the audio sharing session. + * + * @param groupedConnectedDevices devices connected to broadcast assistant grouped by CSIP group + * id. + * @param localBtManager The BT manager to provide BT functions. + * @return A list of connected devices in the audio sharing session. + */ + public static ArrayList buildOrderedDeviceItemsInSharingSession( + Map> groupedConnectedDevices, + LocalBluetoothManager localBtManager) { + ArrayList deviceItems = new ArrayList<>(); + LocalBluetoothLeBroadcastAssistant assistant = + localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile(); + if (assistant == null) return deviceItems; + CachedBluetoothDevice activeDevice = null; + List inactiveDevices = new ArrayList<>(); + for (List devices : groupedConnectedDevices.values()) { + for (CachedBluetoothDevice device : devices) { + List sourceList = + assistant.getAllSources(device.getDevice()); + if (!sourceList.isEmpty()) { + // Use random device in the group within the sharing session to + // represent the group. + if (BluetoothUtils.isActiveLeAudioDevice(device)) { + activeDevice = device; + } else { + inactiveDevices.add(device); + } + break; + } + } + } + if (activeDevice != null) { + deviceItems.add(buildAudioSharingDeviceItem(activeDevice)); + } + inactiveDevices.stream() + .sorted(CachedBluetoothDevice::compareTo) + .forEach( + device -> { + deviceItems.add(buildAudioSharingDeviceItem(device)); + }); + return deviceItems; + } + + /** Build {@link AudioSharingDeviceItem} from {@link CachedBluetoothDevice}. */ + public static AudioSharingDeviceItem buildAudioSharingDeviceItem( + CachedBluetoothDevice cachedDevice) { + return new AudioSharingDeviceItem(cachedDevice.getName(), cachedDevice.getGroupId()); + } +}