[Output Switcher] Increase MediaOutputController unit test coverage

Test: atest MediaOutputControllerTest
Bug: 278857872
Change-Id: I890302c6d7643cd927bbeb592c50983e927b7869
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 53daffc..8e014c6 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 @@
     private final LocalBluetoothManager mLocalBluetoothManager;
     private final ActivityStarter mActivityStarter;
     private final DialogLaunchAnimator mDialogLaunchAnimator;
-    private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
     private final CommonNotifCollection mNotifCollection;
     private final Object mMediaDevicesLock = new Object();
     @VisibleForTesting
+    final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
+    @VisibleForTesting
     final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
     final List<MediaDevice> mCachedMediaDevices = new CopyOnWriteArrayList<>();
     private final List<MediaItem> mMediaItemList = new CopyOnWriteArrayList<>();
@@ -1258,7 +1259,8 @@
         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 de0c6a7..299303d 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 @@
 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 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.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 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 @@
     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 @@
 
     @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(
@@ -258,6 +296,34 @@
     }
 
     @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);
 
@@ -606,6 +672,17 @@
     }
 
     @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);
 
@@ -685,22 +762,6 @@
     }
 
     @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);
         when(mRemoteSessionInfo.getName()).thenReturn(TEST_SESSION_NAME);
@@ -907,6 +968,56 @@
     }
 
     @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<MediaDevice> selectedMediaDevices = new ArrayList<>();
+        final List<MediaDevice> 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(
                 MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE);
@@ -943,6 +1054,42 @@
     }
 
     @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(
                 mActivityLaunchAnimatorController);