VirtualDisplay: Merge AIDL calls to stop race condition

Updating execution flow so that setting ContentRecordingSession is no longer
a second AIDL call to the DisplayManager Service, but instead passing in
the session details with the VirtualDisplayConfig, and having it be set
manually in the execution of an earlier AIDL call.

Bug: 267610691
Fix: 267610691
Test: manually built
Test: atest CtsWindowManagerDeviceTestCases:ActivityCaptureCallbackTests
Test: atest CtsWindowManagerDeviceTestCases:DisplayTests
Test: atest DisplayManagerServiceTest
Test: atest DisplayTest
Test: atest WmTests:ContentRecorderTests
Change-Id: Id926aa0800bd23d329bbc8f2a6f739e26fd72a3c
This commit is contained in:
dakinola
2023-02-08 17:55:07 +00:00
committed by Naomi Musgrave
parent 25d0a6a203
commit 17469b9ac3
6 changed files with 209 additions and 37 deletions

View File

@@ -28,6 +28,7 @@ import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
import android.view.ContentRecordingSession;
import android.view.Display;
import android.view.Surface;
@@ -53,6 +54,8 @@ public final class VirtualDisplayConfig implements Parcelable {
private final int mDisplayIdToMirror;
private final boolean mWindowManagerMirroringEnabled;
private ArraySet<String> mDisplayCategories = null;
@Nullable
private ContentRecordingSession mContentRecordingSession;
private final float mRequestedRefreshRate;
private VirtualDisplayConfig(
@@ -65,6 +68,7 @@ public final class VirtualDisplayConfig implements Parcelable {
@Nullable String uniqueId,
int displayIdToMirror,
boolean windowManagerMirroringEnabled,
ContentRecordingSession session,
@NonNull ArraySet<String> displayCategories,
float requestedRefreshRate) {
mName = name;
@@ -76,6 +80,7 @@ public final class VirtualDisplayConfig implements Parcelable {
mUniqueId = uniqueId;
mDisplayIdToMirror = displayIdToMirror;
mWindowManagerMirroringEnabled = windowManagerMirroringEnabled;
mContentRecordingSession = session;
mDisplayCategories = displayCategories;
mRequestedRefreshRate = requestedRefreshRate;
}
@@ -155,6 +160,17 @@ public final class VirtualDisplayConfig implements Parcelable {
return mWindowManagerMirroringEnabled;
}
/**
* Returns the recording session associated with this VirtualDisplay. Only used for
* recording via {@link MediaProjection}.
*
* @hide
*/
@Nullable
public ContentRecordingSession getContentRecordingSession() {
return mContentRecordingSession;
}
/**
* Returns the display categories.
*
@@ -186,6 +202,7 @@ public final class VirtualDisplayConfig implements Parcelable {
dest.writeString8(mUniqueId);
dest.writeInt(mDisplayIdToMirror);
dest.writeBoolean(mWindowManagerMirroringEnabled);
dest.writeTypedObject(mContentRecordingSession, flags);
dest.writeArraySet(mDisplayCategories);
dest.writeFloat(mRequestedRefreshRate);
}
@@ -211,6 +228,7 @@ public final class VirtualDisplayConfig implements Parcelable {
&& Objects.equals(mUniqueId, that.mUniqueId)
&& mDisplayIdToMirror == that.mDisplayIdToMirror
&& mWindowManagerMirroringEnabled == that.mWindowManagerMirroringEnabled
&& Objects.equals(mContentRecordingSession, that.mContentRecordingSession)
&& Objects.equals(mDisplayCategories, that.mDisplayCategories)
&& mRequestedRefreshRate == that.mRequestedRefreshRate;
}
@@ -219,8 +237,8 @@ public final class VirtualDisplayConfig implements Parcelable {
public int hashCode() {
int hashCode = Objects.hash(
mName, mWidth, mHeight, mDensityDpi, mFlags, mSurface, mUniqueId,
mDisplayIdToMirror, mWindowManagerMirroringEnabled, mDisplayCategories,
mRequestedRefreshRate);
mDisplayIdToMirror, mWindowManagerMirroringEnabled, mContentRecordingSession,
mDisplayCategories, mRequestedRefreshRate);
return hashCode;
}
@@ -237,6 +255,7 @@ public final class VirtualDisplayConfig implements Parcelable {
+ " mUniqueId=" + mUniqueId
+ " mDisplayIdToMirror=" + mDisplayIdToMirror
+ " mWindowManagerMirroringEnabled=" + mWindowManagerMirroringEnabled
+ " mContentRecordingSession=" + mContentRecordingSession
+ " mDisplayCategories=" + mDisplayCategories
+ " mRequestedRefreshRate=" + mRequestedRefreshRate
+ ")";
@@ -252,6 +271,7 @@ public final class VirtualDisplayConfig implements Parcelable {
mUniqueId = in.readString8();
mDisplayIdToMirror = in.readInt();
mWindowManagerMirroringEnabled = in.readBoolean();
mContentRecordingSession = in.readTypedObject(ContentRecordingSession.CREATOR);
mDisplayCategories = (ArraySet<String>) in.readArraySet(null);
mRequestedRefreshRate = in.readFloat();
}
@@ -283,6 +303,8 @@ public final class VirtualDisplayConfig implements Parcelable {
private String mUniqueId = null;
private int mDisplayIdToMirror = DEFAULT_DISPLAY;
private boolean mWindowManagerMirroringEnabled = false;
@Nullable
private ContentRecordingSession mContentRecordingSession;
private ArraySet<String> mDisplayCategories = new ArraySet<>();
private float mRequestedRefreshRate = 0.0f;
@@ -374,6 +396,18 @@ public final class VirtualDisplayConfig implements Parcelable {
return this;
}
/**
* Sets the recording session associated with this {@link VirtualDisplay}. Only used for
* recording via {@link MediaProjection}.
*
* @hide
*/
@NonNull
public Builder setContentRecordingSession(@Nullable ContentRecordingSession session) {
mContentRecordingSession = session;
return this;
}
/**
* Sets the display categories.
*
@@ -435,6 +469,7 @@ public final class VirtualDisplayConfig implements Parcelable {
mUniqueId,
mDisplayIdToMirror,
mWindowManagerMirroringEnabled,
mContentRecordingSession,
mDisplayCategories,
mRequestedRefreshRate);
}

View File

@@ -191,20 +191,13 @@ public final class MediaProjection {
} else {
session = ContentRecordingSession.createTaskSession(launchCookie);
}
// Pass in the current session details, so they are guaranteed to only be set in WMS
// AFTER a VirtualDisplay is constructed (assuming there are no errors during set-up).
virtualDisplayConfig.setContentRecordingSession(session);
virtualDisplayConfig.setWindowManagerMirroringEnabled(true);
final DisplayManager dm = mContext.getSystemService(DisplayManager.class);
final VirtualDisplay virtualDisplay = dm.createVirtualDisplay(this,
virtualDisplayConfig.build(), callback, handler, windowContext);
if (virtualDisplay == null) {
// Since WM handling a new display and DM creating a new VirtualDisplay is async,
// WM may have tried to start task recording and encountered an error that required
// stopping recording entirely. The VirtualDisplay would then be null when the
// MediaProjection is no longer active.
return null;
}
session.setDisplayId(virtualDisplay.getDisplay().getDisplayId());
// Successfully set up, so save the current session details.
getProjectionService().setContentRecordingSession(session, mImpl);
return virtualDisplay;
} catch (RemoteException e) {
// Can not capture if WMS is not accessible, so bail out.

View File

@@ -128,6 +128,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.Spline;
import android.view.ContentRecordingSession;
import android.view.Display;
import android.view.DisplayEventReceiver;
import android.view.DisplayInfo;
@@ -250,6 +251,7 @@ public final class DisplayManagerService extends SystemService {
private ActivityManagerInternal mActivityManagerInternal;
private ActivityManager mActivityManager;
private UidImportanceListener mUidImportanceListener = new UidImportanceListener();
@Nullable
private IMediaProjectionManager mProjectionService;
private DeviceStateManagerInternal mDeviceStateManager;
@GuardedBy("mSyncRoot")
@@ -1494,8 +1496,9 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
final int displayId;
synchronized (mSyncRoot) {
final int displayId =
displayId =
createVirtualDisplayLocked(
callback,
projection,
@@ -1509,8 +1512,39 @@ public final class DisplayManagerService extends SystemService {
mDisplayWindowPolicyControllers.put(
displayId, Pair.create(virtualDevice, dwpc));
}
return displayId;
}
// When calling setContentRecordingSession into the WindowManagerService, the WMS
// 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) {
// Only attempt to set content recording session if there are details to set and a
// VirtualDisplay has been successfully constructed.
session.setDisplayId(displayId);
// 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.
if (!mWindowManagerInternal.setContentRecordingSession(session)) {
// Unable to start mirroring, so tear down projection & release VirtualDisplay.
try {
getProjectionService().stopActiveProjection();
} catch (RemoteException e) {
Slog.e(TAG, "Unable to tell MediaProjectionManagerService to stop the "
+ "active projection", e);
}
releaseVirtualDisplayInternal(callback.asBinder());
return Display.INVALID_DISPLAY;
}
}
return displayId;
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2804,8 +2838,7 @@ public final class DisplayManagerService extends SystemService {
private IMediaProjectionManager getProjectionService() {
if (mProjectionService == null) {
IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
mProjectionService = mInjector.getProjectionService();
}
return mProjectionService;
}
@@ -2964,6 +2997,11 @@ public final class DisplayManagerService extends SystemService {
boolean getHdrOutputConversionSupport() {
return DisplayControl.getHdrOutputConversionSupport();
}
IMediaProjectionManager getProjectionService() {
IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
return IMediaProjectionManager.Stub.asInterface(b);
}
}
@VisibleForTesting

View File

@@ -88,7 +88,17 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
// Called with SyncRoot lock held.
public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener) {
this(syncRoot, context, handler, listener, DisplayControl::createDisplay);
this(syncRoot, context, handler, listener, new SurfaceControlDisplayFactory() {
@Override
public IBinder createDisplay(String name, boolean secure, float requestedRefreshRate) {
return DisplayControl.createDisplay(name, secure, requestedRefreshRate);
}
@Override
public void destroyDisplay(IBinder displayToken) {
DisplayControl.destroyDisplay(displayToken);
}
});
}
@VisibleForTesting
@@ -311,7 +321,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
mSurface.release();
mSurface = null;
}
DisplayControl.destroyDisplay(getDisplayTokenLocked());
mSurfaceControlDisplayFactory.destroyDisplay(getDisplayTokenLocked());
if (mProjection != null && mMediaProjectionCallback != null) {
try {
mProjection.unregisterCallback(mMediaProjectionCallback);
@@ -653,5 +663,12 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
* @return The token reference for the display in SurfaceFlinger.
*/
IBinder createDisplay(String name, boolean secure, float requestedRefreshRate);
/**
* Destroy a display in SurfaceFlinger.
*
* @param displayToken The display token for the display to be destroyed.
*/
void destroyDisplay(IBinder displayToken);
}
}

View File

@@ -108,6 +108,7 @@
<uses-permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES" />
<uses-permission android:name="android.permission.ACCESS_CONTEXT_HUB" />
<uses-permission android:name="android.permission.USE_BIOMETRIC_INTERNAL" />
<uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION" />
<queries>
<package android:name="com.android.servicestests.apps.suspendtestapp" />

View File

@@ -24,6 +24,8 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_D
import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -32,8 +34,10 @@ 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.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -61,10 +65,13 @@ import android.hardware.display.HdrConversionMode;
import android.hardware.display.IDisplayManagerCallback;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
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.view.ContentRecordingSession;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayEventReceiver;
@@ -158,25 +165,40 @@ public class DisplayManagerServiceTest {
}
};
class BasicInjector extends DisplayManagerService.Injector {
@Override
VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
Handler handler, DisplayAdapter.Listener displayAdapterListener) {
return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
(String name, boolean secure, float refreshRate) -> mMockDisplayToken);
}
class BasicInjector extends DisplayManagerService.Injector {
@Override
IMediaProjectionManager getProjectionService() {
return mMockProjectionService;
}
@Override
LocalDisplayAdapter getLocalDisplayAdapter(SyncRoot syncRoot, Context context,
Handler handler, DisplayAdapter.Listener displayAdapterListener) {
return new LocalDisplayAdapter(syncRoot, context, handler,
displayAdapterListener, new LocalDisplayAdapter.Injector() {
@Override
public LocalDisplayAdapter.SurfaceControlProxy getSurfaceControlProxy() {
return mSurfaceControlProxy;
}
});
}
@Override
VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
Handler handler, DisplayAdapter.Listener displayAdapterListener) {
return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
new VirtualDisplayAdapter.SurfaceControlDisplayFactory() {
@Override
public IBinder createDisplay(String name, boolean secure,
float requestedRefreshRate) {
return mMockDisplayToken;
}
@Override
public void destroyDisplay(IBinder displayToken) {
}
});
}
@Override
LocalDisplayAdapter getLocalDisplayAdapter(SyncRoot syncRoot, Context context,
Handler handler, DisplayAdapter.Listener displayAdapterListener) {
return new LocalDisplayAdapter(syncRoot, context, handler,
displayAdapterListener, new LocalDisplayAdapter.Injector() {
@Override
public LocalDisplayAdapter.SurfaceControlProxy getSurfaceControlProxy() {
return mSurfaceControlProxy;
}
});
}
@Override
int setHdrConversionMode(int conversionMode, int preferredHdrOutputType,
@@ -198,6 +220,7 @@ public class DisplayManagerServiceTest {
private final DisplayManagerService.Injector mBasicInjector = new BasicInjector();
@Mock IMediaProjectionManager mMockProjectionService;
@Mock IVirtualDeviceManager mIVirtualDeviceManager;
@Mock InputManagerInternal mMockInputManagerInternal;
@Mock VirtualDeviceManagerInternal mMockVirtualDeviceManagerInternal;
@@ -285,6 +308,7 @@ public class DisplayManagerServiceTest {
builder.setFlags(flags);
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
null /* projection */, PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -410,6 +434,7 @@ public class DisplayManagerServiceTest {
builder.setUniqueId(uniqueId);
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
null /* projection */, PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -446,6 +471,7 @@ public class DisplayManagerServiceTest {
builder.setUniqueId(uniqueId);
int displayId = bs.createVirtualDisplay(builder.build(), /* callback= */ mMockAppToken,
/* projection= */ null, PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -479,6 +505,7 @@ public class DisplayManagerServiceTest {
builder.setUniqueId(uniqueId);
int displayId = bs.createVirtualDisplay(builder.build(), /* callback= */ mMockAppToken,
/* projection= */ null, PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -720,6 +747,7 @@ public class DisplayManagerServiceTest {
builder.setUniqueId(uniqueId);
final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
// The second virtual display requests to mirror the first virtual display.
final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
@@ -731,6 +759,7 @@ public class DisplayManagerServiceTest {
final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
mMockAppToken2 /* callback */, null /* projection */,
PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
// flush the handler
@@ -768,6 +797,7 @@ public class DisplayManagerServiceTest {
virtualDevice /* virtualDeviceToken */,
mock(DisplayWindowPolicyController.class),
PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
int displayGroupId1 = localService.getDisplayInfo(displayId1).displayGroupId;
// Create a second virtual display. This should be added to the previously created display
@@ -783,6 +813,7 @@ public class DisplayManagerServiceTest {
virtualDevice /* virtualDeviceToken */,
mock(DisplayWindowPolicyController.class),
PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
int displayGroupId2 = localService.getDisplayInfo(displayId2).displayGroupId;
assertEquals(
@@ -820,6 +851,7 @@ public class DisplayManagerServiceTest {
virtualDevice /* virtualDeviceToken */,
mock(DisplayWindowPolicyController.class),
PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
int displayGroupId1 = localService.getDisplayInfo(displayId1).displayGroupId;
// Create a second virtual display. With the flag VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP,
@@ -838,6 +870,7 @@ public class DisplayManagerServiceTest {
virtualDevice /* virtualDeviceToken */,
mock(DisplayWindowPolicyController.class),
PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
int displayGroupId2 = localService.getDisplayInfo(displayId2).displayGroupId;
assertNotEquals(
@@ -881,6 +914,7 @@ public class DisplayManagerServiceTest {
virtualDevice /* virtualDeviceToken */,
mock(DisplayWindowPolicyController.class),
PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
// Check that FLAG_ALWAYS_UNLOCKED is set.
assertNotEquals(
@@ -906,6 +940,7 @@ public class DisplayManagerServiceTest {
virtualDevice /* virtualDeviceToken */,
mock(DisplayWindowPolicyController.class),
PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
// Check that FLAG_ALWAYS_UNLOCKED is set.
assertNotEquals(
@@ -929,6 +964,7 @@ public class DisplayManagerServiceTest {
null /* virtualDeviceToken */,
mock(DisplayWindowPolicyController.class),
PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
// Check that FLAG_ALWAYS_UNLOCKED is not set.
assertEquals(
@@ -960,6 +996,7 @@ public class DisplayManagerServiceTest {
.setFlags(VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
// The second virtual display requests to mirror the first virtual display.
final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
@@ -971,6 +1008,7 @@ public class DisplayManagerServiceTest {
final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
mMockAppToken2 /* callback */, null /* projection */,
PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
// flush the handler
@@ -985,6 +1023,54 @@ public class DisplayManagerServiceTest {
Display.INVALID_DISPLAY);
}
@Test
public void testCreateVirtualDisplay_setContentRecordingSessionSuccess() throws Exception {
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
when(mMockWindowManagerInternal
.setContentRecordingSession(any(ContentRecordingSession.class)))
.thenReturn(true);
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
VIRTUAL_DISPLAY_NAME, 600, 800, 320);
builder.setUniqueId("uniqueId --- setContentRecordingSession true");
builder.setContentRecordingSession(
ContentRecordingSession.createDisplaySession(new Binder("")));
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
registerDefaultDisplays(displayManager);
displayManager.windowManagerAndInputReady();
DisplayManagerService.BinderService binderService = displayManager.new BinderService();
final int displayId = binderService.createVirtualDisplay(builder.build(),
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
}
@Test
public void testCreateVirtualDisplay_setContentRecordingSessionFail() throws Exception {
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
when(mMockWindowManagerInternal
.setContentRecordingSession(any(ContentRecordingSession.class)))
.thenReturn(false);
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();
DisplayManagerService.BinderService binderService = displayManager.new BinderService();
final int displayId = binderService.createVirtualDisplay(builder.build(),
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
assertThat(displayId).isEqualTo(Display.INVALID_DISPLAY);
}
/**
* Tests that the virtual display is created with
* {@link VirtualDisplayConfig.Builder#setSurface(Surface)}
@@ -1011,6 +1097,7 @@ public class DisplayManagerServiceTest {
builder.setUniqueId(uniqueId);
final int displayId = binderService.createVirtualDisplay(builder.build(),
mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -1043,6 +1130,7 @@ public class DisplayManagerServiceTest {
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
null /* projection */, PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
@@ -1093,7 +1181,6 @@ public class DisplayManagerServiceTest {
registerDefaultDisplays(displayManager);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
@@ -1111,6 +1198,7 @@ public class DisplayManagerServiceTest {
int displayId = localService.createVirtualDisplay(builder.build(),
mMockAppToken /* callback */, virtualDevice /* virtualDeviceToken */,
mock(DisplayWindowPolicyController.class), PACKAGE_NAME);
verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);