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 53daffc7859d3..8e014c61c6413 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -126,10 +126,11 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private final LocalBluetoothManager mLocalBluetoothManager; private final ActivityStarter mActivityStarter; private final DialogLaunchAnimator mDialogLaunchAnimator; - private final List mGroupMediaDevices = new CopyOnWriteArrayList<>(); private final CommonNotifCollection mNotifCollection; private final Object mMediaDevicesLock = new Object(); @VisibleForTesting + final List mGroupMediaDevices = new CopyOnWriteArrayList<>(); + @VisibleForTesting final List mMediaDevices = new CopyOnWriteArrayList<>(); final List mCachedMediaDevices = new CopyOnWriteArrayList<>(); private final List mMediaItemList = new CopyOnWriteArrayList<>(); @@ -1258,7 +1259,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, return null; } - private final MediaController.Callback mCb = new MediaController.Callback() { + @VisibleForTesting + final MediaController.Callback mCb = new MediaController.Callback() { @Override public void onMetadataChanged(MediaMetadata metadata) { mCallback.onMediaChanged(); 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 de0c6a701ef3a..299303d38f29a 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 @@ -19,6 +19,7 @@ package com.android.systemui.media.dialog; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; @@ -33,7 +34,12 @@ import static org.mockito.Mockito.when; import android.app.KeyguardManager; import android.app.Notification; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.media.AudioDeviceAttributes; import android.media.AudioManager; @@ -44,6 +50,7 @@ import android.media.NearbyDevice; import android.media.RoutingSessionInfo; import android.media.session.MediaController; import android.media.session.MediaSessionManager; +import android.media.session.PlaybackState; import android.os.PowerExemptionManager; import android.os.RemoteException; import android.service.notification.StatusBarNotification; @@ -74,6 +81,9 @@ import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; @@ -93,29 +103,54 @@ public class MediaOutputControllerTest extends SysuiTestCase { private static final String TEST_SONG = "test_song"; private static final String TEST_SESSION_ID = "test_session_id"; private static final String TEST_SESSION_NAME = "test_session_name"; - private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); - private final ActivityLaunchAnimator.Controller mActivityLaunchAnimatorController = mock( - ActivityLaunchAnimator.Controller.class); - private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( - NearbyMediaDevicesManager.class); + @Mock + private DialogLaunchAnimator mDialogLaunchAnimator; + @Mock + private ActivityLaunchAnimator.Controller mActivityLaunchAnimatorController; + @Mock + private NearbyMediaDevicesManager mNearbyMediaDevicesManager; // Mock - private MediaController mMediaController = mock(MediaController.class); - private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); - private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager = - mock(CachedBluetoothDeviceManager.class); - private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); - private MediaOutputController.Callback mCb = mock(MediaOutputController.Callback.class); - private MediaDevice mMediaDevice1 = mock(MediaDevice.class); - private MediaDevice mMediaDevice2 = mock(MediaDevice.class); - private NearbyDevice mNearbyDevice1 = mock(NearbyDevice.class); - private NearbyDevice mNearbyDevice2 = mock(NearbyDevice.class); - private MediaMetadata mMediaMetadata = mock(MediaMetadata.class); - private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class); - private ActivityStarter mStarter = mock(ActivityStarter.class); - private AudioManager mAudioManager = mock(AudioManager.class); - private KeyguardManager mKeyguardManager = mock(KeyguardManager.class); - private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); - private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class); + @Mock + private MediaController mMediaController; + @Mock + private MediaSessionManager mMediaSessionManager; + @Mock + private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager; + @Mock + private LocalBluetoothManager mLocalBluetoothManager; + @Mock + private MediaOutputController.Callback mCb; + @Mock + private MediaDevice mMediaDevice1; + @Mock + private MediaDevice mMediaDevice2; + @Mock + private NearbyDevice mNearbyDevice1; + @Mock + private NearbyDevice mNearbyDevice2; + @Mock + private MediaMetadata mMediaMetadata; + @Mock + private RoutingSessionInfo mRemoteSessionInfo; + @Mock + private ActivityStarter mStarter; + @Mock + private AudioManager mAudioManager; + @Mock + private KeyguardManager mKeyguardManager; + @Mock + private ActivityLaunchAnimator.Controller mController; + @Mock + private PowerExemptionManager mPowerExemptionManager; + @Mock + private CommonNotifCollection mNotifCollection; + @Mock + private PackageManager mPackageManager; + @Mock + private Drawable mDrawable; + @Mock + private PlaybackState mPlaybackState; + private FeatureFlags mFlags = mock(FeatureFlags.class); private View mDialogLaunchView = mock(View.class); private MediaOutputController.Callback mCallback = mock(MediaOutputController.Callback.class); @@ -131,8 +166,11 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Before public void setUp() { + 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); doReturn(mMediaSessionManager).when(mSpyContext).getSystemService( @@ -257,6 +295,34 @@ public class MediaOutputControllerTest extends SysuiTestCase { verify(mCb, never()).dismissDialog(); } + @Test + public void tryToLaunchMediaApplication_intentNotNull_startActivity() { + when(mDialogLaunchAnimator.createActivityLaunchController(any(View.class))).thenReturn( + mController); + Intent intent = new Intent(TEST_PACKAGE_NAME); + doReturn(intent).when(mPackageManager).getLaunchIntentForPackage(TEST_PACKAGE_NAME); + mMediaOutputController.start(mCallback); + + mMediaOutputController.tryToLaunchMediaApplication(mDialogLaunchView); + + verify(mStarter).startActivity(any(Intent.class), anyBoolean(), + Mockito.eq(mController)); + } + + @Test + public void tryToLaunchInAppRoutingIntent_componentNameNotNull_startActivity() { + when(mDialogLaunchAnimator.createActivityLaunchController(any(View.class))).thenReturn( + mController); + mMediaOutputController.start(mCallback); + when(mLocalMediaManager.getLinkedItemComponentName()).thenReturn( + new ComponentName(TEST_PACKAGE_NAME, "")); + + mMediaOutputController.tryToLaunchInAppRoutingIntent(TEST_DEVICE_1_ID, mDialogLaunchView); + + verify(mStarter).startActivity(any(Intent.class), anyBoolean(), + Mockito.eq(mController)); + } + @Test public void onDevicesUpdated_unregistersNearbyDevicesCallback() throws RemoteException { mMediaOutputController.start(mCb); @@ -605,6 +671,17 @@ public class MediaOutputControllerTest extends SysuiTestCase { assertThat(mMediaOutputController.isAnyDeviceTransferring()).isTrue(); } + @Test + public void isAnyDeviceTransferring_advancedLayoutSupport() { + when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true); + when(mMediaDevice1.getState()).thenReturn( + LocalMediaManager.MediaDeviceState.STATE_CONNECTING); + mMediaOutputController.start(mCb); + mMediaOutputController.onDeviceListUpdate(mMediaDevices); + + assertThat(mMediaOutputController.isAnyDeviceTransferring()).isTrue(); + } + @Test public void isPlaying_stateIsNull() { when(mMediaController.getPlaybackState()).thenReturn(null); @@ -684,22 +761,6 @@ public class MediaOutputControllerTest extends SysuiTestCase { assertThat(mMediaOutputController.getHeaderSubTitle()).isEqualTo(TEST_ARTIST); } - @Test - public void connectDevice_verifyConnect() { - when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); - - mMediaOutputController.connectDevice(mMediaDevice1); - - // Wait for background thread execution - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - verify(mLocalMediaManager).connectDevice(mMediaDevice1); - } - @Test public void getActiveRemoteMediaDevice_isSystemSession_returnSession() { when(mRemoteSessionInfo.getId()).thenReturn(TEST_SESSION_ID); @@ -906,6 +967,56 @@ public class MediaOutputControllerTest extends SysuiTestCase { IconCompat.class); } + @Test + public void getDeviceIconCompat_deviceIconIsNotNull_returnsIcon() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); + when(mMediaDevice1.getIcon()).thenReturn(mDrawable); + + assertThat(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).isInstanceOf( + IconCompat.class); + } + + @Test + public void getDeviceIconCompat_deviceIconIsNull_returnsIcon() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); + when(mMediaDevice1.getIcon()).thenReturn(null); + + assertThat(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).isInstanceOf( + IconCompat.class); + } + + @Test + public void setColorFilter_setColorFilterToDrawable() { + mMediaOutputController.setColorFilter(mDrawable, true); + + verify(mDrawable).setColorFilter(any(PorterDuffColorFilter.class)); + } + + @Test + public void resetGroupMediaDevices_clearGroupDevices() { + final MediaDevice selectedMediaDevice1 = mock(MediaDevice.class); + final MediaDevice selectedMediaDevice2 = mock(MediaDevice.class); + final MediaDevice selectableMediaDevice1 = mock(MediaDevice.class); + final MediaDevice selectableMediaDevice2 = mock(MediaDevice.class); + final List selectedMediaDevices = new ArrayList<>(); + final List selectableMediaDevices = new ArrayList<>(); + when(selectedMediaDevice1.getId()).thenReturn(TEST_DEVICE_1_ID); + when(selectedMediaDevice2.getId()).thenReturn(TEST_DEVICE_2_ID); + when(selectableMediaDevice1.getId()).thenReturn(TEST_DEVICE_3_ID); + when(selectableMediaDevice2.getId()).thenReturn(TEST_DEVICE_4_ID); + selectedMediaDevices.add(selectedMediaDevice1); + selectedMediaDevices.add(selectedMediaDevice2); + selectableMediaDevices.add(selectableMediaDevice1); + selectableMediaDevices.add(selectableMediaDevice2); + doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice(); + doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice(); + assertThat(mMediaOutputController.getGroupMediaDevices().isEmpty()).isFalse(); + + mMediaOutputController.resetGroupMediaDevices(); + + assertThat(mMediaOutputController.mGroupMediaDevices.isEmpty()).isTrue(); + } + @Test public void isVolumeControlEnabled_isCastWithVolumeFixed_returnsFalse() { when(mMediaDevice1.getDeviceType()).thenReturn( @@ -942,6 +1053,42 @@ public class MediaOutputControllerTest extends SysuiTestCase { anyLong()); } + @Test + public void setTemporaryAllowListExceptionIfNeeded_packageNameIsNull_NoAction() { + MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext, + null, + mMediaSessionManager, mLocalBluetoothManager, mStarter, + mNotifCollection, mDialogLaunchAnimator, + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager, + mKeyguardManager, mFlags); + + testMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2); + + verify(mPowerExemptionManager, never()).addToTemporaryAllowList(anyString(), anyInt(), + anyString(), + anyLong()); + } + + @Test + public void onMetadataChanged_triggersOnMetadataChanged() { + mMediaOutputController.mCallback = this.mCallback; + + mMediaOutputController.mCb.onMetadataChanged(mMediaMetadata); + + verify(mMediaOutputController.mCallback).onMediaChanged(); + } + + @Test + public void onPlaybackStateChanged_updateWithNullState_onMediaStoppedOrPaused() { + when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_PLAYING); + mMediaOutputController.mCallback = this.mCallback; + mMediaOutputController.start(mCb); + + mMediaOutputController.mCb.onPlaybackStateChanged(null); + + verify(mMediaOutputController.mCallback).onMediaStoppedOrPaused(); + } + @Test public void launchBluetoothPairing_isKeyguardLocked_dismissDialog() { when(mDialogLaunchAnimator.createActivityLaunchController(mDialogLaunchView)).thenReturn(