Skip to content
Snippets Groups Projects
Commit d71737d6 authored by Naomi Musgrave's avatar Naomi Musgrave
Browse files

[MediaProjection] compare orientations of the same type

Attempted comparing orientations from different enums; manifested as wildly
incorrect transformations when handling a rotation & the virtual display
is resized.

Bug: 289976187
Test: atest WmTests:ContentRecorderTests
Test: manual check full display & single app capture with rotations
Change-Id: I10b03c5169a03b6540181b4bc4a3f47fa421f675
parent 025a384f
No related branches found
No related tags found
No related merge requests found
...@@ -3055,6 +3055,12 @@ ...@@ -3055,6 +3055,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS", "group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java" "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": { "644675193": {
"message": "Real start recents", "message": "Real start recents",
"level": "DEBUG", "level": "DEBUG",
......
...@@ -35,6 +35,7 @@ import android.os.RemoteException; ...@@ -35,6 +35,7 @@ import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.provider.DeviceConfig; import android.provider.DeviceConfig;
import android.view.ContentRecordingSession; import android.view.ContentRecordingSession;
import android.view.ContentRecordingSession.RecordContent;
import android.view.Display; import android.view.Display;
import android.view.SurfaceControl; import android.view.SurfaceControl;
...@@ -84,6 +85,7 @@ final class ContentRecorder implements WindowContainerListener { ...@@ -84,6 +85,7 @@ final class ContentRecorder implements WindowContainerListener {
/** /**
* The last configuration orientation. * The last configuration orientation.
*/ */
@Configuration.Orientation
private int mLastOrientation = ORIENTATION_UNDEFINED; private int mLastOrientation = ORIENTATION_UNDEFINED;
ContentRecorder(@NonNull DisplayContent displayContent) { ContentRecorder(@NonNull DisplayContent displayContent) {
...@@ -156,7 +158,8 @@ final class ContentRecorder implements WindowContainerListener { ...@@ -156,7 +158,8 @@ final class ContentRecorder implements WindowContainerListener {
// Retrieve the size of the region to record, and continue with the update // Retrieve the size of the region to record, and continue with the update
// if the bounds or orientation has changed. // if the bounds or orientation has changed.
final Rect recordedContentBounds = mRecordedWindowContainer.getBounds(); final Rect recordedContentBounds = mRecordedWindowContainer.getBounds();
int recordedContentOrientation = mRecordedWindowContainer.getOrientation(); @Configuration.Orientation int recordedContentOrientation =
mRecordedWindowContainer.getConfiguration().orientation;
if (!mLastRecordedBounds.equals(recordedContentBounds) if (!mLastRecordedBounds.equals(recordedContentBounds)
|| lastOrientation != recordedContentOrientation) { || lastOrientation != recordedContentOrientation) {
Point surfaceSize = fetchSurfaceSizeIfPresent(); Point surfaceSize = fetchSurfaceSizeIfPresent();
...@@ -356,7 +359,7 @@ final class ContentRecorder implements WindowContainerListener { ...@@ -356,7 +359,7 @@ final class ContentRecorder implements WindowContainerListener {
*/ */
@Nullable @Nullable
private WindowContainer retrieveRecordedWindowContainer() { private WindowContainer retrieveRecordedWindowContainer() {
final int contentToRecord = mContentRecordingSession.getContentToRecord(); @RecordContent final int contentToRecord = mContentRecordingSession.getContentToRecord();
final IBinder tokenToRecord = mContentRecordingSession.getTokenToRecord(); final IBinder tokenToRecord = mContentRecordingSession.getTokenToRecord();
switch (contentToRecord) { switch (contentToRecord) {
case RECORD_CONTENT_DISPLAY: case RECORD_CONTENT_DISPLAY:
...@@ -472,6 +475,12 @@ final class ContentRecorder implements WindowContainerListener { ...@@ -472,6 +475,12 @@ final class ContentRecorder implements WindowContainerListener {
shiftedY = (surfaceSize.y - scaledHeight) / 2; shiftedY = (surfaceSize.y - scaledHeight) / 2;
} }
ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
"Content Recording: Apply transformations of shift %d x %d, scale %f, crop %d x "
+ "%d for display %d",
shiftedX, shiftedY, scale, recordedContentBounds.width(),
recordedContentBounds.height(), mDisplayContent.getDisplayId());
transaction transaction
// Crop the area to capture to exclude the 'extra' wallpaper that is used // Crop the area to capture to exclude the 'extra' wallpaper that is used
// for parallax (b/189930234). // for parallax (b/189930234).
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package com.android.server.wm; package com.android.server.wm;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.INVALID_DISPLAY;
...@@ -76,6 +78,7 @@ import java.util.concurrent.CountDownLatch; ...@@ -76,6 +78,7 @@ import java.util.concurrent.CountDownLatch;
@RunWith(WindowTestRunner.class) @RunWith(WindowTestRunner.class)
public class ContentRecorderTests extends WindowTestsBase { public class ContentRecorderTests extends WindowTestsBase {
private static IBinder sTaskWindowContainerToken; private static IBinder sTaskWindowContainerToken;
private DisplayContent mVirtualDisplayContent;
private Task mTask; private Task mTask;
private final ContentRecordingSession mDisplaySession = private final ContentRecordingSession mDisplaySession =
ContentRecordingSession.createDisplaySession(DEFAULT_DISPLAY); ContentRecordingSession.createDisplaySession(DEFAULT_DISPLAY);
...@@ -106,11 +109,11 @@ public class ContentRecorderTests extends WindowTestsBase { ...@@ -106,11 +109,11 @@ public class ContentRecorderTests extends WindowTestsBase {
displayInfo.logicalWidth = sSurfaceSize.x; displayInfo.logicalWidth = sSurfaceSize.x;
displayInfo.logicalHeight = sSurfaceSize.y; displayInfo.logicalHeight = sSurfaceSize.y;
displayInfo.state = STATE_ON; displayInfo.state = STATE_ON;
final DisplayContent virtualDisplayContent = createNewDisplay(displayInfo); mVirtualDisplayContent = createNewDisplay(displayInfo);
final int displayId = virtualDisplayContent.getDisplayId(); final int displayId = mVirtualDisplayContent.getDisplayId();
mContentRecorder = new ContentRecorder(virtualDisplayContent, mContentRecorder = new ContentRecorder(mVirtualDisplayContent,
mMediaProjectionManagerWrapper); mMediaProjectionManagerWrapper);
spyOn(virtualDisplayContent); spyOn(mVirtualDisplayContent);
// GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
// record. // record.
...@@ -118,7 +121,7 @@ public class ContentRecorderTests extends WindowTestsBase { ...@@ -118,7 +121,7 @@ public class ContentRecorderTests extends WindowTestsBase {
mDisplaySession.setDisplayToRecord(mDefaultDisplay.mDisplayId); mDisplaySession.setDisplayToRecord(mDefaultDisplay.mDisplayId);
// GIVEN there is a window token associated with a task to record. // GIVEN there is a window token associated with a task to record.
sTaskWindowContainerToken = setUpTaskWindowContainerToken(virtualDisplayContent); sTaskWindowContainerToken = setUpTaskWindowContainerToken(mVirtualDisplayContent);
mTaskSession = ContentRecordingSession.createTaskSession(sTaskWindowContainerToken); mTaskSession = ContentRecordingSession.createTaskSession(sTaskWindowContainerToken);
mTaskSession.setVirtualDisplayId(displayId); mTaskSession.setVirtualDisplayId(displayId);
...@@ -251,7 +254,11 @@ public class ContentRecorderTests extends WindowTestsBase { ...@@ -251,7 +254,11 @@ public class ContentRecorderTests extends WindowTestsBase {
public void testOnConfigurationChanged_resizesSurface() { public void testOnConfigurationChanged_resizesSurface() {
mContentRecorder.setContentRecordingSession(mDisplaySession); mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording(); mContentRecorder.updateRecording();
mContentRecorder.onConfigurationChanged(ORIENTATION_PORTRAIT); // Ensure a different orientation when we check if something has changed.
@Configuration.Orientation final int lastOrientation =
mDisplayContent.getConfiguration().orientation == ORIENTATION_PORTRAIT
? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
mContentRecorder.onConfigurationChanged(lastOrientation);
verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(), verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(),
anyFloat()); anyFloat());
...@@ -259,13 +266,54 @@ public class ContentRecorderTests extends WindowTestsBase { ...@@ -259,13 +266,54 @@ public class ContentRecorderTests extends WindowTestsBase {
anyFloat(), anyFloat()); anyFloat(), anyFloat());
} }
@Test
public void testOnConfigurationChanged_resizesVirtualDisplay() {
final int newWidth = 55;
mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording();
// The user rotates the device, so the host app resizes the virtual display for the capture.
resizeDisplay(mDisplayContent, newWidth, sSurfaceSize.y);
resizeDisplay(mVirtualDisplayContent, newWidth, sSurfaceSize.y);
mContentRecorder.onConfigurationChanged(mDisplayContent.getConfiguration().orientation);
verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(),
anyFloat());
verify(mTransaction, atLeast(2)).setMatrix(eq(mRecordedSurface), anyFloat(), anyFloat(),
anyFloat(), anyFloat());
}
@Test
public void testOnConfigurationChanged_rotateVirtualDisplay() {
mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording();
// Change a value that we shouldn't rely upon; it has the wrong type.
mVirtualDisplayContent.setOverrideOrientation(SCREEN_ORIENTATION_FULL_SENSOR);
mContentRecorder.onConfigurationChanged(
mVirtualDisplayContent.getConfiguration().orientation);
// No resize is issued, only the initial transformations when we started recording.
verify(mTransaction).setPosition(eq(mRecordedSurface), anyFloat(),
anyFloat());
verify(mTransaction).setMatrix(eq(mRecordedSurface), anyFloat(), anyFloat(),
anyFloat(), anyFloat());
}
@Test @Test
public void testOnTaskOrientationConfigurationChanged_resizesSurface() { public void testOnTaskOrientationConfigurationChanged_resizesSurface() {
mContentRecorder.setContentRecordingSession(mTaskSession); mContentRecorder.setContentRecordingSession(mTaskSession);
mContentRecorder.updateRecording(); mContentRecorder.updateRecording();
Configuration config = mTask.getConfiguration(); Configuration config = mTask.getConfiguration();
config.orientation = ORIENTATION_PORTRAIT; // Ensure a different orientation when we compare.
@Configuration.Orientation final int orientation =
config.orientation == ORIENTATION_PORTRAIT ? ORIENTATION_LANDSCAPE
: ORIENTATION_PORTRAIT;
final Rect lastBounds = config.windowConfiguration.getBounds();
config.orientation = orientation;
config.windowConfiguration.setBounds(
new Rect(0, 0, lastBounds.height(), lastBounds.width()));
mTask.onConfigurationChanged(config); mTask.onConfigurationChanged(config);
verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(), verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(),
...@@ -278,13 +326,15 @@ public class ContentRecorderTests extends WindowTestsBase { ...@@ -278,13 +326,15 @@ public class ContentRecorderTests extends WindowTestsBase {
public void testOnTaskBoundsConfigurationChanged_notifiesCallback() { public void testOnTaskBoundsConfigurationChanged_notifiesCallback() {
mTask.getRootTask().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); mTask.getRootTask().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
final int minWidth = 222;
final int minHeight = 777;
final int recordedWidth = 333; final int recordedWidth = 333;
final int recordedHeight = 999; final int recordedHeight = 999;
final ActivityInfo info = new ActivityInfo(); final ActivityInfo info = new ActivityInfo();
info.windowLayout = new ActivityInfo.WindowLayout(-1 /* width */, info.windowLayout = new ActivityInfo.WindowLayout(-1 /* width */,
-1 /* widthFraction */, -1 /* height */, -1 /* heightFraction */, -1 /* widthFraction */, -1 /* height */, -1 /* heightFraction */,
Gravity.NO_GRAVITY, recordedWidth, recordedHeight); Gravity.NO_GRAVITY, minWidth, minHeight);
mTask.setMinDimensions(info); mTask.setMinDimensions(info);
// WHEN a recording is ongoing. // WHEN a recording is ongoing.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment