diff options
2 files changed, 98 insertions, 47 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java index 1d2f7902b781..6ee403d50751 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java @@ -21,6 +21,7 @@ import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; import android.annotation.CallbackExecutor; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; +import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcast; @@ -62,6 +63,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; /** * LocalBluetoothLeBroadcast provides an interface between the Settings app and the functionality of @@ -88,6 +90,8 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { Settings.Secure.BLUETOOTH_LE_BROADCAST_IMPROVE_COMPATIBILITY), }; + private final Context mContext; + private final CachedBluetoothDeviceManager mDeviceManager; private BluetoothLeBroadcast mServiceBroadcast; private BluetoothLeBroadcastAssistant mServiceBroadcastAssistant; private BluetoothLeAudioContentMetadata mBluetoothLeAudioContentMetadata; @@ -256,8 +260,19 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { private final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback = new BluetoothLeBroadcastAssistant.Callback() { @Override - public void onSourceAdded( - @NonNull BluetoothDevice sink, int sourceId, int reason) {} + public void onSourceAdded(@NonNull BluetoothDevice sink, int sourceId, int reason) { + if (DEBUG) { + Log.d( + TAG, + "onSourceAdded(), sink = " + + sink + + ", reason = " + + reason + + ", sourceId = " + + sourceId); + } + updateFallbackActiveDeviceIfNeeded(); + } @Override public void onSearchStarted(int reason) {} @@ -301,6 +316,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { + ", sourceId = " + sourceId); } + updateFallbackActiveDeviceIfNeeded(); } @Override @@ -348,7 +364,9 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { } } - LocalBluetoothLeBroadcast(Context context) { + LocalBluetoothLeBroadcast(Context context, CachedBluetoothDeviceManager deviceManager) { + mContext = context; + mDeviceManager = deviceManager; mExecutor = Executors.newSingleThreadExecutor(); mBuilder = new BluetoothLeAudioContentMetadata.Builder(); mContentResolver = context.getContentResolver(); @@ -430,49 +448,6 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { mServiceBroadcast.startBroadcast(settings); } - /** - * Start the private Broadcast for personal audio sharing or qr code sharing. - * - * <p>The broadcast will use random string for both broadcast name and subgroup program info; - * The broadcast will use random string for broadcast code; The broadcast will only have one - * subgroup due to system limitation; The subgroup language will be null. - * - * <p>If the system started the LE Broadcast, then the system calls the corresponding callback - * {@link BluetoothLeBroadcast.Callback}. - */ - public void startPrivateBroadcast(int quality) { - mNewAppSourceName = "Sharing audio"; - if (mServiceBroadcast == null) { - Log.d(TAG, "The BluetoothLeBroadcast is null when starting the private broadcast."); - return; - } - if (mServiceBroadcast.getAllBroadcastMetadata().size() - >= mServiceBroadcast.getMaximumNumberOfBroadcasts()) { - Log.d(TAG, "Skip starting the broadcast due to number limit."); - return; - } - String programInfo = getProgramInfo(); - if (DEBUG) { - Log.d(TAG, "startBroadcast: language = null ,programInfo = " + programInfo); - } - // Current broadcast framework only support one subgroup - BluetoothLeBroadcastSubgroupSettings subgroupSettings = - buildBroadcastSubgroupSettings( - /* language= */ null, - programInfo, - /* improveCompatibility= */ - BluetoothLeBroadcastSubgroupSettings.QUALITY_STANDARD == quality); - BluetoothLeBroadcastSettings settings = - buildBroadcastSettings( - true, // TODO: set to false after framework fix - TextUtils.isEmpty(programInfo) ? null : programInfo, - (mBroadcastCode != null && mBroadcastCode.length > 0) - ? mBroadcastCode - : null, - ImmutableList.of(subgroupSettings)); - mServiceBroadcast.startBroadcast(settings); - } - private BluetoothLeBroadcastSettings buildBroadcastSettings( boolean isPublic, @Nullable String broadcastName, @@ -1027,4 +1002,80 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { } } } + + /** Update fallback active device if needed. */ + public void updateFallbackActiveDeviceIfNeeded() { + if (!isEnabled(null)) { + Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to no ongoing broadcast"); + return; + } + if (mServiceBroadcastAssistant == null) { + Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to assistant profile is null"); + return; + } + List<BluetoothDevice> connectedDevices = mServiceBroadcastAssistant.getConnectedDevices(); + List<BluetoothDevice> devicesInSharing = + connectedDevices.stream() + .filter( + bluetoothDevice -> { + List<BluetoothLeBroadcastReceiveState> sourceList = + mServiceBroadcastAssistant.getAllSources( + bluetoothDevice); + return !sourceList.isEmpty(); + }) + .collect(Collectors.toList()); + if (devicesInSharing.isEmpty()) { + Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to no sinks in broadcast"); + return; + } + List<BluetoothDevice> devices = + BluetoothAdapter.getDefaultAdapter().getMostRecentlyConnectedDevices(); + BluetoothDevice targetDevice = null; + // Find the earliest connected device in sharing session. + int targetDeviceIdx = -1; + for (BluetoothDevice device : devicesInSharing) { + if (devices.contains(device)) { + int idx = devices.indexOf(device); + if (idx > targetDeviceIdx) { + targetDeviceIdx = idx; + targetDevice = device; + } + } + } + if (targetDevice == null) { + Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded, target is null"); + return; + } + Log.d( + TAG, + "updateFallbackActiveDeviceIfNeeded, set active device: " + + targetDevice.getAnonymizedAddress()); + CachedBluetoothDevice targetCachedDevice = mDeviceManager.findDevice(targetDevice); + if (targetCachedDevice == null) { + Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded, fail to find cached bt device"); + return; + } + int fallbackActiveGroupId = getFallbackActiveGroupId(); + if (targetCachedDevice.getGroupId() == fallbackActiveGroupId) { + Log.d( + TAG, + "Skip updateFallbackActiveDeviceIfNeeded, already is fallback: " + + fallbackActiveGroupId); + return; + } + targetCachedDevice.setActive(); + } + + private boolean isDecryptedSource(BluetoothLeBroadcastReceiveState state) { + return state.getPaSyncState() == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED + && state.getBigEncryptionState() + == BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING; + } + + private int getFallbackActiveGroupId() { + return Settings.Secure.getInt( + mContext.getContentResolver(), + "bluetooth_le_broadcast_fallback_active_group_id", + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 119aef6da12e..79e4c374667e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -257,7 +257,7 @@ public class LocalBluetoothProfileManager { if (DEBUG) { Log.d(TAG, "Adding local LE_AUDIO_BROADCAST profile"); } - mLeAudioBroadcast = new LocalBluetoothLeBroadcast(mContext); + mLeAudioBroadcast = new LocalBluetoothLeBroadcast(mContext, mDeviceManager); // no event handler for the LE boradcast. mProfileNameMap.put(LocalBluetoothLeBroadcast.NAME, mLeAudioBroadcast); } |