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

Commit ed63bbfe authored by Naomi Musgrave's avatar Naomi Musgrave
Browse files

[MediaProjection] transform mirrored layers when the surface resizes

Aside from resizing the VirtualDisplay from MediaProjection#createVirtualDisplay,
an app may also set a new output surface on the VirtualDisplay. This output
surface is where the mirrored layers are rendered out to, so we must transform
the mirrored layers in response to any Surface size changes.

Bug: 300481174
Test: atest WmTests:ContentRecorderTests
Change-Id: I062379b9d702fb2c3a13e5442ee14036d1a31637
parent a47ca2cc
Loading
Loading
Loading
Loading
+18 −18
Original line number Diff line number Diff line
@@ -439,6 +439,12 @@
      "group": "WM_DEBUG_TASKS",
      "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java"
    },
    "-1700778361": {
      "message": "Content Recording: Going ahead with updating recording for display %d to new bounds %s and\/or orientation %d and\/or surface size %s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_CONTENT_RECORDING",
      "at": "com\/android\/server\/wm\/ContentRecorder.java"
    },
    "-1699018375": {
      "message": "Adding activity %s to task %s callers: %s",
      "level": "INFO",
@@ -637,12 +643,6 @@
      "group": "WM_DEBUG_ORIENTATION",
      "at": "com\/android\/server\/wm\/DisplayContent.java"
    },
    "-1480264178": {
      "message": "Content Recording: Unable to update recording for display %d to new bounds %s and\/or orientation %d, since the surface is not available.",
      "level": "VERBOSE",
      "group": "WM_DEBUG_CONTENT_RECORDING",
      "at": "com\/android\/server\/wm\/ContentRecorder.java"
    },
    "-1478175541": {
      "message": "No longer animating wallpaper targets!",
      "level": "VERBOSE",
@@ -1837,12 +1837,6 @@
      "group": "WM_DEBUG_ADD_REMOVE",
      "at": "com\/android\/server\/wm\/Task.java"
    },
    "-452750194": {
      "message": "Content Recording: Going ahead with updating recording for display %d to new bounds %s and\/or orientation %d.",
      "level": "VERBOSE",
      "group": "WM_DEBUG_CONTENT_RECORDING",
      "at": "com\/android\/server\/wm\/ContentRecorder.java"
    },
    "-451552570": {
      "message": "Current focused window being animated by recents. Overriding back callback to recents controller callback.",
      "level": "DEBUG",
@@ -3067,12 +3061,6 @@
      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
    },
    "643263584": {
      "message": "Content Recording: Apply transformations of shift %d x %d, scale %f, crop %d x %d for display %d",
      "level": "VERBOSE",
      "group": "WM_DEBUG_CONTENT_RECORDING",
      "at": "com\/android\/server\/wm\/ContentRecorder.java"
    },
    "644675193": {
      "message": "Real start recents",
      "level": "DEBUG",
@@ -4093,6 +4081,12 @@
      "group": "WM_DEBUG_CONFIGURATION",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "1687944543": {
      "message": "Content Recording: Unable to update recording for display %d to new bounds %s and\/or orientation %d and\/or surface size %s, since the surface is not available.",
      "level": "VERBOSE",
      "group": "WM_DEBUG_CONTENT_RECORDING",
      "at": "com\/android\/server\/wm\/ContentRecorder.java"
    },
    "1699269281": {
      "message": "Don't organize or trigger events for untrusted displayId=%d",
      "level": "WARN",
@@ -4315,6 +4309,12 @@
      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
    },
    "1936800105": {
      "message": "Content Recording: Apply transformations of shift %d x %d, scale %f, crop (aka recorded content size) %d x %d for display %d; display has size %d x %d; surface has size %d x %d",
      "level": "VERBOSE",
      "group": "WM_DEBUG_CONTENT_RECORDING",
      "at": "com\/android\/server\/wm\/ContentRecorder.java"
    },
    "1945495497": {
      "message": "Focused window didn't have a valid surface drawn.",
      "level": "DEBUG",
+23 −10
Original line number Diff line number Diff line
@@ -82,6 +82,11 @@ final class ContentRecorder implements WindowContainerListener {
     */
    @Nullable private Rect mLastRecordedBounds = null;

    /**
     * The last size of the surface mirrored out to.
     */
    @Nullable private Point mLastConsumingSurfaceSize = new Point(0, 0);

    /**
     * The last configuration orientation.
     */
@@ -177,15 +182,17 @@ final class ContentRecorder implements WindowContainerListener {
        final Rect recordedContentBounds = mRecordedWindowContainer.getBounds();
        @Configuration.Orientation int recordedContentOrientation =
                mRecordedWindowContainer.getConfiguration().orientation;
        final Point surfaceSize = fetchSurfaceSizeIfPresent();
        if (!mLastRecordedBounds.equals(recordedContentBounds)
                || lastOrientation != recordedContentOrientation) {
            Point surfaceSize = fetchSurfaceSizeIfPresent();
                || lastOrientation != recordedContentOrientation
                || !mLastConsumingSurfaceSize.equals(surfaceSize)) {
            if (surfaceSize != null) {
                ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
                        "Content Recording: Going ahead with updating recording for display "
                                + "%d to new bounds %s and/or orientation %d.",
                                + "%d to new bounds %s and/or orientation %d and/or surface "
                                + "size %s",
                        mDisplayContent.getDisplayId(), recordedContentBounds,
                        recordedContentOrientation);
                        recordedContentOrientation, surfaceSize);
                updateMirroredSurface(mRecordedWindowContainer.getSyncTransaction(),
                        recordedContentBounds, surfaceSize);
            } else {
@@ -193,10 +200,10 @@ final class ContentRecorder implements WindowContainerListener {
                // (the display will be off if the surface is removed).
                ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
                        "Content Recording: Unable to update recording for display %d to new "
                                + "bounds %s and/or orientation %d, since the surface is not "
                                + "available.",
                                + "bounds %s and/or orientation %d and/or surface size %s, "
                                + "since the surface is not available.",
                        mDisplayContent.getDisplayId(), recordedContentBounds,
                        recordedContentOrientation);
                        recordedContentOrientation, surfaceSize);
            }
        }
    }
@@ -500,10 +507,13 @@ final class ContentRecorder implements WindowContainerListener {
        }

        ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
                "Content Recording: Apply transformations of shift %d x %d, scale %f, crop %d x "
                        + "%d for display %d",
                "Content Recording: Apply transformations of shift %d x %d, scale %f, crop (aka "
                        + "recorded content size) %d x %d for display %d; display has size %d x "
                        + "%d; surface has size %d x %d",
                shiftedX, shiftedY, scale, recordedContentBounds.width(),
                recordedContentBounds.height(), mDisplayContent.getDisplayId());
                recordedContentBounds.height(), mDisplayContent.getDisplayId(),
                mDisplayContent.getConfiguration().screenWidthDp,
                mDisplayContent.getConfiguration().screenHeightDp, surfaceSize.x, surfaceSize.y);

        transaction
                // Crop the area to capture to exclude the 'extra' wallpaper that is used
@@ -517,6 +527,8 @@ final class ContentRecorder implements WindowContainerListener {
                // the content will no longer be centered in the output surface.
                .setPosition(mRecordedSurface, shiftedX /* x */, shiftedY /* y */);
        mLastRecordedBounds = new Rect(recordedContentBounds);
        mLastConsumingSurfaceSize.x = surfaceSize.x;
        mLastConsumingSurfaceSize.y = surfaceSize.y;
        // Request to notify the client about the resize.
        mMediaProjectionManager.notifyActiveProjectionCapturedContentResized(
                mLastRecordedBounds.width(), mLastRecordedBounds.height());
@@ -525,6 +537,7 @@ final class ContentRecorder implements WindowContainerListener {
    /**
     * Returns a non-null {@link Point} if the surface is present, or null otherwise
     */
    @Nullable
    private Point fetchSurfaceSizeIfPresent() {
        // Retrieve the default size of the surface the app provided to
        // MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface,
+24 −0
Original line number Diff line number Diff line
@@ -303,6 +303,30 @@ public class ContentRecorderTests extends WindowTestsBase {
                anyFloat(), anyFloat());
    }

    /**
     * Test that resizing the output surface results in resizing the mirrored content to fit.
     */
    @Test
    public void testOnConfigurationChanged_resizeSurface() {
        mContentRecorder.setContentRecordingSession(mDisplaySession);
        mContentRecorder.updateRecording();

        // Resize the output surface.
        final Point newSurfaceSize = new Point(Math.round(sSurfaceSize.x / 2f),
                Math.round(sSurfaceSize.y * 2));
        doReturn(newSurfaceSize).when(mWm.mDisplayManagerInternal).getDisplaySurfaceDefaultSize(
                anyInt());
        mContentRecorder.onConfigurationChanged(
                mVirtualDisplayContent.getConfiguration().orientation);

        // No resize is issued, only the initial transformations when we started recording.
        verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(),
                anyFloat());
        verify(mTransaction, atLeast(2)).setMatrix(eq(mRecordedSurface), anyFloat(), anyFloat(),
                anyFloat(), anyFloat());

    }

    @Test
    public void testOnTaskOrientationConfigurationChanged_resizesSurface() {
        mContentRecorder.setContentRecordingSession(mTaskSession);