Merge "VirtualDisplay: Merge AIDL calls to stop race condition" into udc-dev am: c722618ac8 am: 0316a9c549
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21567986 Change-Id: I20b79e79e08e0d085c8b3d42c8781f1230a28df1 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user