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

Commit aba85bbd authored by Wes Okuhara's avatar Wes Okuhara
Browse files

Desktop screenshots: Multidisplay support for fullscreen screenshots

Use the ID of the display containing the pre-capture UI in the
screenshot request argument. Ensure that the display ID is honored by
the screenshot executor for screenshot requests from the pre-capture
UI.

Bug: 430361425
Test: atest PreCaptureViewModelTest
Test: atest ScreenshotInteractorTest
Flag: com.android.systemui.desktop_screen_capture
Change-Id: I5ab1ae7482510715af83af17b949f0fec3707b2e
parent 9a3c1b96
Loading
Loading
Loading
Loading
+45 −1
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.display.data.repository.FakeDisplayRepository
import com.android.systemui.display.data.repository.display
import com.android.systemui.screenshot.proxy.ScreenshotProxy
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.kotlinArgumentCaptor as ArgumentCaptor
import com.android.systemui.util.mockito.whenever
@@ -40,6 +39,7 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
@@ -319,6 +319,50 @@ class TakeScreenshotExecutorTest : SysuiTestCase() {
            screenshotExecutor.onDestroy()
        }

    @Test
    @EnableFlags(Flags.FLAG_SCREENSHOT_MULTIDISPLAY_FOCUS_CHANGE)
    fun executeScreenshots_fromScreenCaptureUI_honorsDisplayArgument() =
        testScope.runTest {
            val displayId = 1
            setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = displayId))
            val request =
                createScreenshotRequest(
                    displayId = displayId,
                    source = WindowManager.ScreenshotSource.SCREENSHOT_SCREEN_CAPTURE_UI,
                )
            val onSaved = { _: Uri? -> }
            screenshotExecutor.executeScreenshots(request, onSaved, callback)

            val dataCaptor = ArgumentCaptor<ScreenshotData>()
            verify(controller).handleScreenshot(dataCaptor.capture(), any(), any())
            assertThat(dataCaptor.value.displayId).isEqualTo(displayId)

            screenshotExecutor.onDestroy()
        }

    @Test
    @EnableFlags(Flags.FLAG_SCREENSHOT_MULTIDISPLAY_FOCUS_CHANGE)
    fun executeScreenshots_fromScreenCaptureUI_withInvalidDisplay_usesDefaultDisplay() =
        testScope.runTest {
            setDisplays(
                display(TYPE_INTERNAL, id = Display.DEFAULT_DISPLAY),
                display(TYPE_EXTERNAL, id = 1),
            )
            val request =
                createScreenshotRequest(
                    displayId = 5,
                    source = WindowManager.ScreenshotSource.SCREENSHOT_SCREEN_CAPTURE_UI,
                )
            val onSaved = { _: Uri? -> }
            screenshotExecutor.executeScreenshots(request, onSaved, callback)

            val dataCaptor = ArgumentCaptor<ScreenshotData>()
            verify(controller).handleScreenshot(dataCaptor.capture(), any(), any())
            assertThat(dataCaptor.value.displayId).isEqualTo(Display.DEFAULT_DISPLAY)

            screenshotExecutor.onDestroy()
        }

    @Test
    @EnableFlags(Flags.FLAG_SCREENSHOT_MULTIDISPLAY_FOCUS_CHANGE)
    fun executeScreenshots_keyOther_usesFocusedDisplay() =
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ constructor(
    @Background private val backgroundContext: CoroutineContext,
    @Background private val backgroundHandler: Handler,
) {
    suspend fun takeFullscreenScreenshot(displayId: Int = DEFAULT_DISPLAY) {
    suspend fun takeFullscreenScreenshot(displayId: Int) {
        val request =
            ScreenshotRequest.Builder(
                    WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
+3 −4
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ constructor(
    private val captureRegionSource = MutableStateFlow(ScreenCaptureRegion.FULLSCREEN)
    private val regionBoxSource = MutableStateFlow<Rect?>(null)

    val displayId by lazy { activity.displayId }

    val icons: ScreenCaptureIcons? by iconProvider.icons.hydratedStateOf()

    val isShowingUI: Boolean by isShowingUIFlow.hydratedStateOf()
@@ -117,10 +119,7 @@ constructor(
        hideUI()
        closeUI()

        backgroundScope.launch {
            // TODO(b/430361425) Pass in current display as argument.
            screenshotInteractor.takeFullscreenScreenshot()
        }
        backgroundScope.launch { screenshotInteractor.takeFullscreenScreenshot(displayId) }
    }

    fun takePartialScreenshot() {
+4 −2
Original line number Diff line number Diff line
@@ -209,8 +209,10 @@ constructor(
    // Return the single display to be screenshot based upon the request.
    private suspend fun getDisplayToScreenshot(screenshotRequest: ScreenshotRequest): Display {
        return when (screenshotRequest.source) {
            ScreenshotSource.SCREENSHOT_OVERVIEW ->
                // Show on the display where overview was shown if available.
            // For screenshots from Overview or the Screen Capture UI, use the display where the UI
            // was shown, if available.
            ScreenshotSource.SCREENSHOT_OVERVIEW,
            ScreenshotSource.SCREENSHOT_SCREEN_CAPTURE_UI ->
                displayRepository.getDisplay(screenshotRequest.displayId)
                    ?: displayRepository.getDisplay(Display.DEFAULT_DISPLAY)
                    ?: error("Can't find default display")
+4 −3
Original line number Diff line number Diff line
@@ -63,9 +63,10 @@ class ScreenshotInteractorTest : SysuiTestCase() {
    }

    @Test
    fun takeFullscreenScreenshot_makesCorrectRequestAndCallsScreenshotHelper() {
    fun takeFullscreenScreenshot_callsScreenshotHelper_withCorrectRequest() {
        testScope.runTest {
            interactor.takeFullscreenScreenshot()
            val displayId = 3
            interactor.takeFullscreenScreenshot(displayId)

            verify(kosmos.mockScreenshotHelper, times(1))
                .takeScreenshot(screenshotRequestCaptor.capture(), any(), isNull())
@@ -74,7 +75,7 @@ class ScreenshotInteractorTest : SysuiTestCase() {
            assertThat(capturedRequest.type).isEqualTo(WindowManager.TAKE_SCREENSHOT_FULLSCREEN)
            assertThat(capturedRequest.source)
                .isEqualTo(WindowManager.ScreenshotSource.SCREENSHOT_SCREEN_CAPTURE_UI)
            assertThat(capturedRequest.displayId).isEqualTo(DEFAULT_DISPLAY)
            assertThat(capturedRequest.displayId).isEqualTo(displayId)
        }
    }

Loading