Merge "Do not use virtual display from real system in mocked test" into main

This commit is contained in:
Riddle Hsu
2023-07-28 10:48:45 +00:00
committed by Android (Google) Code Review
4 changed files with 115 additions and 217 deletions

View File

@@ -453,6 +453,78 @@ public class ContentRecorderTests extends WindowTestsBase {
displayAreaBounds.width(), displayAreaBounds.height());
}
@Test
public void testDisplayContentUpdatesRecording_withoutSurface() {
// GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
// mirror.
setUpDefaultTaskDisplayAreaWindowToken();
// WHEN getting the DisplayContent for the new virtual display without providing a valid
// size from getDisplaySurfaceDefaultSize, i.e. the case of null surface.
final DisplayContent virtualDisplay =
mRootWindowContainer.getDisplayContent(mDisplaySession.getVirtualDisplayId());
doReturn(null).when(mWm.mDisplayManagerInternal).getDisplaySurfaceDefaultSize(anyInt());
mWm.mContentRecordingController.setContentRecordingSessionLocked(mDisplaySession, mWm);
virtualDisplay.updateRecording();
// THEN mirroring is not started, since a null surface indicates the VirtualDisplay is off.
assertThat(virtualDisplay.isCurrentlyRecording()).isFalse();
}
@Test
public void testDisplayContentUpdatesRecording_withSurface() {
// GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
// mirror.
setUpDefaultTaskDisplayAreaWindowToken();
// WHEN getting the DisplayContent for the virtual display with a valid size from
// getDisplaySurfaceDefaultSize (done by surfaceControlMirrors in setUp).
final DisplayContent virtualDisplay =
mRootWindowContainer.getDisplayContent(mDisplaySession.getVirtualDisplayId());
mWm.mContentRecordingController.setContentRecordingSessionLocked(mDisplaySession, mWm);
virtualDisplay.updateRecording();
// THEN mirroring is initiated for the default display's DisplayArea.
assertThat(virtualDisplay.isCurrentlyRecording()).isTrue();
}
@Test
public void testDisplayContentUpdatesRecording_displayMirroring() {
// GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
// mirror.
setUpDefaultTaskDisplayAreaWindowToken();
// GIVEN SurfaceControl can successfully mirror the provided surface.
surfaceControlMirrors(sSurfaceSize);
// Initially disable getDisplayIdToMirror since the DMS may create the DC outside the direct
// call in the test. We need to spy on the DC before updateRecording is called or we can't
// verify setDisplayMirroring is called
doReturn(INVALID_DISPLAY).when(mWm.mDisplayManagerInternal).getDisplayIdToMirror(anyInt());
// WHEN getting the DisplayContent for the new virtual display.
final DisplayContent virtualDisplay =
mRootWindowContainer.getDisplayContent(mDisplaySession.getVirtualDisplayId());
// Return the default display as the value to mirror to ensure the VD with flag mirroring
// creates a ContentRecordingSession automatically.
doReturn(DEFAULT_DISPLAY).when(mWm.mDisplayManagerInternal).getDisplayIdToMirror(anyInt());
virtualDisplay.updateRecording();
// THEN mirroring is initiated for the default display's DisplayArea.
verify(virtualDisplay).setDisplayMirroring();
assertThat(virtualDisplay.isCurrentlyRecording()).isTrue();
}
/**
* Creates a WindowToken associated with the default task DisplayArea, in order for that
* DisplayArea to be mirrored.
*/
private void setUpDefaultTaskDisplayAreaWindowToken() {
// GIVEN the default task display area is represented by the WindowToken.
spyOn(mWm.mWindowContextListenerController);
doReturn(mDefaultDisplay.getDefaultTaskDisplayArea()).when(
mWm.mWindowContextListenerController).getContainer(any());
}
/**
* Creates a {@link android.window.WindowContainerToken} associated with a task, in order for
* that task to be recorded.

View File

@@ -27,12 +27,10 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.os.Build.VERSION_CODES.P;
import static android.os.Build.VERSION_CODES.Q;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
import static android.view.DisplayCutout.fromBoundingRect;
import static android.view.Surface.ROTATION_0;
@@ -112,11 +110,9 @@ import android.app.ActivityTaskManager;
import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.HardwareBuffer;
import android.hardware.display.VirtualDisplay;
import android.metrics.LogMaker;
import android.os.Binder;
import android.os.RemoteException;
@@ -124,7 +120,6 @@ import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.view.ContentRecordingSession;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
@@ -2654,138 +2649,6 @@ public class DisplayContentTests extends WindowTestsBase {
assertNotEquals(imeMenuDialog, mDisplayContent.findFocusedWindow());
}
@Test
public void testVirtualDisplayContent_withoutSurface() {
// GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
// mirror.
setUpDefaultTaskDisplayAreaWindowToken();
// GIVEN SurfaceControl does not mirror a null surface.
Point surfaceSize = new Point(
mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(),
mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height());
// GIVEN a new VirtualDisplay with an associated surface.
final VirtualDisplay display = createVirtualDisplay(surfaceSize, null /* surface */);
final int displayId = display.getDisplay().getDisplayId();
mWm.mRoot.onDisplayAdded(displayId);
// WHEN getting the DisplayContent for the new virtual display.
DisplayContent actualDC = mWm.mRoot.getDisplayContent(displayId);
ContentRecordingSession session = ContentRecordingSession.createDisplaySession(
DEFAULT_DISPLAY);
session.setVirtualDisplayId(displayId);
mWm.mContentRecordingController.setContentRecordingSessionLocked(session, mWm);
actualDC.updateRecording();
// THEN mirroring is not started, since a null surface indicates the VirtualDisplay is off.
assertThat(actualDC.isCurrentlyRecording()).isFalse();
display.release();
}
@Test
public void testVirtualDisplayContent_withSurface() {
// GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
// mirror.
setUpDefaultTaskDisplayAreaWindowToken();
// GIVEN SurfaceControl can successfully mirror the provided surface.
Point surfaceSize = new Point(
mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(),
mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height());
surfaceControlMirrors(surfaceSize);
// GIVEN a new VirtualDisplay with an associated surface.
final VirtualDisplay display = createVirtualDisplay(surfaceSize, new Surface());
final int displayId = display.getDisplay().getDisplayId();
// GIVEN a session for this display.
ContentRecordingSession session = ContentRecordingSession.createDisplaySession(
DEFAULT_DISPLAY);
session.setVirtualDisplayId(displayId);
mWm.mContentRecordingController.setContentRecordingSessionLocked(session, mWm);
mWm.mRoot.onDisplayAdded(displayId);
// WHEN getting the DisplayContent for the new virtual display.
DisplayContent actualDC = mWm.mRoot.getDisplayContent(displayId);
actualDC.updateRecording();
// THEN mirroring is initiated for the default display's DisplayArea.
assertThat(actualDC.isCurrentlyRecording()).isTrue();
display.release();
}
@Test
public void testVirtualDisplayContent_displayMirroring() {
// GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
// mirror.
setUpDefaultTaskDisplayAreaWindowToken();
// GIVEN SurfaceControl can successfully mirror the provided surface.
Point surfaceSize = new Point(
mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(),
mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height());
surfaceControlMirrors(surfaceSize);
// Initially disable getDisplayIdToMirror since the DMS may create the DC outside the direct
// call in the test. We need to spy on the DC before updateRecording is called or we can't
// verify setDisplayMirroring is called
doReturn(INVALID_DISPLAY).when(mWm.mDisplayManagerInternal).getDisplayIdToMirror(anyInt());
// GIVEN a new VirtualDisplay with an associated surface.
final VirtualDisplay display = createVirtualDisplay(surfaceSize, new Surface());
final int displayId = display.getDisplay().getDisplayId();
// GIVEN a session for this display.
mWm.mRoot.onDisplayAdded(displayId);
// WHEN getting the DisplayContent for the new virtual display.
DisplayContent actualDC = mWm.mRoot.getDisplayContent(displayId);
spyOn(actualDC);
// Return the default display as the value to mirror to ensure the VD with flag mirroring
// creates a ContentRecordingSession automatically.
doReturn(DEFAULT_DISPLAY).when(mWm.mDisplayManagerInternal).getDisplayIdToMirror(anyInt());
actualDC.updateRecording();
// THEN mirroring is initiated for the default display's DisplayArea.
verify(actualDC).setDisplayMirroring();
assertThat(actualDC.isCurrentlyRecording()).isTrue();
display.release();
}
/**
* Creates a WindowToken associated with the default task DisplayArea, in order for that
* DisplayArea to be mirrored.
*/
private void setUpDefaultTaskDisplayAreaWindowToken() {
// GIVEN the default task display area is represented by the WindowToken.
spyOn(mWm.mWindowContextListenerController);
doReturn(mDefaultDisplay.getDefaultTaskDisplayArea()).when(
mWm.mWindowContextListenerController).getContainer(any());
}
/**
* SurfaceControl successfully creates a mirrored surface of the given size.
*/
private SurfaceControl surfaceControlMirrors(Point surfaceSize) {
// Do not set the parent, since the mirrored surface is the root of a new surface hierarchy.
SurfaceControl mirroredSurface = new SurfaceControl.Builder()
.setName("mirroredSurface")
.setBufferSize(surfaceSize.x, surfaceSize.y)
.setCallsite("mirrorSurface")
.build();
doReturn(mirroredSurface).when(() -> SurfaceControl.mirrorSurface(any()));
doReturn(surfaceSize).when(mWm.mDisplayManagerInternal).getDisplaySurfaceDefaultSize(
anyInt());
return mirroredSurface;
}
private VirtualDisplay createVirtualDisplay(Point size, Surface surface) {
return mWm.mDisplayManager.createVirtualDisplay("VirtualDisplay", size.x, size.y,
DisplayMetrics.DENSITY_140, surface, VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR);
}
@Test
public void testKeepClearAreasMultipleWindows() {
final WindowState w1 = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent, "w1");

View File

@@ -21,9 +21,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_OWN_FOCUS;
import static android.view.Display.INVALID_DISPLAY;
@@ -63,6 +60,8 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.description;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -71,9 +70,7 @@ import static org.mockito.Mockito.when;
import android.app.ActivityThread;
import android.app.IApplicationThread;
import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.VirtualDisplay;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -82,7 +79,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
import android.view.ContentRecordingSession;
import android.view.IWindow;
@@ -90,7 +86,6 @@ import android.view.IWindowSessionCallback;
import android.view.InputChannel;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowInsets;
@@ -575,13 +570,14 @@ public class WindowManagerServiceTests extends WindowTestsBase {
mWm.mPerDisplayFocusEnabled = false;
// Create one extra display
final VirtualDisplay virtualDisplay = createVirtualDisplay(/* ownFocus= */ false);
final VirtualDisplay virtualDisplayOwnTouchMode =
createVirtualDisplay(/* ownFocus= */ true);
final DisplayContent display = createMockSimulatedDisplay();
display.getDisplayInfo().flags &= ~FLAG_OWN_FOCUS;
final DisplayContent displayOwnTouchMode = createMockSimulatedDisplay();
displayOwnTouchMode.getDisplayInfo().flags |= FLAG_OWN_FOCUS;
final int numberOfDisplays = mWm.mRoot.mChildren.size();
assertThat(numberOfDisplays).isAtLeast(3);
final int numberOfGlobalTouchModeDisplays = (int) mWm.mRoot.mChildren.stream()
.filter(d -> (d.getDisplay().getFlags() & FLAG_OWN_FOCUS) == 0)
.filter(d -> (d.getDisplayInfo().flags & FLAG_OWN_FOCUS) == 0)
.count();
assertThat(numberOfGlobalTouchModeDisplays).isAtLeast(2);
@@ -601,12 +597,13 @@ public class WindowManagerServiceTests extends WindowTestsBase {
}
@Test
public void testSetInTouchMode_multiDisplay_perDisplayFocus_singleDisplayTouchModeUpdate() {
public void testSetInTouchMode_multiDisplay_singleDisplayTouchModeUpdate() {
// Enable global touch mode
mWm.mPerDisplayFocusEnabled = true;
// Create one extra display
final VirtualDisplay virtualDisplay = createVirtualDisplay(/* ownFocus= */ false);
final DisplayContent virtualDisplay = createMockSimulatedDisplay();
virtualDisplay.getDisplayInfo().flags &= ~FLAG_OWN_FOCUS;
final int numberOfDisplays = mWm.mRoot.mChildren.size();
assertThat(numberOfDisplays).isAtLeast(2);
@@ -618,99 +615,64 @@ public class WindowManagerServiceTests extends WindowTestsBase {
when(mWm.mAtmService.instrumentationSourceHasPermission(callingPid,
android.Manifest.permission.MODIFY_TOUCH_MODE_STATE)).thenReturn(true);
mWm.setInTouchMode(!currentTouchMode, virtualDisplay.getDisplay().getDisplayId());
mWm.setInTouchMode(!currentTouchMode, virtualDisplay.mDisplayId);
// Ensure that new display touch mode state has changed.
verify(mWm.mInputManager).setInTouchMode(
!currentTouchMode, callingPid, callingUid, /* hasPermission= */ true,
virtualDisplay.getDisplay().getDisplayId());
}
virtualDisplay.mDisplayId);
@Test
public void testSetInTouchMode_multiDisplay_ownTouchMode_singleDisplayTouchModeUpdate() {
// Disable global touch mode
// Disable global touch mode and make the virtual display own focus.
mWm.mPerDisplayFocusEnabled = false;
// Create one extra display
final VirtualDisplay virtualDisplay = createVirtualDisplay(/* ownFocus= */ true);
final int numberOfDisplays = mWm.mRoot.mChildren.size();
assertThat(numberOfDisplays).isAtLeast(2);
// Get current touch mode state and setup WMS to run setInTouchMode
boolean currentTouchMode = mWm.isInTouchMode(DEFAULT_DISPLAY);
int callingPid = Binder.getCallingPid();
int callingUid = Binder.getCallingUid();
doReturn(false).when(mWm).checkCallingPermission(anyString(), anyString(), anyBoolean());
when(mWm.mAtmService.instrumentationSourceHasPermission(callingPid,
android.Manifest.permission.MODIFY_TOUCH_MODE_STATE)).thenReturn(true);
mWm.setInTouchMode(!currentTouchMode, virtualDisplay.getDisplay().getDisplayId());
virtualDisplay.getDisplayInfo().flags |= FLAG_OWN_FOCUS;
clearInvocations(mWm.mInputManager);
mWm.setInTouchMode(!currentTouchMode, virtualDisplay.mDisplayId);
// Ensure that new display touch mode state has changed.
verify(mWm.mInputManager).setInTouchMode(
!currentTouchMode, callingPid, callingUid, /* hasPermission= */ true,
virtualDisplay.getDisplay().getDisplayId());
virtualDisplay.mDisplayId);
}
@Test
public void testSetInTouchModeOnAllDisplays_perDisplayFocusDisabled() {
testSetInTouchModeOnAllDisplays(/* perDisplayFocusEnabled= */ false);
}
@Test
public void testSetInTouchModeOnAllDisplays_perDisplayFocusEnabled() {
testSetInTouchModeOnAllDisplays(/* perDisplayFocusEnabled= */ true);
}
private void testSetInTouchModeOnAllDisplays(boolean perDisplayFocusEnabled) {
// Set global touch mode with the value passed as argument.
mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
public void testSetInTouchModeOnAllDisplays() {
// Create a couple of extra displays.
// setInTouchModeOnAllDisplays should ignore the ownFocus setting.
final VirtualDisplay virtualDisplay = createVirtualDisplay(/* ownFocus= */ false);
final VirtualDisplay virtualDisplayOwnFocus = createVirtualDisplay(/* ownFocus= */ true);
final DisplayContent display = createMockSimulatedDisplay();
display.getDisplayInfo().flags &= ~FLAG_OWN_FOCUS;
final DisplayContent displayOwnTouchMode = createMockSimulatedDisplay();
displayOwnTouchMode.getDisplayInfo().flags |= FLAG_OWN_FOCUS;
int callingPid = Binder.getCallingPid();
int callingUid = Binder.getCallingUid();
doReturn(true).when(mWm.mInputManager).setInTouchMode(anyBoolean(), anyInt(),
anyInt(), anyBoolean(), anyInt());
doReturn(false).when(mWm).checkCallingPermission(anyString(), anyString(), anyBoolean());
when(mWm.mAtmService.instrumentationSourceHasPermission(callingPid,
android.Manifest.permission.MODIFY_TOUCH_MODE_STATE)).thenReturn(true);
for (boolean inTouchMode : new boolean[]{true, false}) {
mWm.setInTouchModeOnAllDisplays(inTouchMode);
for (int i = 0; i < mWm.mRoot.mChildren.size(); ++i) {
DisplayContent dc = mWm.mRoot.mChildren.get(i);
// All displays that are not already in the desired touch mode are requested to
// change their touch mode.
if (dc.isInTouchMode() != inTouchMode) {
verify(mWm.mInputManager).setInTouchMode(
true, callingPid, callingUid, /* hasPermission= */ true,
dc.getDisplay().getDisplayId());
final Runnable verification = () -> {
for (boolean inTouchMode : new boolean[] { true, false }) {
mWm.setInTouchModeOnAllDisplays(inTouchMode);
for (int i = 0; i < mRootWindowContainer.getChildCount(); ++i) {
final DisplayContent dc = mRootWindowContainer.getChildAt(i);
// All displays that are not already in the desired touch mode are requested to
// change their touch mode.
if (dc.isInTouchMode() != inTouchMode) {
verify(mWm.mInputManager, description("perDisplayFocusEnabled="
+ mWm.mPerDisplayFocusEnabled)).setInTouchMode(true,
callingPid, callingUid, /* hasPermission= */ true, dc.mDisplayId);
}
}
}
}
}
};
private VirtualDisplay createVirtualDisplay(boolean ownFocus) {
// Create virtual display
Point surfaceSize = new Point(
mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(),
mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height());
int flags = VIRTUAL_DISPLAY_FLAG_PUBLIC;
if (ownFocus) {
flags |= VIRTUAL_DISPLAY_FLAG_OWN_FOCUS | VIRTUAL_DISPLAY_FLAG_TRUSTED;
}
VirtualDisplay virtualDisplay = mWm.mDisplayManager.createVirtualDisplay("VirtualDisplay",
surfaceSize.x, surfaceSize.y, DisplayMetrics.DENSITY_140, new Surface(), flags);
final int displayId = virtualDisplay.getDisplay().getDisplayId();
mWm.mRoot.onDisplayAdded(displayId);
mWm.mPerDisplayFocusEnabled = false;
verification.run();
// Ensure that virtual display was properly created and stored in WRC
assertThat(mWm.mRoot.getDisplayContent(
virtualDisplay.getDisplay().getDisplayId())).isNotNull();
return virtualDisplay;
clearInvocations(mWm.mInputManager);
mWm.mPerDisplayFocusEnabled = true;
verification.run();
}
@Test

View File

@@ -901,6 +901,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
DisplayInfo displayInfo = new DisplayInfo();
displayInfo.copyFrom(mDisplayInfo);
displayInfo.type = Display.TYPE_VIRTUAL;
displayInfo.state = Display.STATE_ON;
displayInfo.ownerUid = SYSTEM_UID;
return createNewDisplay(displayInfo, DISPLAY_IME_POLICY_FALLBACK_DISPLAY, overrideSettings);
}