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

Commit ddf7af6f authored by Naomi Musgrave's avatar Naomi Musgrave Committed by Automerger Merge Worker
Browse files

Merge "Only allow mirroring on a VirtualDisplay with a mirroring flag or...

Merge "Only allow mirroring on a VirtualDisplay with a mirroring flag or MediaProjection instance." into udc-dev am: df60ec39

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22075082



Change-Id: I210dfb0f9b516a19ed75ed0659edb9dd2f91ca1e
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 63e1b3ba df60ec39
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -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 {
+98 −4
Original line number Diff line number Diff line
@@ -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)}