Merge "Only allow mirroring on a VirtualDisplay with a mirroring flag or MediaProjection instance." into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
df60ec3925
@@ -1514,14 +1514,17 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
// When calling setContentRecordingSession into the WindowManagerService, the WMS
|
||||
// When calling WindowManagerService#setContentRecordingSession, WindowManagerService
|
||||
// attempts to acquire a lock before executing its main body. Due to this, we need
|
||||
// to be sure that it isn't called while the DisplayManagerService is also holding
|
||||
// a lock, to avoid a deadlock scenario.
|
||||
final ContentRecordingSession session =
|
||||
virtualDisplayConfig.getContentRecordingSession();
|
||||
|
||||
if (displayId != Display.INVALID_DISPLAY && session != null) {
|
||||
// Ensure session details are only set when mirroring (through VirtualDisplay flags or
|
||||
// MediaProjection).
|
||||
final boolean shouldMirror =
|
||||
projection != null || (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0;
|
||||
if (shouldMirror && displayId != Display.INVALID_DISPLAY && session != null) {
|
||||
// Only attempt to set content recording session if there are details to set and a
|
||||
// VirtualDisplay has been successfully constructed.
|
||||
session.setDisplayId(displayId);
|
||||
@@ -1529,8 +1532,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
// We set the content recording session here on the server side instead of using
|
||||
// a second AIDL call in MediaProjection. By ensuring that a virtual display has
|
||||
// been constructed before calling setContentRecordingSession, we avoid a race
|
||||
// condition between the DMS & WMS which could lead to the MediaProjection
|
||||
// being pre-emptively torn down.
|
||||
// condition between the DisplayManagerService & WindowManagerService which could
|
||||
// lead to the MediaProjection being pre-emptively torn down.
|
||||
if (!mWindowManagerInternal.setContentRecordingSession(session)) {
|
||||
// Unable to start mirroring, so tear down projection & release VirtualDisplay.
|
||||
try {
|
||||
|
||||
@@ -34,7 +34,9 @@ import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -65,12 +67,14 @@ import android.hardware.display.HdrConversionMode;
|
||||
import android.hardware.display.IDisplayManagerCallback;
|
||||
import android.hardware.display.IVirtualDisplayCallback;
|
||||
import android.hardware.display.VirtualDisplayConfig;
|
||||
import android.media.projection.IMediaProjection;
|
||||
import android.media.projection.IMediaProjectionManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.MessageQueue;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.view.ContentRecordingSession;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayCutout;
|
||||
@@ -1024,11 +1028,14 @@ public class DisplayManagerServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateVirtualDisplay_setContentRecordingSessionSuccess() throws Exception {
|
||||
public void testCreateVirtualDisplay_setContentRecordingSessionSuccess()
|
||||
throws RemoteException {
|
||||
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
||||
when(mMockWindowManagerInternal
|
||||
.setContentRecordingSession(any(ContentRecordingSession.class)))
|
||||
.thenReturn(true);
|
||||
IMediaProjection projection = mock(IMediaProjection.class);
|
||||
doReturn(true).when(mMockProjectionService).isCurrentProjection(eq(projection));
|
||||
|
||||
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
|
||||
VIRTUAL_DISPLAY_NAME, 600, 800, 320);
|
||||
@@ -1042,17 +1049,19 @@ public class DisplayManagerServiceTest {
|
||||
|
||||
DisplayManagerService.BinderService binderService = displayManager.new BinderService();
|
||||
final int displayId = binderService.createVirtualDisplay(builder.build(),
|
||||
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
|
||||
mMockAppToken /* callback */, projection, PACKAGE_NAME);
|
||||
|
||||
assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateVirtualDisplay_setContentRecordingSessionFail() throws Exception {
|
||||
public void testCreateVirtualDisplay_setContentRecordingSessionFail() throws RemoteException {
|
||||
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
||||
when(mMockWindowManagerInternal
|
||||
.setContentRecordingSession(any(ContentRecordingSession.class)))
|
||||
.thenReturn(false);
|
||||
IMediaProjection projection = mock(IMediaProjection.class);
|
||||
doReturn(true).when(mMockProjectionService).isCurrentProjection(eq(projection));
|
||||
|
||||
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
|
||||
VIRTUAL_DISPLAY_NAME, 600, 800, 320);
|
||||
@@ -1066,11 +1075,96 @@ public class DisplayManagerServiceTest {
|
||||
|
||||
DisplayManagerService.BinderService binderService = displayManager.new BinderService();
|
||||
final int displayId = binderService.createVirtualDisplay(builder.build(),
|
||||
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
|
||||
mMockAppToken /* callback */, projection, PACKAGE_NAME);
|
||||
|
||||
assertThat(displayId).isEqualTo(Display.INVALID_DISPLAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateVirtualDisplay_setContentRecordingSession_noProjection_noFlags() {
|
||||
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
||||
|
||||
// Set no flags for the VirtualDisplay.
|
||||
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
|
||||
VIRTUAL_DISPLAY_NAME, 600, 800, 320);
|
||||
builder.setUniqueId("uniqueId --- setContentRecordingSession false");
|
||||
builder.setContentRecordingSession(
|
||||
ContentRecordingSession.createDisplaySession(new Binder("")));
|
||||
|
||||
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
|
||||
registerDefaultDisplays(displayManager);
|
||||
displayManager.windowManagerAndInputReady();
|
||||
|
||||
// Pass in a null projection.
|
||||
DisplayManagerService.BinderService binderService = displayManager.new BinderService();
|
||||
final int displayId = binderService.createVirtualDisplay(builder.build(),
|
||||
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
|
||||
|
||||
// VirtualDisplay is created but not for mirroring.
|
||||
assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
|
||||
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(
|
||||
any(ContentRecordingSession.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateVirtualDisplay_setContentRecordingSession_noProjection_noMirroringFlag() {
|
||||
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
||||
|
||||
// Set a non-mirroring flag for the VirtualDisplay.
|
||||
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
|
||||
VIRTUAL_DISPLAY_NAME, 600, 800, 320);
|
||||
builder.setUniqueId("uniqueId --- setContentRecordingSession false");
|
||||
builder.setFlags(VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
|
||||
builder.setContentRecordingSession(
|
||||
ContentRecordingSession.createDisplaySession(new Binder("")));
|
||||
|
||||
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
|
||||
registerDefaultDisplays(displayManager);
|
||||
displayManager.windowManagerAndInputReady();
|
||||
|
||||
// Pass in a null projection.
|
||||
DisplayManagerService.BinderService binderService = displayManager.new BinderService();
|
||||
final int displayId = binderService.createVirtualDisplay(builder.build(),
|
||||
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
|
||||
|
||||
// VirtualDisplay is created but not for mirroring.
|
||||
assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
|
||||
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(
|
||||
any(ContentRecordingSession.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateVirtualDisplay_setContentRecordingSession_projection_noMirroringFlag()
|
||||
throws RemoteException {
|
||||
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
||||
when(mMockWindowManagerInternal
|
||||
.setContentRecordingSession(any(ContentRecordingSession.class)))
|
||||
.thenReturn(true);
|
||||
IMediaProjection projection = mock(IMediaProjection.class);
|
||||
doReturn(true).when(mMockProjectionService).isCurrentProjection(eq(projection));
|
||||
|
||||
// Set no flags for the VirtualDisplay.
|
||||
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
|
||||
VIRTUAL_DISPLAY_NAME, 600, 800, 320);
|
||||
builder.setUniqueId("uniqueId --- setContentRecordingSession false");
|
||||
builder.setContentRecordingSession(
|
||||
ContentRecordingSession.createDisplaySession(new Binder("")));
|
||||
|
||||
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
|
||||
registerDefaultDisplays(displayManager);
|
||||
displayManager.windowManagerAndInputReady();
|
||||
|
||||
// Pass in a non-null projection.
|
||||
DisplayManagerService.BinderService binderService = displayManager.new BinderService();
|
||||
final int displayId = binderService.createVirtualDisplay(builder.build(),
|
||||
mMockAppToken /* callback */, projection, PACKAGE_NAME);
|
||||
|
||||
// VirtualDisplay is created for mirroring.
|
||||
assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
|
||||
verify(mMockWindowManagerInternal, atLeastOnce()).setContentRecordingSession(
|
||||
any(ContentRecordingSession.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the virtual display is created with
|
||||
* {@link VirtualDisplayConfig.Builder#setSurface(Surface)}
|
||||
|
||||
Reference in New Issue
Block a user