diff options
7 files changed, 370 insertions, 54 deletions
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index f7acda7ec379..6a5416d2addf 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2283,6 +2283,10 @@ <string name="media_output_broadcast_code">Password</string> <!-- Button for change broadcast name and broadcast code [CHAR LIMIT=60] --> <string name="media_output_broadcast_dialog_save">Save</string> + <!-- The "starting" text when Broadcast is starting [CHAR LIMIT=60] --> + <string name="media_output_broadcast_starting">Starting…</string> + <!-- The button text when Broadcast start failed [CHAR LIMIT=60] --> + <string name="media_output_broadcast_start_failed">Can\u2019t broadcast</string> <!-- Label for clip data when copying the build number off QS [CHAR LIMIT=NONE]--> <string name="build_number_clip_data_label">Build number</string> diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java index bde772d95674..e5e7eb66630b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -19,7 +19,10 @@ package com.android.systemui.media.dialog; import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowInsets.Type.statusBars; +import android.annotation.NonNull; import android.app.WallpaperColors; +import android.bluetooth.BluetoothLeBroadcast; +import android.bluetooth.BluetoothLeBroadcastMetadata; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; @@ -59,6 +62,9 @@ import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.statusbar.phone.SystemUIDialog; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + /** * Base dialog for media output UI */ @@ -69,6 +75,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements private static final String EMPTY_TITLE = " "; private static final String PREF_NAME = "MediaOutputDialog"; private static final String PREF_IS_LE_BROADCAST_FIRST_LAUNCH = "PrefIsLeBroadcastFirstLaunch"; + private static final boolean DEBUG = true; private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper()); private final RecyclerView.LayoutManager mLayoutManager; @@ -91,6 +98,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements private Button mAppButton; private int mListMaxHeight; private WallpaperColors mWallpaperColors; + private Executor mExecutor; MediaOutputBaseAdapter mAdapter; @@ -103,6 +111,79 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements } }; + private final BluetoothLeBroadcast.Callback mBroadcastCallback = + new BluetoothLeBroadcast.Callback() { + @Override + public void onBroadcastStarted(int reason, int broadcastId) { + if (DEBUG) { + Log.d(TAG, "onBroadcastStarted(), reason = " + reason + + ", broadcastId = " + broadcastId); + } + mMainThreadHandler.post(() -> startLeBroadcastDialog()); + } + + @Override + public void onBroadcastStartFailed(int reason) { + if (DEBUG) { + Log.d(TAG, "onBroadcastStartFailed(), reason = " + reason); + } + handleLeBroadcastStartFailed(); + } + + @Override + public void onBroadcastMetadataChanged(int broadcastId, + @NonNull BluetoothLeBroadcastMetadata metadata) { + if (DEBUG) { + Log.d(TAG, "onBroadcastMetadataChanged(), broadcastId = " + broadcastId + + ", metadata = " + metadata); + } + mMainThreadHandler.post(() -> refresh()); + } + + @Override + public void onBroadcastStopped(int reason, int broadcastId) { + if (DEBUG) { + Log.d(TAG, "onBroadcastStopped(), reason = " + reason + + ", broadcastId = " + broadcastId); + } + mMainThreadHandler.post(() -> refresh()); + } + + @Override + public void onBroadcastStopFailed(int reason) { + if (DEBUG) { + Log.d(TAG, "onBroadcastStopFailed(), reason = " + reason); + } + mMainThreadHandler.post(() -> refresh()); + } + + @Override + public void onBroadcastUpdated(int reason, int broadcastId) { + if (DEBUG) { + Log.d(TAG, "onBroadcastUpdated(), reason = " + reason + + ", broadcastId = " + broadcastId); + } + mMainThreadHandler.post(() -> refresh()); + } + + @Override + public void onBroadcastUpdateFailed(int reason, int broadcastId) { + if (DEBUG) { + Log.d(TAG, "onBroadcastUpdateFailed(), reason = " + reason + + ", broadcastId = " + broadcastId); + } + mMainThreadHandler.post(() -> refresh()); + } + + @Override + public void onPlaybackStarted(int reason, int broadcastId) { + } + + @Override + public void onPlaybackStopped(int reason, int broadcastId) { + } + }; + public MediaOutputBaseDialog(Context context, BroadcastSender broadcastSender, MediaOutputController mediaOutputController) { super(context, R.style.Theme_SystemUI_Dialog_Media); @@ -114,6 +195,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements mLayoutManager = new LinearLayoutManager(mContext); mListMaxHeight = context.getResources().getDimensionPixelSize( R.dimen.media_output_dialog_list_max_height); + mExecutor = Executors.newSingleThreadExecutor(); } @Override @@ -171,11 +253,18 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements public void onStart() { super.onStart(); mMediaOutputController.start(this); + if(isBroadcastSupported()) { + mMediaOutputController.registerLeBroadcastServiceCallBack(mExecutor, + mBroadcastCallback); + } } @Override public void onStop() { super.onStop(); + if(isBroadcastSupported()) { + mMediaOutputController.unregisterLeBroadcastServiceCallBack(mBroadcastCallback); + } mMediaOutputController.stop(); } @@ -254,35 +343,12 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements mAdapter.notifyDataSetChanged(); } } - // Show when remote media session is available + // Show when remote media session is available or + // when the device supports BT LE audio + media is playing mStopButton.setVisibility(getStopButtonVisibility()); - if (isBroadcastSupported() && mMediaOutputController.isPlaying()) { - mStopButton.setText(R.string.media_output_broadcast); - mStopButton.setOnClickListener(v -> { - SharedPreferences sharedPref = mContext.getSharedPreferences(PREF_NAME, - Context.MODE_PRIVATE); - - if (sharedPref != null - && sharedPref.getBoolean(PREF_IS_LE_BROADCAST_FIRST_LAUNCH, true)) { - Log.d(TAG, "PREF_IS_LE_BROADCAST_FIRST_LAUNCH: true"); - - mMediaOutputController.launchLeBroadcastNotifyDialog(mDialogView, - mBroadcastSender, - MediaOutputController.BroadcastNotifyDialog.ACTION_FIRST_LAUNCH); - SharedPreferences.Editor editor = sharedPref.edit(); - editor.putBoolean(PREF_IS_LE_BROADCAST_FIRST_LAUNCH, false); - editor.apply(); - } else { - mMediaOutputController.launchMediaOutputBroadcastDialog(mDialogView, - mBroadcastSender); - } - }); - } else { - mStopButton.setOnClickListener(v -> { - mMediaOutputController.releaseSession(); - dismiss(); - }); - } + mStopButton.setEnabled(true); + mStopButton.setText(getStopButtonText()); + mStopButton.setOnClickListener(v -> onStopButtonClick()); } private Drawable resizeDrawable(Drawable drawable, int size) { @@ -301,6 +367,56 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements Bitmap.createScaledBitmap(bitmap, size, size, false)); } + protected void handleLeBroadcastStartFailed() { + mStopButton.setText(R.string.media_output_broadcast_start_failed); + mStopButton.setEnabled(false); + mMainThreadHandler.postDelayed(() -> refresh(), 3000); + } + + protected void startLeBroadcast() { + mStopButton.setText(R.string.media_output_broadcast_starting); + mStopButton.setEnabled(false); + if (!mMediaOutputController.startBluetoothLeBroadcast()) { + // If the system can't execute "broadcast start", then UI shows the error. + handleLeBroadcastStartFailed(); + } + } + + protected boolean startLeBroadcastDialogForFirstTime(){ + SharedPreferences sharedPref = mContext.getSharedPreferences(PREF_NAME, + Context.MODE_PRIVATE); + if (sharedPref != null + && sharedPref.getBoolean(PREF_IS_LE_BROADCAST_FIRST_LAUNCH, true)) { + Log.d(TAG, "PREF_IS_LE_BROADCAST_FIRST_LAUNCH: true"); + + mMediaOutputController.launchLeBroadcastNotifyDialog(mDialogView, + mBroadcastSender, + MediaOutputController.BroadcastNotifyDialog.ACTION_FIRST_LAUNCH, + (d, w) -> { + startLeBroadcast(); + }); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putBoolean(PREF_IS_LE_BROADCAST_FIRST_LAUNCH, false); + editor.apply(); + return true; + } + return false; + } + + protected void startLeBroadcastDialog() { + mMediaOutputController.launchMediaOutputBroadcastDialog(mDialogView, + mBroadcastSender); + refresh(); + } + + protected void stopLeBroadcast() { + mStopButton.setEnabled(false); + if (!mMediaOutputController.stopBluetoothLeBroadcast()) { + // If the system can't execute "broadcast stop", then UI does refresh. + mMainThreadHandler.post(() -> refresh()); + } + } + abstract Drawable getAppSourceIcon(); abstract int getHeaderIconRes(); @@ -315,6 +431,15 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements abstract int getStopButtonVisibility(); + public CharSequence getStopButtonText() { + return mContext.getText(R.string.keyboard_key_media_stop); + } + + public void onStopButtonClick() { + mMediaOutputController.releaseSession(); + dismiss(); + } + public boolean isBroadcastSupported() { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java index 494dae0532dc..9b3b3ce6109f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java @@ -142,8 +142,11 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { mBroadcastNotify = getDialogView().requireViewById(R.id.broadcast_info); mBroadcastNotify.setOnClickListener(v -> { - mMediaOutputController.launchLeBroadcastNotifyDialog(null, null, - MediaOutputController.BroadcastNotifyDialog.ACTION_BROADCAST_INFO_ICON); + mMediaOutputController.launchLeBroadcastNotifyDialog( + /* view= */ null, + /* broadcastSender= */ null, + MediaOutputController.BroadcastNotifyDialog.ACTION_BROADCAST_INFO_ICON, + /* onClickListener= */ null); }); mBroadcastName = getDialogView().requireViewById(R.id.broadcast_name_summary); mBroadcastNameEdit = getDialogView().requireViewById(R.id.broadcast_name_edit); 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 ec2a950051b7..0fbec3baffa6 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -18,10 +18,13 @@ package com.android.systemui.media.dialog; import static android.provider.Settings.ACTION_BLUETOOTH_PAIRING_SETTINGS; +import android.annotation.CallbackExecutor; import android.app.AlertDialog; import android.app.Notification; import android.app.WallpaperColors; +import android.bluetooth.BluetoothLeBroadcast; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -58,7 +61,7 @@ import androidx.mediarouter.media.MediaRouterParams; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.BluetoothUtils; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.BluetoothMediaDevice; import com.android.settingslib.media.InfoMediaManager; @@ -83,6 +86,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; import javax.inject.Inject; @@ -642,17 +646,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, } void launchLeBroadcastNotifyDialog(View mediaOutputDialog, BroadcastSender broadcastSender, - BroadcastNotifyDialog action) { + BroadcastNotifyDialog action, final DialogInterface.OnClickListener listener) { final AlertDialog.Builder builder = new AlertDialog.Builder(mContext); switch (action) { case ACTION_FIRST_LAUNCH: builder.setTitle(R.string.media_output_first_broadcast_title); builder.setMessage(R.string.media_output_first_notify_broadcast_message); builder.setNegativeButton(android.R.string.cancel, null); - builder.setPositiveButton(R.string.media_output_broadcast, - (d, w) -> { - launchMediaOutputBroadcastDialog(mediaOutputDialog, broadcastSender); - }); + builder.setPositiveButton(R.string.media_output_broadcast, listener); break; case ACTION_BROADCAST_INFO_ICON: builder.setTitle(R.string.media_output_broadcast); @@ -685,18 +686,64 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, || features.contains(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK)); } - boolean isBluetoothLeDevice(@NonNull MediaDevice device) { - if (device instanceof BluetoothMediaDevice) { - final CachedBluetoothDevice cachedDevice = - ((BluetoothMediaDevice) device).getCachedDevice(); - boolean isConnectedLeAudioDevice = - (cachedDevice != null) ? cachedDevice.isConnectedLeAudioDevice() : false; - if (DEBUG) { - Log.d(TAG, "isConnectedLeAudioDevice=" + isConnectedLeAudioDevice); - } - return isConnectedLeAudioDevice; + boolean isBroadcastSupported() { + LocalBluetoothLeBroadcast broadcast = + mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); + return broadcast != null ? true : false; + } + + boolean isBluetoothLeBroadcastEnabled() { + LocalBluetoothLeBroadcast broadcast = + mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); + if (broadcast == null) { + return false; } - return false; + return broadcast.isEnabled(null); + } + + boolean startBluetoothLeBroadcast() { + LocalBluetoothLeBroadcast broadcast = + mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); + if (broadcast == null) { + Log.d(TAG, "The broadcast profile is null"); + return false; + } + broadcast.startBroadcast(getAppSourceName(), /*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; + } + + void registerLeBroadcastServiceCallBack( + @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); + } + + void unregisterLeBroadcastServiceCallBack( + @NonNull BluetoothLeBroadcast.Callback callback) { + LocalBluetoothLeBroadcast broadcast = + mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); + if (broadcast == null) { + Log.d(TAG, "The broadcast profile is null"); + return; + } + broadcast.unregisterServiceCallBack(callback); } private boolean isPlayBackInfoLocal() { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java index fc1039780419..9248433a4a90 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java @@ -27,7 +27,6 @@ import androidx.core.graphics.drawable.IconCompat; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; -import com.android.settingslib.media.MediaDevice; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.SysUISingleton; @@ -93,18 +92,41 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { isActiveRemoteDevice = mMediaOutputController.isActiveRemoteDevice( mMediaOutputController.getCurrentConnectedMediaDevice()); } - boolean isBroadCastSupported = isBroadcastSupported(); + boolean showBroadcastButton = isBroadcastSupported() && mMediaOutputController.isPlaying(); - return (isActiveRemoteDevice || isBroadCastSupported) ? View.VISIBLE : View.GONE; + return (isActiveRemoteDevice || showBroadcastButton) ? View.VISIBLE : View.GONE; } @Override public boolean isBroadcastSupported() { - MediaDevice device = mMediaOutputController.getCurrentConnectedMediaDevice(); - if (device == null) { - return false; + return mMediaOutputController.isBroadcastSupported(); + } + + @Override + public CharSequence getStopButtonText() { + int resId = R.string.keyboard_key_media_stop; + if (isBroadcastSupported() && mMediaOutputController.isPlaying() + && !mMediaOutputController.isBluetoothLeBroadcastEnabled()) { + resId = R.string.media_output_broadcast; + } + return mContext.getText(resId); + } + + @Override + public void onStopButtonClick() { + if (isBroadcastSupported() && mMediaOutputController.isPlaying()) { + if (!mMediaOutputController.isBluetoothLeBroadcastEnabled()) { + if (startLeBroadcastDialogForFirstTime()) { + return; + } + startLeBroadcast(); + } else { + stopLeBroadcast(); + } + } else { + mMediaOutputController.releaseSession(); + dismiss(); } - return mMediaOutputController.isBluetoothLeDevice(device); } @VisibleForTesting diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java index 380fa6d50df7..7c53388c81aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java @@ -18,6 +18,7 @@ package com.android.systemui.media.dialog; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -26,18 +27,23 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; +import android.media.session.MediaController; import android.media.session.MediaSessionManager; +import android.media.session.PlaybackState; import android.os.Bundle; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; +import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import androidx.core.graphics.drawable.IconCompat; import androidx.test.filters.SmallTest; +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.SysuiTestCase; import com.android.systemui.animation.DialogLaunchAnimator; @@ -50,6 +56,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; @SmallTest @@ -61,8 +69,14 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { // Mock private MediaOutputBaseAdapter mMediaOutputBaseAdapter = mock(MediaOutputBaseAdapter.class); + private MediaController mMediaController = mock(MediaController.class); + private PlaybackState mPlaybackState = mock(PlaybackState.class); private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); + private final LocalBluetoothProfileManager mLocalBluetoothProfileManager = mock( + LocalBluetoothProfileManager.class); + private final LocalBluetoothLeBroadcast mLocalBluetoothLeBroadcast = mock( + LocalBluetoothLeBroadcast.class); private ActivityStarter mStarter = mock(ActivityStarter.class); private BroadcastSender mBroadcastSender = mock(BroadcastSender.class); private NotificationEntryManager mNotificationEntryManager = @@ -71,15 +85,26 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { NearbyMediaDevicesManager.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); + private List<MediaController> mMediaControllers = new ArrayList<>(); private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl; private MediaOutputController mMediaOutputController; private int mHeaderIconRes; private IconCompat mIconCompat; private CharSequence mHeaderTitle; private CharSequence mHeaderSubtitle; + private String mStopText; + private boolean mIsBroadcasting; @Before public void setUp() { + when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(null); + when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState); + when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_NONE); + when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE); + mMediaControllers.add(mMediaController); + when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers); + mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotificationEntryManager, mDialogLaunchAnimator, @@ -173,6 +198,59 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { verify(mMediaOutputBaseAdapter).notifyDataSetChanged(); } + @Test + public void onStart_isBroadcasting_verifyRegisterLeBroadcastServiceCallBack() { + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( + mLocalBluetoothLeBroadcast); + mIsBroadcasting = true; + + mMediaOutputBaseDialogImpl.onStart(); + + verify(mLocalBluetoothLeBroadcast).registerServiceCallBack(any(), any()); + } + + @Test + public void onStart_notBroadcasting_noRegisterLeBroadcastServiceCallBack() { + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( + mLocalBluetoothLeBroadcast); + mIsBroadcasting = false; + + mMediaOutputBaseDialogImpl.onStart(); + + verify(mLocalBluetoothLeBroadcast, never()).registerServiceCallBack(any(), any()); + } + + @Test + public void onStart_isBroadcasting_verifyUnregisterLeBroadcastServiceCallBack() { + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( + mLocalBluetoothLeBroadcast); + mIsBroadcasting = true; + + mMediaOutputBaseDialogImpl.onStop(); + + verify(mLocalBluetoothLeBroadcast).unregisterServiceCallBack(any()); + } + + @Test + public void onStop_notBroadcasting_noUnregisterLeBroadcastServiceCallBack() { + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( + mLocalBluetoothLeBroadcast); + mIsBroadcasting = false; + + mMediaOutputBaseDialogImpl.onStop(); + + verify(mLocalBluetoothLeBroadcast, never()).unregisterServiceCallBack(any()); + } + + @Test + public void refresh_checkStopText() { + mStopText = "test_string"; + mMediaOutputBaseDialogImpl.refresh(); + final Button stop = mMediaOutputBaseDialogImpl.mDialogView.requireViewById(R.id.stop); + + assertThat(stop.getText().toString()).isEqualTo(mStopText); + } + class MediaOutputBaseDialogImpl extends MediaOutputBaseDialog { MediaOutputBaseDialogImpl(Context context, BroadcastSender broadcastSender, @@ -216,5 +294,15 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { int getStopButtonVisibility() { return 0; } + + @Override + public boolean isBroadcastSupported() { + return mIsBroadcasting; + } + + @Override + public CharSequence getStopButtonText() { + return mStopText; + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index db56f875dd5c..e6ad6edcec45 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -18,13 +18,16 @@ package com.android.systemui.media.dialog; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.media.MediaRoute2Info; +import android.media.session.MediaController; import android.media.session.MediaSessionManager; +import android.media.session.PlaybackState; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; @@ -32,7 +35,9 @@ import android.view.View; 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.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.systemui.SysuiTestCase; @@ -60,7 +65,13 @@ public class MediaOutputDialogTest extends SysuiTestCase { // Mock private final MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); + private MediaController mMediaController = mock(MediaController.class); + private PlaybackState mPlaybackState = mock(PlaybackState.class); private final LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); + private final LocalBluetoothProfileManager mLocalBluetoothProfileManager = mock( + LocalBluetoothProfileManager.class); + private final LocalBluetoothLeBroadcast mLocalBluetoothLeBroadcast = mock( + LocalBluetoothLeBroadcast.class); private final ActivityStarter mStarter = mock(ActivityStarter.class); private final BroadcastSender mBroadcastSender = mock(BroadcastSender.class); private final LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class); @@ -72,12 +83,21 @@ public class MediaOutputDialogTest extends SysuiTestCase { private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); + private List<MediaController> mMediaControllers = new ArrayList<>(); private MediaOutputDialog mMediaOutputDialog; private MediaOutputController mMediaOutputController; private final List<String> mFeatures = new ArrayList<>(); @Before public void setUp() { + when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(null); + when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState); + when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_NONE); + when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE); + mMediaControllers.add(mMediaController); + when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers); + mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotificationEntryManager, mDialogLaunchAnimator, @@ -116,6 +136,13 @@ public class MediaOutputDialogTest extends SysuiTestCase { mFeatures.add(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK); assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE); + + mFeatures.clear(); + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( + mLocalBluetoothLeBroadcast); + when(mLocalBluetoothLeBroadcast.isEnabled(any())).thenReturn(false); + when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_PLAYING); + assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE); } @Test |