From 3983f096b99ffef94d198a54fb3df863ec370930 Mon Sep 17 00:00:00 2001 From: shaoweishen Date: Thu, 11 May 2023 09:53:47 +0000 Subject: [PATCH] [Output Switcher] Update device icon and Media metadata 1. add new route type and icons 2. update the way to get Media information to consist with UMO Bug: 279641026 Bug: 278728942 Test: atest MediaOutputAdapterTest MediaOutputControllerTest MediaOutputBaseDialogTest MediaOutputDialogTest Change-Id: I42f1bbc433d7471f54417332102ed7be345df5be --- .../SettingsLib/res/drawable/ic_media_car.xml | 25 +++++ .../res/drawable/ic_media_computer.xml | 25 +++++ .../res/drawable/ic_media_game_console.xml | 25 +++++ .../res/drawable/ic_media_smartwatch.xml | 25 +++++ .../res/drawable/ic_media_tablet.xml | 25 +++++ .../settingslib/media/InfoMediaDevice.java | 48 +++++----- .../settingslib/media/InfoMediaManager.java | 14 ++- .../media/InfoMediaDeviceTest.java | 70 ++++++++------ .../MediaOutputBroadcastDialogFactory.kt | 6 +- .../media/dialog/MediaOutputController.java | 45 ++++++--- .../media/dialog/MediaOutputDialogFactory.kt | 6 +- .../dialog/MediaOutputBaseDialogTest.java | 4 +- .../MediaOutputBroadcastDialogTest.java | 4 +- .../dialog/MediaOutputControllerTest.java | 96 ++++++++++++++----- .../media/dialog/MediaOutputDialogTest.java | 12 ++- 15 files changed, 330 insertions(+), 100 deletions(-) create mode 100644 packages/SettingsLib/res/drawable/ic_media_car.xml create mode 100644 packages/SettingsLib/res/drawable/ic_media_computer.xml create mode 100644 packages/SettingsLib/res/drawable/ic_media_game_console.xml create mode 100644 packages/SettingsLib/res/drawable/ic_media_smartwatch.xml create mode 100644 packages/SettingsLib/res/drawable/ic_media_tablet.xml diff --git a/packages/SettingsLib/res/drawable/ic_media_car.xml b/packages/SettingsLib/res/drawable/ic_media_car.xml new file mode 100644 index 0000000000000..452e7bb5f9c07 --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_media_car.xml @@ -0,0 +1,25 @@ + + + + diff --git a/packages/SettingsLib/res/drawable/ic_media_computer.xml b/packages/SettingsLib/res/drawable/ic_media_computer.xml new file mode 100644 index 0000000000000..2aa6f8e319158 --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_media_computer.xml @@ -0,0 +1,25 @@ + + + + diff --git a/packages/SettingsLib/res/drawable/ic_media_game_console.xml b/packages/SettingsLib/res/drawable/ic_media_game_console.xml new file mode 100644 index 0000000000000..8e422ac30c038 --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_media_game_console.xml @@ -0,0 +1,25 @@ + + + + diff --git a/packages/SettingsLib/res/drawable/ic_media_smartwatch.xml b/packages/SettingsLib/res/drawable/ic_media_smartwatch.xml new file mode 100644 index 0000000000000..9c734857c2cd1 --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_media_smartwatch.xml @@ -0,0 +1,25 @@ + + + + diff --git a/packages/SettingsLib/res/drawable/ic_media_tablet.xml b/packages/SettingsLib/res/drawable/ic_media_tablet.xml new file mode 100644 index 0000000000000..c773b96dade6f --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_media_tablet.xml @@ -0,0 +1,25 @@ + + + + diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java index c036fdb7982f7..632120e77c87a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java @@ -15,10 +15,14 @@ */ package com.android.settingslib.media; -import static android.media.MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK; -import static android.media.MediaRoute2Info.FEATURE_REMOTE_VIDEO_PLAYBACK; import static android.media.MediaRoute2Info.TYPE_GROUP; +import static android.media.MediaRoute2Info.TYPE_REMOTE_CAR; +import static android.media.MediaRoute2Info.TYPE_REMOTE_COMPUTER; +import static android.media.MediaRoute2Info.TYPE_REMOTE_GAME_CONSOLE; +import static android.media.MediaRoute2Info.TYPE_REMOTE_SMARTWATCH; import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER; +import static android.media.MediaRoute2Info.TYPE_REMOTE_TABLET; +import static android.media.MediaRoute2Info.TYPE_REMOTE_TABLET_DOCKED; import static android.media.MediaRoute2Info.TYPE_REMOTE_TV; import android.content.Context; @@ -31,8 +35,6 @@ import androidx.annotation.VisibleForTesting; import com.android.settingslib.R; -import java.util.List; - /** * InfoMediaDevice extends MediaDevice to represents wifi device. */ @@ -69,13 +71,12 @@ public class InfoMediaDevice extends MediaDevice { @Override public Drawable getIconWithoutBackground() { - return mContext.getDrawable(getDrawableResIdByFeature()); + return mContext.getDrawable(getDrawableResIdByType()); } @VisibleForTesting - // MediaRoute2Info.getType was made public on API 34, but exists since API 30. @SuppressWarnings("NewApi") - int getDrawableResId() { + int getDrawableResIdByType() { int resId; switch (mRouteInfo.getType()) { case TYPE_GROUP: @@ -84,6 +85,24 @@ public class InfoMediaDevice extends MediaDevice { case TYPE_REMOTE_TV: resId = R.drawable.ic_media_display_device; break; + case TYPE_REMOTE_TABLET: + resId = R.drawable.ic_media_tablet; + break; + case TYPE_REMOTE_TABLET_DOCKED: + resId = R.drawable.ic_dock_device; + break; + case TYPE_REMOTE_COMPUTER: + resId = R.drawable.ic_media_computer; + break; + case TYPE_REMOTE_GAME_CONSOLE: + resId = R.drawable.ic_media_game_console; + break; + case TYPE_REMOTE_CAR: + resId = R.drawable.ic_media_car; + break; + case TYPE_REMOTE_SMARTWATCH: + resId = R.drawable.ic_media_smartwatch; + break; case TYPE_REMOTE_SPEAKER: default: resId = R.drawable.ic_media_speaker_device; @@ -92,21 +111,6 @@ public class InfoMediaDevice extends MediaDevice { return resId; } - @VisibleForTesting - int getDrawableResIdByFeature() { - int resId; - final List features = mRouteInfo.getFeatures(); - if (features.contains(FEATURE_REMOTE_GROUP_PLAYBACK)) { - resId = R.drawable.ic_media_group_device; - } else if (features.contains(FEATURE_REMOTE_VIDEO_PLAYBACK)) { - resId = R.drawable.ic_media_display_device; - } else { - resId = R.drawable.ic_media_speaker_device; - } - - return resId; - } - @Override public String getId() { return MediaDeviceUtils.getId(mRouteInfo); diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java index 82c6f11346372..3fcb7f3981853 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java @@ -23,7 +23,13 @@ import static android.media.MediaRoute2Info.TYPE_GROUP; import static android.media.MediaRoute2Info.TYPE_HDMI; import static android.media.MediaRoute2Info.TYPE_HEARING_AID; import static android.media.MediaRoute2Info.TYPE_REMOTE_AUDIO_VIDEO_RECEIVER; +import static android.media.MediaRoute2Info.TYPE_REMOTE_CAR; +import static android.media.MediaRoute2Info.TYPE_REMOTE_COMPUTER; +import static android.media.MediaRoute2Info.TYPE_REMOTE_GAME_CONSOLE; +import static android.media.MediaRoute2Info.TYPE_REMOTE_SMARTWATCH; import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER; +import static android.media.MediaRoute2Info.TYPE_REMOTE_TABLET; +import static android.media.MediaRoute2Info.TYPE_REMOTE_TABLET_DOCKED; import static android.media.MediaRoute2Info.TYPE_REMOTE_TV; import static android.media.MediaRoute2Info.TYPE_UNKNOWN; import static android.media.MediaRoute2Info.TYPE_USB_ACCESSORY; @@ -531,7 +537,6 @@ public class InfoMediaManager extends MediaManager { @SuppressWarnings("NewApi") @VisibleForTesting void addMediaDevice(MediaRoute2Info route) { - //TODO(b/258141461): Attach flag and disable reason in MediaDevice final int deviceType = route.getType(); MediaDevice mediaDevice = null; switch (deviceType) { @@ -539,7 +544,12 @@ public class InfoMediaManager extends MediaManager { case TYPE_REMOTE_TV: case TYPE_REMOTE_SPEAKER: case TYPE_GROUP: - //TODO(b/148765806): use correct device type once api is ready. + case TYPE_REMOTE_TABLET: + case TYPE_REMOTE_TABLET_DOCKED: + case TYPE_REMOTE_COMPUTER: + case TYPE_REMOTE_GAME_CONSOLE: + case TYPE_REMOTE_CAR: + case TYPE_REMOTE_SMARTWATCH: mediaDevice = new InfoMediaDevice(mContext, mRouterManager, route, mPackageName, mPreferenceItemMap.get(route.getId())); break; diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java index c45b7f333fa1a..67a045e9a449b 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java @@ -16,11 +16,14 @@ package com.android.settingslib.media; -import static android.media.MediaRoute2Info.FEATURE_REMOTE_AUDIO_PLAYBACK; -import static android.media.MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK; -import static android.media.MediaRoute2Info.FEATURE_REMOTE_VIDEO_PLAYBACK; import static android.media.MediaRoute2Info.TYPE_GROUP; +import static android.media.MediaRoute2Info.TYPE_REMOTE_CAR; +import static android.media.MediaRoute2Info.TYPE_REMOTE_COMPUTER; +import static android.media.MediaRoute2Info.TYPE_REMOTE_GAME_CONSOLE; +import static android.media.MediaRoute2Info.TYPE_REMOTE_SMARTWATCH; import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER; +import static android.media.MediaRoute2Info.TYPE_REMOTE_TABLET; +import static android.media.MediaRoute2Info.TYPE_REMOTE_TABLET_DOCKED; import static android.media.MediaRoute2Info.TYPE_REMOTE_TV; import static com.google.common.truth.Truth.assertThat; @@ -41,8 +44,6 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; -import java.util.ArrayList; - @RunWith(RobolectricTestRunner.class) public class InfoMediaDeviceTest { @@ -100,40 +101,47 @@ public class InfoMediaDeviceTest { public void getDrawableResId_returnCorrectResId() { when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_TV); - assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo( + assertThat(mInfoMediaDevice.getDrawableResIdByType()).isEqualTo( R.drawable.ic_media_display_device); when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_SPEAKER); - assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo( + assertThat(mInfoMediaDevice.getDrawableResIdByType()).isEqualTo( R.drawable.ic_media_speaker_device); when(mRouteInfo.getType()).thenReturn(TYPE_GROUP); - assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo(R.drawable.ic_media_group_device); - } - - @Test - public void getDrawableResIdByFeature_returnCorrectResId() { - final ArrayList features = new ArrayList<>(); - features.add(FEATURE_REMOTE_VIDEO_PLAYBACK); - when(mRouteInfo.getFeatures()).thenReturn(features); - - assertThat(mInfoMediaDevice.getDrawableResIdByFeature()).isEqualTo( - R.drawable.ic_media_display_device); - - features.clear(); - features.add(FEATURE_REMOTE_AUDIO_PLAYBACK); - when(mRouteInfo.getFeatures()).thenReturn(features); - - assertThat(mInfoMediaDevice.getDrawableResIdByFeature()).isEqualTo( - R.drawable.ic_media_speaker_device); - - features.clear(); - features.add(FEATURE_REMOTE_GROUP_PLAYBACK); - when(mRouteInfo.getFeatures()).thenReturn(features); - - assertThat(mInfoMediaDevice.getDrawableResIdByFeature()).isEqualTo( + assertThat(mInfoMediaDevice.getDrawableResIdByType()).isEqualTo( R.drawable.ic_media_group_device); + + when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_TABLET); + + assertThat(mInfoMediaDevice.getDrawableResIdByType()).isEqualTo( + R.drawable.ic_media_tablet); + + when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_TABLET_DOCKED); + + assertThat(mInfoMediaDevice.getDrawableResIdByType()).isEqualTo( + R.drawable.ic_dock_device); + + when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_COMPUTER); + + assertThat(mInfoMediaDevice.getDrawableResIdByType()).isEqualTo( + R.drawable.ic_media_computer); + + when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_GAME_CONSOLE); + + assertThat(mInfoMediaDevice.getDrawableResIdByType()).isEqualTo( + R.drawable.ic_media_game_console); + + when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_CAR); + + assertThat(mInfoMediaDevice.getDrawableResIdByType()).isEqualTo( + R.drawable.ic_media_car); + + when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_SMARTWATCH); + + assertThat(mInfoMediaDevice.getDrawableResIdByType()).isEqualTo( + R.drawable.ic_media_smartwatch); } } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt index cdd00f99fa29f..a1e9995dd6950 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt @@ -29,6 +29,7 @@ import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.flags.FeatureFlags import com.android.systemui.media.nearby.NearbyMediaDevicesManager import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection import java.util.Optional import javax.inject.Inject @@ -49,7 +50,8 @@ class MediaOutputBroadcastDialogFactory @Inject constructor( private val audioManager: AudioManager, private val powerExemptionManager: PowerExemptionManager, private val keyGuardManager: KeyguardManager, - private val featureFlags: FeatureFlags + private val featureFlags: FeatureFlags, + private val userTracker: UserTracker ) { var mediaOutputBroadcastDialog: MediaOutputBroadcastDialog? = null @@ -61,7 +63,7 @@ class MediaOutputBroadcastDialogFactory @Inject constructor( val controller = MediaOutputController(context, packageName, mediaSessionManager, lbm, starter, notifCollection, dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager, - powerExemptionManager, keyGuardManager, featureFlags) + powerExemptionManager, keyGuardManager, featureFlags, userTracker) val dialog = MediaOutputBroadcastDialog(context, aboveStatusBar, broadcastSender, controller) mediaOutputBroadcastDialog = dialog 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 822644b8e5738..2713642cf3f96 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -49,6 +49,7 @@ import android.media.MediaRoute2Info; import android.media.NearbyDevice; import android.media.RoutingSessionInfo; import android.media.session.MediaController; +import android.media.session.MediaSession; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.IBinder; @@ -86,6 +87,7 @@ import com.android.systemui.flags.Flags; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.monet.ColorScheme; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.phone.SystemUIDialog; @@ -165,6 +167,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private float mInactiveRadius; private float mActiveRadius; private FeatureFlags mFeatureFlags; + private UserTracker mUserTracker; public enum BroadcastNotifyDialog { ACTION_FIRST_LAUNCH, @@ -181,7 +184,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, AudioManager audioManager, PowerExemptionManager powerExemptionManager, KeyguardManager keyGuardManager, - FeatureFlags featureFlags) { + FeatureFlags featureFlags, + UserTracker userTracker) { mContext = context; mPackageName = packageName; mMediaSessionManager = mediaSessionManager; @@ -192,6 +196,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mPowerExemptionManager = powerExemptionManager; mKeyGuardManager = keyGuardManager; mFeatureFlags = featureFlags; + mUserTracker = userTracker; InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); @@ -232,16 +237,13 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mNearbyMediaDevicesManager.registerNearbyDevicesCallback(this); } if (!TextUtils.isEmpty(mPackageName)) { - for (MediaController controller : mMediaSessionManager.getActiveSessions(null)) { - if (TextUtils.equals(controller.getPackageName(), mPackageName)) { - mMediaController = controller; - mMediaController.unregisterCallback(mCb); - if (mMediaController.getPlaybackState() != null) { - mCurrentState = mMediaController.getPlaybackState().getState(); - } - mMediaController.registerCallback(mCb); - break; + mMediaController = getMediaController(); + if (mMediaController != null) { + mMediaController.unregisterCallback(mCb); + if (mMediaController.getPlaybackState() != null) { + mCurrentState = mMediaController.getPlaybackState().getState(); } + mMediaController.registerCallback(mCb); } } if (mMediaController == null) { @@ -284,6 +286,26 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mNearbyDeviceInfoMap.clear(); } + private MediaController getMediaController() { + for (NotificationEntry entry : mNotifCollection.getAllNotifs()) { + final Notification notification = entry.getSbn().getNotification(); + if (notification.isMediaNotification() + && TextUtils.equals(entry.getSbn().getPackageName(), mPackageName)) { + MediaSession.Token token = notification.extras.getParcelable( + Notification.EXTRA_MEDIA_SESSION, + MediaSession.Token.class); + return new MediaController(mContext, token); + } + } + for (MediaController controller : mMediaSessionManager.getActiveSessionsForUser(null, + mUserTracker.getUserHandle())) { + if (TextUtils.equals(controller.getPackageName(), mPackageName)) { + return controller; + } + } + return null; + } + @Override public void onDeviceListUpdate(List devices) { boolean isListEmpty = @@ -1011,7 +1033,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, MediaOutputController controller = new MediaOutputController(mContext, mPackageName, mMediaSessionManager, mLocalBluetoothManager, mActivityStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), - mAudioManager, mPowerExemptionManager, mKeyGuardManager, mFeatureFlags); + mAudioManager, mPowerExemptionManager, mKeyGuardManager, mFeatureFlags, + mUserTracker); MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true, broadcastSender, controller); dialog.show(); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt index 7dbf876bb3776..802488668f16a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt @@ -32,6 +32,7 @@ import com.android.systemui.media.nearby.NearbyMediaDevicesManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection import com.android.systemui.flags.FeatureFlags +import com.android.systemui.settings.UserTracker import java.util.Optional import javax.inject.Inject @@ -51,7 +52,8 @@ class MediaOutputDialogFactory @Inject constructor( private val audioManager: AudioManager, private val powerExemptionManager: PowerExemptionManager, private val keyGuardManager: KeyguardManager, - private val featureFlags: FeatureFlags + private val featureFlags: FeatureFlags, + private val userTracker: UserTracker ) { companion object { private const val INTERACTION_JANK_TAG = "media_output" @@ -67,7 +69,7 @@ class MediaOutputDialogFactory @Inject constructor( context, packageName, mediaSessionManager, lbm, starter, notifCollection, dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager, - powerExemptionManager, keyGuardManager, featureFlags) + powerExemptionManager, keyGuardManager, featureFlags, userTracker) val dialog = MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger) mediaOutputDialog = dialog 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 480d59c5e8bfd..f79c53d10b524 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 @@ -54,6 +54,7 @@ import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import org.junit.Before; @@ -91,6 +92,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private KeyguardManager mKeyguardManager = mock(KeyguardManager.class); private FeatureFlags mFlags = mock(FeatureFlags.class); + private UserTracker mUserTracker = mock(UserTracker.class); private List mMediaControllers = new ArrayList<>(); private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl; @@ -123,7 +125,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender, mMediaOutputController); mMediaOutputBaseDialogImpl.onCreate(new Bundle()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java index 891a6f8a102cb..705b485ce1b4a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java @@ -50,6 +50,7 @@ import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import org.junit.After; @@ -95,6 +96,7 @@ public class MediaOutputBroadcastDialogTest extends SysuiTestCase { private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private KeyguardManager mKeyguardManager = mock(KeyguardManager.class); private FeatureFlags mFlags = mock(FeatureFlags.class); + private UserTracker mUserTracker = mock(UserTracker.class); private MediaOutputBroadcastDialog mMediaOutputBroadcastDialog; private MediaOutputController mMediaOutputController; @@ -109,7 +111,7 @@ public class MediaOutputBroadcastDialogTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputBroadcastDialog = new MediaOutputBroadcastDialog(mContext, false, mBroadcastSender, mMediaOutputController); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index 299303d38f29a..8f7bad6a1a83c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.app.KeyguardManager; @@ -48,13 +49,18 @@ import android.media.MediaMetadata; import android.media.MediaRoute2Info; import android.media.NearbyDevice; import android.media.RoutingSessionInfo; +import android.media.session.ISessionController; import android.media.session.MediaController; +import android.media.session.MediaSession; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; +import android.os.Bundle; import android.os.PowerExemptionManager; import android.os.RemoteException; +import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; import android.text.TextUtils; import android.view.View; @@ -73,6 +79,7 @@ import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; @@ -91,6 +98,7 @@ import java.util.Optional; @SmallTest @RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) public class MediaOutputControllerTest extends SysuiTestCase { private static final String TEST_PACKAGE_NAME = "com.test.package.name"; @@ -111,7 +119,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { private NearbyMediaDevicesManager mNearbyMediaDevicesManager; // Mock @Mock - private MediaController mMediaController; + private MediaController mSessionMediaController; @Mock private MediaSessionManager mMediaSessionManager; @Mock @@ -151,10 +159,15 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Mock private PlaybackState mPlaybackState; + @Mock + private UserTracker mUserTracker; + private FeatureFlags mFlags = mock(FeatureFlags.class); private View mDialogLaunchView = mock(View.class); private MediaOutputController.Callback mCallback = mock(MediaOutputController.Callback.class); + final Notification mNotification = mock(Notification.class); + private Context mSpyContext; private MediaOutputController mMediaOutputController; private LocalMediaManager mLocalMediaManager; @@ -169,10 +182,14 @@ public class MediaOutputControllerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mContext.setMockPackageManager(mPackageManager); mSpyContext = spy(mContext); - when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME); - when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState); - mMediaControllers.add(mMediaController); - when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers); + final UserHandle userHandle = mock(UserHandle.class); + when(mUserTracker.getUserHandle()).thenReturn(userHandle); + when(mSessionMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME); + when(mSessionMediaController.getPlaybackState()).thenReturn(mPlaybackState); + mMediaControllers.add(mSessionMediaController); + when(mMediaSessionManager.getActiveSessionsForUser(any(), + Mockito.eq(userHandle))).thenReturn( + mMediaControllers); doReturn(mMediaSessionManager).when(mSpyContext).getSystemService( MediaSessionManager.class); when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn( @@ -182,7 +199,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(false); when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ROUTES_PROCESSING)).thenReturn(false); mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager); @@ -205,6 +222,24 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mNearbyDevice2.getRangeZone()).thenReturn(NearbyDevice.RANGE_CLOSE); mNearbyDevices.add(mNearbyDevice1); mNearbyDevices.add(mNearbyDevice2); + + final List entryList = new ArrayList<>(); + final NotificationEntry entry = mock(NotificationEntry.class); + final StatusBarNotification sbn = mock(StatusBarNotification.class); + final Bundle bundle = mock(Bundle.class); + final MediaSession.Token token = mock(MediaSession.Token.class); + final ISessionController binder = mock(ISessionController.class); + entryList.add(entry); + + when(mNotification.isMediaNotification()).thenReturn(false); + when(mNotifCollection.getAllNotifs()).thenReturn(entryList); + when(entry.getSbn()).thenReturn(sbn); + when(sbn.getNotification()).thenReturn(mNotification); + when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME); + mNotification.extras = bundle; + when(bundle.getParcelable(Notification.EXTRA_MEDIA_SESSION, + MediaSession.Token.class)).thenReturn(token); + when(token.getBinder()).thenReturn(binder); } @Test @@ -227,10 +262,19 @@ public class MediaOutputControllerTest extends SysuiTestCase { } @Test - public void start_withPackageName_verifyMediaControllerInit() { + public void start_notificationNotFound_mediaControllerInitFromSession() { mMediaOutputController.start(mCb); - verify(mMediaController).registerCallback(any()); + verify(mSessionMediaController).registerCallback(any()); + } + + @Test + public void start_MediaNotificationFound_mediaControllerNotInitFromSession() { + when(mNotification.isMediaNotification()).thenReturn(true); + mMediaOutputController.start(mCb); + + verify(mSessionMediaController, never()).registerCallback(any()); + verifyZeroInteractions(mMediaSessionManager); } @Test @@ -239,11 +283,11 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); mMediaOutputController.start(mCb); - verify(mMediaController, never()).registerCallback(any()); + verify(mSessionMediaController, never()).registerCallback(any()); } @Test @@ -256,11 +300,11 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void stop_withPackageName_verifyMediaControllerDeinit() { mMediaOutputController.start(mCb); - reset(mMediaController); + reset(mSessionMediaController); mMediaOutputController.stop(); - verify(mMediaController).unregisterCallback(any()); + verify(mSessionMediaController).unregisterCallback(any()); } @Test @@ -269,19 +313,19 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); mMediaOutputController.start(mCb); mMediaOutputController.stop(); - verify(mMediaController, never()).unregisterCallback(any()); + verify(mSessionMediaController, never()).unregisterCallback(any()); } @Test public void stop_nearbyMediaDevicesManagerNotNull_unregistersNearbyDevicesCallback() { mMediaOutputController.start(mCb); - reset(mMediaController); + reset(mSessionMediaController); mMediaOutputController.stop(); @@ -509,7 +553,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); testMediaOutputController.start(mCb); reset(mCb); @@ -532,7 +576,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); testMediaOutputController.start(mCb); reset(mCb); @@ -568,7 +612,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); LocalMediaManager testLocalMediaManager = spy(testMediaOutputController.mLocalMediaManager); testMediaOutputController.mLocalMediaManager = testLocalMediaManager; @@ -585,7 +629,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); LocalMediaManager testLocalMediaManager = spy(testMediaOutputController.mLocalMediaManager); testMediaOutputController.mLocalMediaManager = testLocalMediaManager; @@ -684,7 +728,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void isPlaying_stateIsNull() { - when(mMediaController.getPlaybackState()).thenReturn(null); + when(mSessionMediaController.getPlaybackState()).thenReturn(null); assertThat(mMediaOutputController.isPlaying()).isFalse(); } @@ -726,7 +770,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getHeaderTitle_withoutMetadata_returnDefaultString() { - when(mMediaController.getMetadata()).thenReturn(null); + when(mSessionMediaController.getMetadata()).thenReturn(null); mMediaOutputController.start(mCb); @@ -736,7 +780,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getHeaderTitle_withMetadata_returnSongName() { - when(mMediaController.getMetadata()).thenReturn(mMediaMetadata); + when(mSessionMediaController.getMetadata()).thenReturn(mMediaMetadata); mMediaOutputController.start(mCb); @@ -745,7 +789,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getHeaderSubTitle_withoutMetadata_returnNull() { - when(mMediaController.getMetadata()).thenReturn(null); + when(mSessionMediaController.getMetadata()).thenReturn(null); mMediaOutputController.start(mCb); @@ -754,7 +798,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getHeaderSubTitle_withMetadata_returnArtistName() { - when(mMediaController.getMetadata()).thenReturn(mMediaMetadata); + when(mSessionMediaController.getMetadata()).thenReturn(mMediaMetadata); mMediaOutputController.start(mCb); @@ -868,7 +912,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); } @@ -1060,7 +1104,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); testMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2); 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 425d0bc47a4ef..f3aee48cfb56c 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 @@ -34,6 +34,7 @@ import android.media.session.MediaController; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.PowerExemptionManager; +import android.os.UserHandle; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.FeatureFlagUtils; @@ -55,12 +56,14 @@ import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import java.util.ArrayList; import java.util.List; @@ -98,6 +101,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private KeyguardManager mKeyguardManager = mock(KeyguardManager.class); private FeatureFlags mFlags = mock(FeatureFlags.class); + private UserTracker mUserTracker = mock(UserTracker.class); private List mMediaControllers = new ArrayList<>(); private MediaOutputDialog mMediaOutputDialog; @@ -119,13 +123,17 @@ public class MediaOutputDialogTest extends SysuiTestCase { when(mMediaController.getMetadata()).thenReturn(mMediaMetadata); when(mMediaMetadata.getDescription()).thenReturn(mMediaDescription); mMediaControllers.add(mMediaController); - when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers); + final UserHandle userHandle = mock(UserHandle.class); + when(mUserTracker.getUserHandle()).thenReturn(userHandle); + when(mMediaSessionManager.getActiveSessionsForUser(any(), + Mockito.eq(userHandle))).thenReturn( + mMediaControllers); mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, - mKeyguardManager, mFlags); + mKeyguardManager, mFlags, mUserTracker); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputDialog = makeTestDialog(mMediaOutputController); mMediaOutputDialog.show();