Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 534cbb1d authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[Screen share] Update our status to "projecting" earlier in process." into main

parents f4f58948 f85ad48e
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -377,6 +377,17 @@ flag {
    bug: "332662551"
}

flag {
    name: "status_bar_show_audio_only_projection_chip"
    namespace: "systemui"
    description: "Show chip on the left side of the status bar when a user is only sharing *audio* "
        "during a media projection"
    bug: "373308507"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "status_bar_use_repos_for_call_chip"
    namespace: "systemui"
+35 −2
Original line number Diff line number Diff line
@@ -21,10 +21,13 @@ import android.media.projection.MediaProjectionInfo
import android.os.Binder
import android.os.Handler
import android.os.UserHandle
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.ContentRecordingSession
import android.view.Display
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.applicationCoroutineScope
@@ -74,7 +77,8 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
        }

    @Test
    fun mediaProjectionState_onStart_emitsNotProjecting() =
    @DisableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
    fun mediaProjectionState_onStart_flagOff_emitsNotProjecting() =
        testScope.runTest {
            val state by collectLastValue(repo.mediaProjectionState)

@@ -83,6 +87,35 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
            assertThat(state).isEqualTo(MediaProjectionState.NotProjecting)
        }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
    fun mediaProjectionState_onStart_flagOn_emitsProjectingNoScreen() =
        testScope.runTest {
            val state by collectLastValue(repo.mediaProjectionState)

            fakeMediaProjectionManager.dispatchOnStart()

            assertThat(state).isInstanceOf(MediaProjectionState.Projecting.NoScreen::class.java)
        }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
    fun mediaProjectionState_noScreen_hasHostPackage() =
        testScope.runTest {
            val state by collectLastValue(repo.mediaProjectionState)

            val info =
                MediaProjectionInfo(
                    /* packageName= */ "com.media.projection.repository.test",
                    /* handle= */ UserHandle.getUserHandleForUid(UserHandle.myUserId()),
                    /* launchCookie = */ null,
                )
            fakeMediaProjectionManager.dispatchOnStart(info)

            assertThat((state as MediaProjectionState.Projecting).hostPackage)
                .isEqualTo("com.media.projection.repository.test")
        }

    @Test
    fun mediaProjectionState_onStop_emitsNotProjecting() =
        testScope.runTest {
@@ -212,7 +245,7 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
                )
            fakeMediaProjectionManager.dispatchOnSessionSet(
                info = info,
                session = ContentRecordingSession.createTaskSession(token.asBinder())
                session = ContentRecordingSession.createTaskSession(token.asBinder()),
            )

            assertThat((state as MediaProjectionState.Projecting.SingleTask).hostPackage)
+12 −11
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
        createAndSetDelegate(
            MediaProjectionState.Projecting.EntireScreen(
                HOST_PACKAGE,
                hostDeviceName = "My Favorite Device"
                hostDeviceName = "My Favorite Device",
            )
        )

@@ -118,8 +118,8 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
            MediaProjectionState.Projecting.SingleTask(
                HOST_PACKAGE,
                hostDeviceName = null,
                createTask(taskId = 1, baseIntent = baseIntent)
            ),
                createTask(taskId = 1, baseIntent = baseIntent),
            )
        )

        underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
@@ -141,8 +141,8 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
            MediaProjectionState.Projecting.SingleTask(
                HOST_PACKAGE,
                hostDeviceName = "My Favorite Device",
                createTask(taskId = 1, baseIntent = baseIntent)
            ),
                createTask(taskId = 1, baseIntent = baseIntent),
            )
        )

        underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
@@ -169,8 +169,8 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
            MediaProjectionState.Projecting.SingleTask(
                HOST_PACKAGE,
                hostDeviceName = null,
                createTask(taskId = 1, baseIntent = baseIntent)
            ),
                createTask(taskId = 1, baseIntent = baseIntent),
            )
        )

        underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
@@ -198,7 +198,7 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
                HOST_PACKAGE,
                hostDeviceName = "My Favorite Device",
                createTask(taskId = 1, baseIntent = baseIntent),
            ),
            )
        )

        underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
@@ -235,7 +235,7 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
            verify(sysuiDialog)
                .setPositiveButton(
                    eq(R.string.cast_to_other_device_stop_dialog_button),
                    clickListener.capture()
                    clickListener.capture(),
                )

            // Verify that clicking the button stops the recording
@@ -254,7 +254,8 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
                kosmos.applicationContext,
                stopAction = kosmos.mediaProjectionChipInteractor::stopProjecting,
                ProjectionChipModel.Projecting(
                    ProjectionChipModel.Type.CAST_TO_OTHER_DEVICE,
                    ProjectionChipModel.Receiver.CastToOtherDevice,
                    ProjectionChipModel.ContentType.Screen,
                    state,
                ),
            )
@@ -268,7 +269,7 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
            MediaProjectionState.Projecting.SingleTask(
                HOST_PACKAGE,
                hostDeviceName = null,
                createTask(taskId = 1)
                createTask(taskId = 1),
            )
    }
}
+41 −24
Original line number Diff line number Diff line
@@ -17,9 +17,11 @@
package com.android.systemui.statusbar.chips.casttootherdevice.ui.viewmodel

import android.content.DialogInterface
import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.filters.SmallTest
import com.android.internal.jank.Cuj
import com.android.systemui.Flags.FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.mockDialogTransitionAnimator
@@ -134,6 +136,29 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
                .isEqualTo(R.string.cast_screen_to_other_device_chip_accessibility_label)
        }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
    fun chip_projectionIsAudioOnly_otherDevicePackage_isShownAsIconOnly() =
        testScope.runTest {
            val latest by collectLastValue(underTest.chip)
            mediaRouterRepo.castDevices.value = emptyList()

            mediaProjectionRepo.mediaProjectionState.value =
                MediaProjectionState.Projecting.NoScreen(
                    hostPackage = CAST_TO_OTHER_DEVICES_PACKAGE
                )

            assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.IconOnly::class.java)
            val icon =
                (((latest as OngoingActivityChipModel.Shown).icon)
                        as OngoingActivityChipModel.ChipIcon.SingleColorIcon)
                    .impl as Icon.Resource
            assertThat(icon.res).isEqualTo(R.drawable.ic_cast_connected)
            // This content description is just generic "Casting", not "Casting screen"
            assertThat((icon.contentDescription as ContentDescription.Resource).res)
                .isEqualTo(R.string.accessibility_casting)
        }

    @Test
    fun chip_projectionIsEntireScreenState_otherDevicesPackage_isShownAsTimer_forScreen() =
        testScope.runTest {
@@ -291,6 +316,18 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {
            assertThat((latest as OngoingActivityChipModel.Shown).colors).isEqualTo(ColorsModel.Red)
        }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
    fun chip_projectionIsNoScreenState_normalPackage_isHidden() =
        testScope.runTest {
            val latest by collectLastValue(underTest.chip)

            mediaProjectionRepo.mediaProjectionState.value =
                MediaProjectionState.Projecting.NoScreen(NORMAL_PACKAGE)

            assertThat(latest).isInstanceOf(OngoingActivityChipModel.Hidden::class.java)
        }

    @Test
    fun chip_projectionIsSingleTaskState_normalPackage_isHidden() =
        testScope.runTest {
@@ -387,12 +424,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {

            clickListener!!.onClick(chipView)
            verify(kosmos.mockDialogTransitionAnimator)
                .showFromView(
                    eq(mockScreenCastDialog),
                    eq(chipBackgroundView),
                    any(),
                    anyBoolean(),
                )
                .showFromView(eq(mockScreenCastDialog), eq(chipBackgroundView), any(), anyBoolean())
        }

    @Test
@@ -412,12 +444,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {

            clickListener!!.onClick(chipView)
            verify(kosmos.mockDialogTransitionAnimator)
                .showFromView(
                    eq(mockScreenCastDialog),
                    eq(chipBackgroundView),
                    any(),
                    anyBoolean(),
                )
                .showFromView(eq(mockScreenCastDialog), eq(chipBackgroundView), any(), anyBoolean())
        }

    @Test
@@ -461,12 +488,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {

            val cujCaptor = argumentCaptor<DialogCuj>()
            verify(kosmos.mockDialogTransitionAnimator)
                .showFromView(
                    any(),
                    any(),
                    cujCaptor.capture(),
                    anyBoolean(),
                )
                .showFromView(any(), any(), cujCaptor.capture(), anyBoolean())

            assertThat(cujCaptor.firstValue.cujType)
                .isEqualTo(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP)
@@ -494,12 +516,7 @@ class CastToOtherDeviceChipViewModelTest : SysuiTestCase() {

            val cujCaptor = argumentCaptor<DialogCuj>()
            verify(kosmos.mockDialogTransitionAnimator)
                .showFromView(
                    any(),
                    any(),
                    cujCaptor.capture(),
                    anyBoolean(),
                )
                .showFromView(any(), any(), cujCaptor.capture(), anyBoolean())

            assertThat(cujCaptor.firstValue.cujType)
                .isEqualTo(Cuj.CUJ_STATUS_BAR_LAUNCH_DIALOG_FROM_CHIP)
+58 −18
Original line number Diff line number Diff line
@@ -21,7 +21,9 @@ import android.content.Intent
import android.content.packageManager
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.platform.test.annotations.EnableFlags
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.Kosmos
@@ -65,7 +67,23 @@ class MediaProjectionChipInteractorTest : SysuiTestCase() {
        }

    @Test
    fun projection_singleTaskState_otherDevicesPackage_isCastToOtherDeviceType() =
    @EnableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
    fun projection_noScreenState_otherDevicesPackage_isCastToOtherAndAudio() =
        testScope.runTest {
            val latest by collectLastValue(underTest.projection)

            mediaProjectionRepo.mediaProjectionState.value =
                MediaProjectionState.Projecting.NoScreen(CAST_TO_OTHER_DEVICES_PACKAGE)

            assertThat(latest).isInstanceOf(ProjectionChipModel.Projecting::class.java)
            assertThat((latest as ProjectionChipModel.Projecting).receiver)
                .isEqualTo(ProjectionChipModel.Receiver.CastToOtherDevice)
            assertThat((latest as ProjectionChipModel.Projecting).contentType)
                .isEqualTo(ProjectionChipModel.ContentType.Audio)
        }

    @Test
    fun projection_singleTaskState_otherDevicesPackage_isCastToOtherAndScreen() =
        testScope.runTest {
            val latest by collectLastValue(underTest.projection)

@@ -73,31 +91,49 @@ class MediaProjectionChipInteractorTest : SysuiTestCase() {
                MediaProjectionState.Projecting.SingleTask(
                    CAST_TO_OTHER_DEVICES_PACKAGE,
                    hostDeviceName = null,
                    createTask(taskId = 1)
                    createTask(taskId = 1),
                )

            assertThat(latest).isInstanceOf(ProjectionChipModel.Projecting::class.java)
            assertThat((latest as ProjectionChipModel.Projecting).type)
                .isEqualTo(ProjectionChipModel.Type.CAST_TO_OTHER_DEVICE)
            assertThat((latest as ProjectionChipModel.Projecting).receiver)
                .isEqualTo(ProjectionChipModel.Receiver.CastToOtherDevice)
            assertThat((latest as ProjectionChipModel.Projecting).contentType)
                .isEqualTo(ProjectionChipModel.ContentType.Screen)
        }

    @Test
    fun projection_entireScreenState_otherDevicesPackage_isCastToOtherDeviceChipType() =
    fun projection_entireScreenState_otherDevicesPackage_isCastToOtherAndScreen() =
        testScope.runTest {
            val latest by collectLastValue(underTest.projection)

            mediaProjectionRepo.mediaProjectionState.value =
                MediaProjectionState.Projecting.EntireScreen(
                    CAST_TO_OTHER_DEVICES_PACKAGE,
                )
                MediaProjectionState.Projecting.EntireScreen(CAST_TO_OTHER_DEVICES_PACKAGE)

            assertThat(latest).isInstanceOf(ProjectionChipModel.Projecting::class.java)
            assertThat((latest as ProjectionChipModel.Projecting).type)
                .isEqualTo(ProjectionChipModel.Type.CAST_TO_OTHER_DEVICE)
            assertThat((latest as ProjectionChipModel.Projecting).receiver)
                .isEqualTo(ProjectionChipModel.Receiver.CastToOtherDevice)
            assertThat((latest as ProjectionChipModel.Projecting).contentType)
                .isEqualTo(ProjectionChipModel.ContentType.Screen)
        }

    @Test
    fun projection_singleTaskState_normalPackage_isShareToAppChipType() =
    @EnableFlags(FLAG_STATUS_BAR_SHOW_AUDIO_ONLY_PROJECTION_CHIP)
    fun projection_noScreenState_normalPackage_isShareToAppAndAudio() =
        testScope.runTest {
            val latest by collectLastValue(underTest.projection)

            mediaProjectionRepo.mediaProjectionState.value =
                MediaProjectionState.Projecting.NoScreen(NORMAL_PACKAGE)

            assertThat(latest).isInstanceOf(ProjectionChipModel.Projecting::class.java)
            assertThat((latest as ProjectionChipModel.Projecting).receiver)
                .isEqualTo(ProjectionChipModel.Receiver.ShareToApp)
            assertThat((latest as ProjectionChipModel.Projecting).contentType)
                .isEqualTo(ProjectionChipModel.ContentType.Audio)
        }

    @Test
    fun projection_singleTaskState_normalPackage_isShareToAppAndScreen() =
        testScope.runTest {
            val latest by collectLastValue(underTest.projection)

@@ -109,12 +145,14 @@ class MediaProjectionChipInteractorTest : SysuiTestCase() {
                )

            assertThat(latest).isInstanceOf(ProjectionChipModel.Projecting::class.java)
            assertThat((latest as ProjectionChipModel.Projecting).type)
                .isEqualTo(ProjectionChipModel.Type.SHARE_TO_APP)
            assertThat((latest as ProjectionChipModel.Projecting).receiver)
                .isEqualTo(ProjectionChipModel.Receiver.ShareToApp)
            assertThat((latest as ProjectionChipModel.Projecting).contentType)
                .isEqualTo(ProjectionChipModel.ContentType.Screen)
        }

    @Test
    fun projection_entireScreenState_normalPackage_isShareToAppChipType() =
    fun projection_entireScreenState_normalPackage_isShareToAppAndScreen() =
        testScope.runTest {
            val latest by collectLastValue(underTest.projection)

@@ -122,8 +160,10 @@ class MediaProjectionChipInteractorTest : SysuiTestCase() {
                MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)

            assertThat(latest).isInstanceOf(ProjectionChipModel.Projecting::class.java)
            assertThat((latest as ProjectionChipModel.Projecting).type)
                .isEqualTo(ProjectionChipModel.Type.SHARE_TO_APP)
            assertThat((latest as ProjectionChipModel.Projecting).receiver)
                .isEqualTo(ProjectionChipModel.Receiver.ShareToApp)
            assertThat((latest as ProjectionChipModel.Projecting).contentType)
                .isEqualTo(ProjectionChipModel.ContentType.Screen)
        }

    companion object {
@@ -140,14 +180,14 @@ class MediaProjectionChipInteractorTest : SysuiTestCase() {
                whenever(
                        this.checkPermission(
                            Manifest.permission.REMOTE_DISPLAY_PROVIDER,
                            CAST_TO_OTHER_DEVICES_PACKAGE
                            CAST_TO_OTHER_DEVICES_PACKAGE,
                        )
                    )
                    .thenReturn(PackageManager.PERMISSION_GRANTED)
                whenever(
                        this.checkPermission(
                            Manifest.permission.REMOTE_DISPLAY_PROVIDER,
                            NORMAL_PACKAGE
                            NORMAL_PACKAGE,
                        )
                    )
                    .thenReturn(PackageManager.PERMISSION_DENIED)
Loading