From e2af98571769cdd3a06cbb0a711e88e56f094361 Mon Sep 17 00:00:00 2001 From: changbetty Date: Fri, 17 Feb 2023 11:48:57 +0000 Subject: [PATCH] To set the click listener when the user clicks the switch broadcast button - Register the LE Audio Broadcast - Set the click listener for the switch button Bug: 265872244 Bug: 265611086 Test: Manual test Test: atest BroadcastDialogTest Change-Id: I084d9a2d998d7f632c2dec45e862cd0d282e87cf --- packages/SystemUI/AndroidManifest.xml | 1 + .../systemui/bluetooth/BroadcastDialog.java | 220 +++++++++++++++++- .../bluetooth/BroadcastDialogController.java | 14 +- .../media/dialog/MediaOutputController.java | 2 +- .../media/dialog/MediaOutputDialogReceiver.kt | 3 +- .../bluetooth/BroadcastDialogTest.java | 77 +++++- .../dialog/MediaOutputDialogReceiverTest.java | 2 +- 7 files changed, 308 insertions(+), 11 deletions(-) diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index dc24dce76d789..a571cae57ba42 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -346,6 +346,7 @@ + startSwitchBroadcast()); changeOutput.setOnClickListener((view) -> { mMediaOutputDialogFactory.create(mOutputPackageName, true, null); dismiss(); @@ -101,6 +199,79 @@ public class BroadcastDialog extends SystemUIDialog { }); } + @Override + public void onStop() { + super.onStop(); + unregisterBroadcastCallBack(mBroadcastCallback); + } + + void refreshSwitchBroadcastButton() { + String switchBroadcastApp = MediaDataUtils.getAppLabel(mContext, mOutputPackageName, + mContext.getString(R.string.bt_le_audio_broadcast_dialog_unknown_name)); + mSwitchBroadcast.setText(mContext.getString( + R.string.bt_le_audio_broadcast_dialog_switch_app, switchBroadcastApp), null); + mSwitchBroadcast.setEnabled(true); + } + + private void startSwitchBroadcast() { + if (DEBUG) { + Log.d(TAG, "startSwitchBroadcast"); + } + mSwitchBroadcast.setText(R.string.media_output_broadcast_starting); + mSwitchBroadcast.setEnabled(false); + //Stop the current Broadcast + if (!stopBluetoothLeBroadcast()) { + handleLeBroadcastStopFailed(); + return; + } + } + + private void registerBroadcastCallBack( + @NonNull @CallbackExecutor Executor executor, + @NonNull BluetoothLeBroadcast.Callback callback) { + LocalBluetoothLeBroadcast broadcast = + mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); + if (broadcast == null) { + Log.d(TAG, "The broadcast profile is null"); + return; + } + broadcast.registerServiceCallBack(executor, callback); + } + + private void unregisterBroadcastCallBack(@NonNull BluetoothLeBroadcast.Callback callback) { + LocalBluetoothLeBroadcast broadcast = + mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); + if (broadcast == null) { + Log.d(TAG, "The broadcast profile is null"); + return; + } + broadcast.unregisterServiceCallBack(callback); + } + + boolean startBluetoothLeBroadcast() { + LocalBluetoothLeBroadcast broadcast = + mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); + if (broadcast == null) { + Log.d(TAG, "The broadcast profile is null"); + return false; + } + String switchBroadcastApp = MediaDataUtils.getAppLabel(mContext, mOutputPackageName, + mContext.getString(R.string.bt_le_audio_broadcast_dialog_unknown_name)); + broadcast.startBroadcast(switchBroadcastApp, /*language*/ null); + return true; + } + + boolean stopBluetoothLeBroadcast() { + LocalBluetoothLeBroadcast broadcast = + mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); + if (broadcast == null) { + Log.d(TAG, "The broadcast profile is null"); + return false; + } + broadcast.stopLatestBroadcast(); + return true; + } + @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); @@ -125,4 +296,45 @@ public class BroadcastDialog extends SystemUIDialog { } } + void handleLeBroadcastStarted() { + // Waiting for the onBroadcastMetadataChanged. The UI launchs the broadcast dialog when + // the metadata is ready. + mShouldLaunchLeBroadcastDialog = true; + } + + private void handleLeBroadcastStartFailed() { + mSwitchBroadcast.setText(R.string.media_output_broadcast_start_failed); + mSwitchBroadcast.setEnabled(false); + refreshSwitchBroadcastButton(); + } + + void handleLeBroadcastMetadataChanged() { + if (mShouldLaunchLeBroadcastDialog) { + startLeBroadcastDialog(); + mShouldLaunchLeBroadcastDialog = false; + } + } + + @VisibleForTesting + void handleLeBroadcastStopped() { + mShouldLaunchLeBroadcastDialog = false; + if (!startBluetoothLeBroadcast()) { + handleLeBroadcastStartFailed(); + return; + } + } + + private void handleLeBroadcastStopFailed() { + mSwitchBroadcast.setText(R.string.media_output_broadcast_start_failed); + mSwitchBroadcast.setEnabled(false); + refreshSwitchBroadcastButton(); + } + + private void startLeBroadcastDialog() { + mBroadcastSender.sendBroadcast(new Intent() + .setPackage(mContext.getPackageName()) + .setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG) + .putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, mOutputPackageName)); + dismiss(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java index 1b699e8ea5dda..17bf1a716944d 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java @@ -16,11 +16,14 @@ package com.android.systemui.bluetooth; +import android.annotation.Nullable; import android.content.Context; import android.view.View; import com.android.internal.logging.UiEventLogger; +import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.media.dialog.MediaOutputDialogFactory; @@ -36,15 +39,21 @@ public class BroadcastDialogController { private UiEventLogger mUiEventLogger; private DialogLaunchAnimator mDialogLaunchAnimator; private MediaOutputDialogFactory mMediaOutputDialogFactory; + private final LocalBluetoothManager mLocalBluetoothManager; + private BroadcastSender mBroadcastSender; @Inject public BroadcastDialogController(Context context, UiEventLogger uiEventLogger, DialogLaunchAnimator dialogLaunchAnimator, - MediaOutputDialogFactory mediaOutputDialogFactory) { + MediaOutputDialogFactory mediaOutputDialogFactory, + @Nullable LocalBluetoothManager localBluetoothManager, + BroadcastSender broadcastSender) { mContext = context; mUiEventLogger = uiEventLogger; mDialogLaunchAnimator = dialogLaunchAnimator; mMediaOutputDialogFactory = mediaOutputDialogFactory; + mLocalBluetoothManager = localBluetoothManager; + mBroadcastSender = broadcastSender; } /** Creates a [BroadcastDialog] for the user to switch broadcast or change the output device @@ -55,7 +64,8 @@ public class BroadcastDialogController { public void createBroadcastDialog(String currentBroadcastAppName, String outputPkgName, boolean aboveStatusBar, View view) { BroadcastDialog broadcastDialog = new BroadcastDialog(mContext, mMediaOutputDialogFactory, - currentBroadcastAppName, outputPkgName, mUiEventLogger); + mLocalBluetoothManager, currentBroadcastAppName, outputPkgName, mUiEventLogger, + mBroadcastSender); if (view != null) { mDialogLaunchAnimator.showFromView(broadcastDialog, view); } else { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 2aedd36346262..84dc2851b56c9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -996,7 +996,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mAudioManager, mPowerExemptionManager, mKeyGuardManager, mFeatureFlags); MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true, broadcastSender, controller); - mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog); + dialog.show(); } String getBroadcastName() { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt index 760a42cc512c3..132bf99c3f627 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt @@ -62,7 +62,8 @@ class MediaOutputDialogReceiver @Inject constructor( private fun launchMediaOutputBroadcastDialogIfPossible(packageName: String?) { if (!packageName.isNullOrEmpty()) { - mediaOutputBroadcastDialogFactory.create(packageName, false) + mediaOutputBroadcastDialogFactory.create( + packageName, aboveStatusBar = true, view = null) } else if (DEBUG) { Log.e(TAG, "Unable to launch media output broadcast dialog. Package name is empty.") } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java index 9d16185e75c54..6fa19162b1505 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java @@ -18,7 +18,11 @@ package com.android.systemui.bluetooth; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -29,7 +33,11 @@ import android.widget.TextView; import androidx.test.filters.SmallTest; import com.android.internal.logging.UiEventLogger; +import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.systemui.R; +import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.SysuiTestCase; import com.android.systemui.media.dialog.MediaOutputDialogFactory; @@ -47,6 +55,12 @@ public class BroadcastDialogTest extends SysuiTestCase { private static final String CURRENT_BROADCAST_APP = "Music"; private static final String SWITCH_APP = "System UI"; private static final String TEST_PACKAGE = "com.android.systemui"; + private final LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); + private final LocalBluetoothProfileManager mLocalBluetoothProfileManager = mock( + LocalBluetoothProfileManager.class); + private final LocalBluetoothLeBroadcast mLocalBluetoothLeBroadcast = mock( + LocalBluetoothLeBroadcast.class); + private final BroadcastSender mBroadcastSender = mock(BroadcastSender.class); private BroadcastDialog mBroadcastDialog; private View mDialogView; private TextView mTitle; @@ -57,9 +71,11 @@ public class BroadcastDialogTest extends SysuiTestCase { @Before public void setUp() { MockitoAnnotations.initMocks(this); + when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(null); mBroadcastDialog = new BroadcastDialog(mContext, mock(MediaOutputDialogFactory.class), - CURRENT_BROADCAST_APP, TEST_PACKAGE, mock(UiEventLogger.class)); - + mLocalBluetoothManager, CURRENT_BROADCAST_APP, TEST_PACKAGE, + mock(UiEventLogger.class), mBroadcastSender); mBroadcastDialog.show(); mDialogView = mBroadcastDialog.mDialogView; } @@ -100,4 +116,61 @@ public class BroadcastDialogTest extends SysuiTestCase { assertThat(mBroadcastDialog.isShowing()).isFalse(); } + + @Test + public void onClick_withSwitchBroadcast_stopCurrentBroadcast() { + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( + mLocalBluetoothLeBroadcast); + mSwitchBroadcastAppButton = mDialogView.requireViewById(R.id.switch_broadcast); + mSwitchBroadcastAppButton.performClick(); + + verify(mLocalBluetoothLeBroadcast).stopLatestBroadcast(); + } + + @Test + public void onClick_withSwitchBroadcast_stopCurrentBroadcastFailed() { + mSwitchBroadcastAppButton = mDialogView.requireViewById(R.id.switch_broadcast); + mSwitchBroadcastAppButton.performClick(); + + assertThat(mSwitchBroadcastAppButton.getText().toString()).isEqualTo( + mContext.getString(R.string.bt_le_audio_broadcast_dialog_switch_app, SWITCH_APP)); + } + + @Test + public void handleLeBroadcastStopped_withBroadcastProfileNull_doRefreshButton() { + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(null); + mSwitchBroadcastAppButton = mDialogView.requireViewById(R.id.switch_broadcast); + + mBroadcastDialog.handleLeBroadcastStopped(); + + assertThat(mSwitchBroadcastAppButton.getText().toString()).isEqualTo( + mContext.getString(R.string.bt_le_audio_broadcast_dialog_switch_app, SWITCH_APP)); + } + + @Test + public void handleLeBroadcastStopped_withBroadcastProfile_doStartBroadcast() { + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( + mLocalBluetoothLeBroadcast); + + mBroadcastDialog.handleLeBroadcastStopped(); + + verify(mLocalBluetoothLeBroadcast).startBroadcast(eq(SWITCH_APP), any()); + } + + @Test + public void handleLeBroadcastMetadataChanged_withNotLaunchFlag_doNotDismissDialog() { + + mBroadcastDialog.handleLeBroadcastMetadataChanged(); + + assertThat(mBroadcastDialog.isShowing()).isTrue(); + } + + @Test + public void handleLeBroadcastMetadataChanged_withLaunchFlag_dismissDialog() { + + mBroadcastDialog.handleLeBroadcastStarted(); + mBroadcastDialog.handleLeBroadcastMetadataChanged(); + + assertThat(mBroadcastDialog.isShowing()).isFalse(); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java index 3d5dba3b9efcd..e2cf87a6dd621 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java @@ -92,7 +92,7 @@ public class MediaOutputDialogReceiverTest extends SysuiTestCase { verify(mMockMediaOutputDialogFactory, never()).create(any(), anyBoolean(), any()); verify(mMockMediaOutputBroadcastDialogFactory, times(1)) - .create(getContext().getPackageName(), false, null); + .create(getContext().getPackageName(), true, null); } @Test