From 630373676297d3995be0500607ac29733b7ebf0f Mon Sep 17 00:00:00 2001 From: Yiyi Shen Date: Wed, 13 Dec 2023 18:51:30 +0800 Subject: [PATCH] [Audiosharing] Move time consuming work to background. Bug: 305620450 Test: manual Change-Id: I9192d8ebbcd12d0bf13d0145d8a2e47cb8da5edd --- ...udioSharingDevicePreferenceController.java | 279 ++++++++++-------- 1 file changed, 163 insertions(+), 116 deletions(-) diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java index 9329cc29d65..70859c21a20 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java @@ -47,6 +47,9 @@ 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.android.settingslib.utils.ThreadUtils; + +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; @@ -260,6 +263,9 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro return; } mLocalBtManager.getEventManager().registerCallback(this); + if (DEBUG) { + Log.d(TAG, "onStart() Register callbacks for broadcast and assistant."); + } mBroadcast.registerServiceCallBack(mExecutor, mBroadcastCallback); mAssistant.registerServiceCallBack(mExecutor, mBroadcastAssistantCallback); mBluetoothDeviceUpdater.registerCallback(); @@ -281,15 +287,11 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro return; } mLocalBtManager.getEventManager().unregisterCallback(this); - // TODO: verify the reason for failing to unregister - try { - mBroadcast.unregisterServiceCallBack(mBroadcastCallback); - mAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback); - } catch (IllegalArgumentException e) { - Log.e( - TAG, - "Fail to unregister broadcast or assistant callback due to " + e.getMessage()); + if (DEBUG) { + Log.d(TAG, "onStop() Unregister callbacks for broadcast and assistant."); } + mBroadcast.unregisterServiceCallBack(mBroadcastCallback); + mAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback); mBluetoothDeviceUpdater.unregisterCallback(); } @@ -358,6 +360,28 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro "Ignore onProfileConnectionStateChanged, no broadcast or assistant supported"); return; } + var unused = + ThreadUtils.postOnBackgroundThread( + () -> handleOnProfileStateChanged(cachedDevice, bluetoothProfile)); + } + + /** + * Initialize the controller. + * + * @param fragment The fragment to provide the context and metrics category for {@link + * AudioSharingBluetoothDeviceUpdater} and provide the host for dialogs. + */ + public void init(DashboardFragment fragment) { + mFragment = fragment; + mBluetoothDeviceUpdater = + new AudioSharingBluetoothDeviceUpdater( + fragment.getContext(), + AudioSharingDevicePreferenceController.this, + fragment.getMetricsCategory()); + } + + private void handleOnProfileStateChanged( + @NonNull CachedBluetoothDevice cachedDevice, int bluetoothProfile) { boolean isLeAudioSupported = isLeAudioSupported(cachedDevice); // For eligible (LE audio) remote device, we only check its connected LE audio profile. if (isLeAudioSupported && bluetoothProfile != BluetoothProfile.LE_AUDIO) { @@ -384,120 +408,143 @@ public class AudioSharingDevicePreferenceController extends BasePreferenceContro } if (!isLeAudioSupported) { // Handle connected ineligible (non LE audio) remote device - if (isBroadcasting()) { - // Show stop audio sharing dialog when an ineligible (non LE audio) remote device - // connected during a sharing session. - closeOpeningDialogs(); - AudioSharingStopDialogFragment.show( - mFragment, - cachedDevice.getName(), - () -> mBroadcast.stopBroadcast(mBroadcast.getLatestBroadcastId())); - } else { - // Do nothing for ineligible (non LE audio) remote device when no sharing session. - if (DEBUG) { - Log.d( - TAG, - "Ignore onProfileConnectionStateChanged for non LE audio without" - + " sharing session"); - } - } + handleOnProfileStateChangedForNonLeAudioDevice(cachedDevice); } else { - Map> groupedDevices = - 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 = - AudioSharingUtils.buildOrderedConnectedLeadAudioSharingDeviceItem( - mLocalBtManager, groupedDevices, /* filterByInSharing= */ true); - // Show audio sharing switch dialog when the third eligible (LE audio) remote device - // connected during a sharing session. - if (deviceItemsInSharingSession.size() >= 2) { - closeOpeningDialogs(); - AudioSharingDisconnectDialogFragment.show( - mFragment, - deviceItemsInSharingSession, - cachedDevice.getName(), - (AudioSharingDeviceItem item) -> { - // Remove all sources from the device user clicked - for (CachedBluetoothDevice device : - groupedDevices.get(item.getGroupId())) { - for (BluetoothLeBroadcastReceiveState source : - mAssistant.getAllSources(device.getDevice())) { - mAssistant.removeSource( - device.getDevice(), source.getSourceId()); - } - } - // Add current broadcast to the latest connected device - mAssistant.addSource( - cachedDevice.getDevice(), - mBroadcast.getLatestBluetoothLeBroadcastMetadata(), - /* isGroupOp= */ true); - }); - } else { - // Show audio sharing join dialog when the first or second eligible (LE audio) - // remote device connected during a sharing session. - closeOpeningDialogs(); - AudioSharingJoinDialogFragment.show( - mFragment, - deviceItemsInSharingSession, - cachedDevice.getName(), - () -> { - // Add current broadcast to the latest connected device - mAssistant.addSource( - cachedDevice.getDevice(), - mBroadcast.getLatestBluetoothLeBroadcastMetadata(), - /* isGroupOp= */ true); - }); - } - } else { - ArrayList deviceItems = new ArrayList<>(); - for (List devices : groupedDevices.values()) { - // Use random device in the group within the sharing session to - // represent the group. - CachedBluetoothDevice device = devices.get(0); - if (device.getGroupId() == cachedDevice.getGroupId()) { - continue; - } - deviceItems.add(AudioSharingUtils.buildAudioSharingDeviceItem(device)); - } - // Show audio sharing join dialog when the second eligible (LE audio) remote device - // connect and no sharing session. - if (deviceItems.size() == 1) { - closeOpeningDialogs(); - AudioSharingJoinDialogFragment.show( - mFragment, - deviceItems, - cachedDevice.getName(), - () -> { - mTargetSinks = new ArrayList<>(); - for (List devices : - groupedDevices.values()) { - for (CachedBluetoothDevice device : devices) { - mTargetSinks.add(device.getDevice()); - } - } - mBroadcast.startBroadcast("test", null); - }); - } + handleOnProfileStateChangedForLeAudioDevice(cachedDevice); + } + } + + private void handleOnProfileStateChangedForNonLeAudioDevice( + @NonNull CachedBluetoothDevice cachedDevice) { + if (isBroadcasting()) { + // Show stop audio sharing dialog when an ineligible (non LE audio) remote device + // connected during a sharing session. + ThreadUtils.postOnMainThread( + () -> { + closeOpeningDialogs(); + AudioSharingStopDialogFragment.show( + mFragment, + cachedDevice.getName(), + () -> mBroadcast.stopBroadcast(mBroadcast.getLatestBroadcastId())); + }); + } else { + // Do nothing for ineligible (non LE audio) remote device when no sharing session. + if (DEBUG) { + Log.d( + TAG, + "Ignore onProfileConnectionStateChanged for non LE audio without" + + " sharing session"); } } } - /** - * Initialize the controller. - * - * @param fragment The fragment to provide the context and metrics category for {@link - * AudioSharingBluetoothDeviceUpdater} and provide the host for dialogs. - */ - public void init(DashboardFragment fragment) { - mFragment = fragment; - mBluetoothDeviceUpdater = - new AudioSharingBluetoothDeviceUpdater( - fragment.getContext(), - AudioSharingDevicePreferenceController.this, - fragment.getMetricsCategory()); + private void handleOnProfileStateChangedForLeAudioDevice( + @NonNull CachedBluetoothDevice cachedDevice) { + Map> groupedDevices = + AudioSharingUtils.fetchConnectedDevicesByGroupId(mLocalBtManager); + if (isBroadcasting()) { + if (groupedDevices.containsKey(cachedDevice.getGroupId()) + && groupedDevices.get(cachedDevice.getGroupId()).stream() + .anyMatch( + device -> + AudioSharingUtils.hasBroadcastSource( + device, mLocalBtManager))) { + Log.d( + TAG, + "Automatically add another device within the same group to the sharing: " + + cachedDevice.getDevice().getAnonymizedAddress()); + addSourceToTargetDevices(ImmutableList.of(cachedDevice.getDevice())); + return; + } + // Show audio sharing switch or join dialog according to device count in the sharing + // session. + ArrayList deviceItemsInSharingSession = + AudioSharingUtils.buildOrderedConnectedLeadAudioSharingDeviceItem( + mLocalBtManager, groupedDevices, /* filterByInSharing= */ true); + // Show audio sharing switch dialog when the third eligible (LE audio) remote device + // connected during a sharing session. + if (deviceItemsInSharingSession.size() >= 2) { + ThreadUtils.postOnMainThread( + () -> { + closeOpeningDialogs(); + AudioSharingDisconnectDialogFragment.show( + mFragment, + deviceItemsInSharingSession, + cachedDevice.getName(), + (AudioSharingDeviceItem item) -> { + // Remove all sources from the device user clicked + if (groupedDevices.containsKey(item.getGroupId())) { + for (CachedBluetoothDevice device : + groupedDevices.get(item.getGroupId())) { + for (BluetoothLeBroadcastReceiveState source : + mAssistant.getAllSources( + device.getDevice())) { + mAssistant.removeSource( + device.getDevice(), + source.getSourceId()); + } + } + } + // Add current broadcast to the latest connected device + mAssistant.addSource( + cachedDevice.getDevice(), + mBroadcast.getLatestBluetoothLeBroadcastMetadata(), + /* isGroupOp= */ true); + }); + }); + } else { + // Show audio sharing join dialog when the first or second eligible (LE audio) + // remote device connected during a sharing session. + ThreadUtils.postOnMainThread( + () -> { + closeOpeningDialogs(); + AudioSharingJoinDialogFragment.show( + mFragment, + deviceItemsInSharingSession, + cachedDevice.getName(), + () -> { + // Add current broadcast to the latest connected device + mAssistant.addSource( + cachedDevice.getDevice(), + mBroadcast.getLatestBluetoothLeBroadcastMetadata(), + /* isGroupOp= */ true); + }); + }); + } + } else { + ArrayList deviceItems = new ArrayList<>(); + for (List devices : groupedDevices.values()) { + // Use random device in the group within the sharing session to represent the group. + CachedBluetoothDevice device = devices.get(0); + if (device.getGroupId() == cachedDevice.getGroupId()) { + continue; + } + deviceItems.add(AudioSharingUtils.buildAudioSharingDeviceItem(device)); + } + // Show audio sharing join dialog when the second eligible (LE audio) remote + // device connect and no sharing session. + if (deviceItems.size() == 1) { + ThreadUtils.postOnMainThread( + () -> { + closeOpeningDialogs(); + AudioSharingJoinDialogFragment.show( + mFragment, + deviceItems, + cachedDevice.getName(), + () -> { + mTargetSinks = new ArrayList<>(); + for (List devices : + groupedDevices.values()) { + for (CachedBluetoothDevice device : devices) { + mTargetSinks.add(device.getDevice()); + } + } + mBroadcast.startBroadcast("test", null); + }); + }); + } + } } private boolean isLeAudioSupported(CachedBluetoothDevice cachedDevice) {