From 725dad7d717fc641d3ee3adb782270b82ee92cd8 Mon Sep 17 00:00:00 2001 From: Antony Sargent Date: Mon, 9 May 2022 16:12:35 -0700 Subject: Prevent deadlocks during VirtualDisplay creation When creating a VirtualDisplay for a VirtualDevice, we need to do some extra work like setting up for input injection, creating a DisplayWindowPolicyController, and grabbing a wakelock to keep the display awake. Some parts of this extra work end up calling back into the DisplayManagerService from another thread, but since we're already holding the mSyncRoot lock we sometimes get into situations where those threads get blocked trying to acquire mSyncRoot, while holding a lock that another thread ends up needing like the global window manager one, so we get deadlock. The fix in this CL is to break up the extra work the VirtualDeviceManagerService needs to do into two parts: one part that happens before the VirtualDisplay is created, and one part after. Neither of these needs mSyncRoot to be held. Fixes: 230544802 Test: atest CreateVirtualDisplayTest Change-Id: I6a6e03f816567579510b3f1ef0705375549a3c88 --- .../companion/virtual/IVirtualDeviceManager.aidl | 14 +++++ .../companion/virtual/VirtualDeviceManager.java | 35 +++++++----- .../android/hardware/display/DisplayManager.java | 14 +---- .../hardware/display/DisplayManagerGlobal.java | 26 ++++++--- .../hardware/display/DisplayManagerInternal.java | 9 ++++ .../android/hardware/display/IDisplayManager.aidl | 5 +- .../virtual/GenericWindowPolicyController.java | 44 ++++++++++----- .../companion/virtual/VirtualDeviceImpl.java | 56 +++++++++---------- .../virtual/VirtualDeviceManagerService.java | 59 ++++++++++++++++---- .../virtual/VirtualDeviceManagerInternal.java | 12 ----- .../server/display/DisplayManagerService.java | 38 +++++++------ .../virtual/VirtualDeviceManagerServiceTest.java | 63 ++++++++++++---------- .../server/display/DisplayManagerServiceTest.java | 25 +++++---- 13 files changed, 248 insertions(+), 152 deletions(-) diff --git a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl index a1640ee6d2e8..5418f7e93dd9 100644 --- a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl +++ b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl @@ -19,6 +19,8 @@ package android.companion.virtual; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; import android.companion.virtual.VirtualDeviceParams; +import android.hardware.display.IVirtualDisplayCallback; +import android.hardware.display.VirtualDisplayConfig; /** * Interface for communication between VirtualDeviceManager and VirtualDeviceManagerService. @@ -42,4 +44,16 @@ interface IVirtualDeviceManager { IVirtualDevice createVirtualDevice( in IBinder token, String packageName, int associationId, in VirtualDeviceParams params, in IVirtualDeviceActivityListener activityListener); + + /** + * Creates a virtual display owned by a particular virtual device. + * + * @param virtualDisplayConfig The configuration used in creating the display + * @param callback A callback that receives display lifecycle events + * @param virtualDevice The device that will own this display + * @param packageName The package name of the calling app + */ + int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig, + in IVirtualDisplayCallback callback, in IVirtualDevice virtualDevice, + String packageName); } diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java index 3bb837317ad4..1b93bb851567 100644 --- a/core/java/android/companion/virtual/VirtualDeviceManager.java +++ b/core/java/android/companion/virtual/VirtualDeviceManager.java @@ -33,6 +33,8 @@ import android.content.Context; import android.graphics.Point; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.VirtualDisplayFlag; +import android.hardware.display.DisplayManagerGlobal; +import android.hardware.display.IVirtualDisplayCallback; import android.hardware.display.VirtualDisplay; import android.hardware.display.VirtualDisplayConfig; import android.hardware.input.VirtualKeyboard; @@ -65,7 +67,7 @@ import java.util.function.IntConsumer; public final class VirtualDeviceManager { private static final boolean DEBUG = false; - private static final String LOG_TAG = "VirtualDeviceManager"; + private static final String TAG = "VirtualDeviceManager"; private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS = DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC @@ -150,6 +152,7 @@ public final class VirtualDeviceManager { public static class VirtualDevice implements AutoCloseable { private final Context mContext; + private final IVirtualDeviceManager mService; private final IVirtualDevice mVirtualDevice; private final ArrayMap mActivityListeners = new ArrayMap<>(); @@ -189,6 +192,7 @@ public final class VirtualDeviceManager { Context context, int associationId, VirtualDeviceParams params) throws RemoteException { + mService = service; mContext = context.getApplicationContext(); mVirtualDevice = service.createVirtualDevice( new Binder(), @@ -274,18 +278,23 @@ public final class VirtualDeviceManager { // TODO(b/205343547): Handle display groups properly instead of creating a new display // group for every new virtual display created using this API. // belongs to the same display group. - DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); - // DisplayManager will call into VirtualDeviceManagerInternal to register the - // created displays. - return displayManager.createVirtualDisplay( - mVirtualDevice, - new VirtualDisplayConfig.Builder( - getVirtualDisplayName(), width, height, densityDpi) - .setSurface(surface) - .setFlags(getVirtualDisplayFlags(flags)) - .build(), - callback, - executor); + VirtualDisplayConfig config = new VirtualDisplayConfig.Builder( + getVirtualDisplayName(), width, height, densityDpi) + .setSurface(surface) + .setFlags(getVirtualDisplayFlags(flags)) + .build(); + IVirtualDisplayCallback callbackWrapper = + new DisplayManagerGlobal.VirtualDisplayCallback(callback, executor); + final int displayId; + try { + displayId = mService.createVirtualDisplay(config, callbackWrapper, mVirtualDevice, + mContext.getPackageName()); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance(); + return displayManager.createVirtualDisplayWrapper(config, mContext, callbackWrapper, + displayId); } /** diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index eadcac91dcd7..b505395a091a 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -31,7 +31,6 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.app.KeyguardManager; -import android.companion.virtual.IVirtualDevice; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; @@ -971,17 +970,8 @@ public final class DisplayManager { executor = new HandlerExecutor( Handler.createAsync(handler != null ? handler.getLooper() : Looper.myLooper())); } - return mGlobal.createVirtualDisplay(mContext, projection, null /* virtualDevice */, - virtualDisplayConfig, callback, executor, windowContext); - } - - /** @hide */ - public VirtualDisplay createVirtualDisplay(@Nullable IVirtualDevice virtualDevice, - @NonNull VirtualDisplayConfig virtualDisplayConfig, - @Nullable VirtualDisplay.Callback callback, - @Nullable Executor executor) { - return mGlobal.createVirtualDisplay(mContext, null /* projection */, virtualDevice, - virtualDisplayConfig, callback, executor, null); + return mGlobal.createVirtualDisplay(mContext, projection, virtualDisplayConfig, callback, + executor, windowContext); } /** diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index a62bbf623000..74356ddecc76 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -24,7 +24,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.PropertyInvalidatedCache; -import android.companion.virtual.IVirtualDevice; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.ParceledListSlice; @@ -586,18 +585,28 @@ public final class DisplayManagerGlobal { } public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection, - IVirtualDevice virtualDevice, @NonNull VirtualDisplayConfig virtualDisplayConfig, - VirtualDisplay.Callback callback, @Nullable Executor executor, - @Nullable Context windowContext) { + @NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback, + @Nullable Executor executor, @Nullable Context windowContext) { VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, executor); IMediaProjection projectionToken = projection != null ? projection.getProjection() : null; int displayId; try { displayId = mDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper, - projectionToken, virtualDevice, context.getPackageName()); + projectionToken, context.getPackageName()); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } + return createVirtualDisplayWrapper(virtualDisplayConfig, windowContext, callbackWrapper, + displayId); + } + + /** + * Create a VirtualDisplay wrapper object for a newly created virtual display ; to be called + * once the display has been created in system_server. + */ + @Nullable + public VirtualDisplay createVirtualDisplayWrapper(VirtualDisplayConfig virtualDisplayConfig, + Context windowContext, IVirtualDisplayCallback callbackWrapper, int displayId) { if (displayId < 0) { Log.e(TAG, "Could not create virtual display: " + virtualDisplayConfig.getName()); return null; @@ -1050,7 +1059,10 @@ public final class DisplayManagerGlobal { } } - private final static class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub { + /** + * Assists in dispatching VirtualDisplay lifecycle event callbacks on a given Executor. + */ + public static final class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub { @Nullable private final VirtualDisplay.Callback mCallback; @Nullable private final Executor mExecutor; @@ -1062,7 +1074,7 @@ public final class DisplayManagerGlobal { * @param executor The executor to call the {@code callback} on. Must not be {@code null} if * the callback is not {@code null}. */ - VirtualDisplayCallback(VirtualDisplay.Callback callback, Executor executor) { + public VirtualDisplayCallback(VirtualDisplay.Callback callback, Executor executor) { mCallback = callback; mExecutor = mCallback != null ? Objects.requireNonNull(executor) : null; } diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index be482c9146c9..1c3bec5b52f4 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -18,6 +18,7 @@ package android.hardware.display; import android.annotation.IntDef; import android.annotation.Nullable; +import android.companion.virtual.IVirtualDevice; import android.graphics.Point; import android.hardware.SensorManager; import android.os.Handler; @@ -59,6 +60,14 @@ public abstract class DisplayManagerInternal { public abstract void initPowerManagement(DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager); + /** + * Called by the VirtualDeviceManagerService to create a VirtualDisplay owned by a + * VirtualDevice. + */ + public abstract int createVirtualDisplay(VirtualDisplayConfig config, + IVirtualDisplayCallback callback, IVirtualDevice virtualDevice, + DisplayWindowPolicyController dwpc, String packageName); + /** * Called by the power manager to request a new power state. *

diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index ddd18f4502e7..ca3e58094400 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -16,7 +16,6 @@ package android.hardware.display; -import android.companion.virtual.IVirtualDevice; import android.content.pm.ParceledListSlice; import android.graphics.Point; import android.hardware.display.BrightnessConfiguration; @@ -88,10 +87,10 @@ interface IDisplayManager { void requestColorMode(int displayId, int colorMode); // Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate - // MediaProjection token or VirtualDevice for certain combinations of flags. + // MediaProjection token for certain combinations of flags. int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig, in IVirtualDisplayCallback callback, in IMediaProjection projectionToken, - in IVirtualDevice virtualDevice, String packageName); + String packageName); // No permissions required, but must be same Uid as the creator. void resizeVirtualDisplay(in IVirtualDisplayCallback token, diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java index 4473a095063a..43e2b881927c 100644 --- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java @@ -48,7 +48,6 @@ import com.android.internal.app.BlockedAppStreamingActivity; import java.util.List; import java.util.Set; -import java.util.function.Consumer; /** @@ -66,6 +65,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController void onRunningAppsChanged(ArraySet runningUids); } + /** + * For communicating when activities are blocked from running on the display by this policy + * controller. + */ + public interface ActivityBlockedCallback { + /** Called when an activity is blocked.*/ + void onActivityBlocked(int displayId, ActivityInfo activityInfo); + } private static final ComponentName BLOCKED_APP_STREAMING_COMPONENT = new ComponentName("android", BlockedAppStreamingActivity.class.getName()); @@ -89,7 +96,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController private final Object mGenericWindowPolicyControllerLock = new Object(); @ActivityPolicy private final int mDefaultActivityPolicy; - private final Consumer mActivityBlockedCallback; + private final ActivityBlockedCallback mActivityBlockedCallback; + private int mDisplayId = Display.INVALID_DISPLAY; @NonNull @GuardedBy("mGenericWindowPolicyControllerLock") @@ -98,6 +106,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController private final Handler mHandler = new Handler(Looper.getMainLooper()); private final ArraySet mRunningAppsChangedListener = new ArraySet<>(); + @Nullable private final @AssociationRequest.DeviceProfile String mDeviceProfile; /** @@ -119,8 +128,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_ALLOWED} * @param defaultActivityPolicy Whether activities are default allowed to be displayed or * blocked. - * @param activityListener Activity listener to listen for activity changes. The display ID - * is not populated in this callback and is always {@link Display#INVALID_DISPLAY}. + * @param activityListener Activity listener to listen for activity changes. * @param activityBlockedCallback Callback that is called when an activity is blocked from * launching. * @param deviceProfile The {@link AssociationRequest.DeviceProfile} of this virtual device. @@ -133,7 +141,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @NonNull Set blockedActivities, @ActivityPolicy int defaultActivityPolicy, @NonNull ActivityListener activityListener, - @NonNull Consumer activityBlockedCallback, + @NonNull ActivityBlockedCallback activityBlockedCallback, @AssociationRequest.DeviceProfile String deviceProfile) { super(); mAllowedUsers = allowedUsers; @@ -148,6 +156,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController mDeviceProfile = deviceProfile; } + /** + * Expected to be called once this object is associated with a newly created display. + */ + public void setDisplayId(int displayId) { + mDisplayId = displayId; + } + /** Register a listener for running applications changes. */ public void registerRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) { mRunningAppsChangedListener.add(listener); @@ -169,7 +184,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController for (int i = 0; i < activityCount; i++) { final ActivityInfo aInfo = activities.get(i); if (!canContainActivity(aInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) { - mActivityBlockedCallback.accept(aInfo); + mActivityBlockedCallback.onActivityBlocked(mDisplayId, aInfo); return false; } } @@ -191,7 +206,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController } if (!canContainActivity(activityInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) { - mActivityBlockedCallback.accept(activityInfo); + mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo); return false; } @@ -201,14 +216,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController if (isNewTask && !mBlockedCrossTaskNavigations.isEmpty() && mBlockedCrossTaskNavigations.contains(activityComponent)) { Slog.d(TAG, "Virtual device blocking cross task navigation of " + activityComponent); - mActivityBlockedCallback.accept(activityInfo); + mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo); return false; } if (isNewTask && !mAllowedCrossTaskNavigations.isEmpty() && !mAllowedCrossTaskNavigations.contains(activityComponent)) { Slog.d(TAG, "Virtual device not allowing cross task navigation of " + activityComponent); - mActivityBlockedCallback.accept(activityInfo); + mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo); return false; } @@ -220,7 +235,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags, int systemWindowFlags) { if (!canContainActivity(activityInfo, windowFlags, systemWindowFlags)) { - mActivityBlockedCallback.accept(activityInfo); + mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo); return false; } return true; @@ -234,7 +249,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController if (mActivityListener != null && topActivity != null) { // Post callback on the main thread so it doesn't block activity launching mHandler.post(() -> - mActivityListener.onTopActivityChanged(Display.INVALID_DISPLAY, topActivity)); + mActivityListener.onTopActivityChanged(mDisplayId, topActivity)); } } @@ -245,7 +260,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController mRunningUids.addAll(runningUids); if (mActivityListener != null && mRunningUids.isEmpty()) { // Post callback on the main thread so it doesn't block activity launching - mHandler.post(() -> mActivityListener.onDisplayEmpty(Display.INVALID_DISPLAY)); + mHandler.post(() -> mActivityListener.onDisplayEmpty(mDisplayId)); } } mHandler.post(() -> { @@ -257,7 +272,10 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @Override public boolean canShowTasksInRecents() { - // TODO(b/234075973) : Remove this once proper API is ready. + if (mDeviceProfile == null) { + return true; + } + // TODO(b/234075973) : Remove this once proper API is ready. switch (mDeviceProfile) { case DEVICE_PROFILE_AUTOMOTIVE_PROJECTION: return false; diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java index 33fd83bf6bd7..3b3bf11f2d9e 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -64,7 +64,6 @@ import android.util.SparseArray; import android.view.Display; import android.view.WindowManager; import android.widget.Toast; -import android.window.DisplayWindowPolicyController; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -110,11 +109,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @GuardedBy("mVirtualDeviceLock") private boolean mDefaultShowPointerIcon = true; - private ActivityListener createListenerAdapter(int displayId) { + private ActivityListener createListenerAdapter() { return new ActivityListener() { @Override - public void onTopActivityChanged(int unusedDisplayId, ComponentName topActivity) { + public void onTopActivityChanged(int displayId, ComponentName topActivity) { try { mActivityListener.onTopActivityChanged(displayId, topActivity); } catch (RemoteException e) { @@ -123,7 +122,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } @Override - public void onDisplayEmpty(int unusedDisplayId) { + public void onDisplayEmpty(int displayId) { try { mActivityListener.onDisplayEmpty(displayId); } catch (RemoteException e) { @@ -529,24 +528,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mInputController.dump(fout); } - DisplayWindowPolicyController onVirtualDisplayCreatedLocked(int displayId) { + GenericWindowPolicyController createWindowPolicyController() { synchronized (mVirtualDeviceLock) { - if (mVirtualDisplayIds.contains(displayId)) { - throw new IllegalStateException( - "Virtual device already have a virtual display with ID " + displayId); - } - mVirtualDisplayIds.add(displayId); - mInputController.setShowPointerIcon(mDefaultShowPointerIcon, displayId); - mInputController.setPointerAcceleration(1f, displayId); - mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false, - displayId); - mInputController.setLocalIme(displayId); - - // Since we're being called in the middle of the display being created, we post a - // task to grab the wakelock instead of doing it synchronously here, to avoid - // reentrancy problems. - mContext.getMainThreadHandler().post(() -> addWakeLockForDisplay(displayId)); - final GenericWindowPolicyController gwpc = new GenericWindowPolicyController(FLAG_SECURE, SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, @@ -556,19 +539,36 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mParams.getAllowedActivities(), mParams.getBlockedActivities(), mParams.getDefaultActivityPolicy(), - createListenerAdapter(displayId), - activityInfo -> onActivityBlocked(displayId, activityInfo), + createListenerAdapter(), + this::onActivityBlocked, mAssociationInfo.getDeviceProfile()); gwpc.registerRunningAppsChangedListener(/* listener= */ this); - mWindowPolicyControllers.put(displayId, gwpc); return gwpc; } } - void addWakeLockForDisplay(int displayId) { + void onVirtualDisplayCreatedLocked(GenericWindowPolicyController gwpc, int displayId) { synchronized (mVirtualDeviceLock) { - if (!mVirtualDisplayIds.contains(displayId) - || mPerDisplayWakelocks.containsKey(displayId)) { + if (displayId == Display.INVALID_DISPLAY) { + return; + } + if (mVirtualDisplayIds.contains(displayId)) { + throw new IllegalStateException( + "Virtual device already has a virtual display with ID " + displayId); + } + mVirtualDisplayIds.add(displayId); + + gwpc.setDisplayId(displayId); + mWindowPolicyControllers.put(displayId, gwpc); + + mInputController.setShowPointerIcon(mDefaultShowPointerIcon, displayId); + mInputController.setPointerAcceleration(1f, displayId); + mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false, + displayId); + mInputController.setLocalIme(displayId); + + + if (mPerDisplayWakelocks.containsKey(displayId)) { Slog.e(TAG, "Not creating wakelock for displayId " + displayId); return; } @@ -576,8 +576,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub PowerManager.WakeLock wakeLock = powerManager.newWakeLock( PowerManager.SCREEN_BRIGHT_WAKE_LOCK, TAG + ":" + displayId, displayId); - wakeLock.acquire(); mPerDisplayWakelocks.put(displayId, wakeLock); + wakeLock.acquire(); } } diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java index 6398b2142e37..35e9060b58d4 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java @@ -31,6 +31,10 @@ import android.companion.virtual.IVirtualDeviceManager; import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceParams; import android.content.Context; +import android.hardware.display.DisplayManagerInternal; +import android.hardware.display.IVirtualDisplayCallback; +import android.hardware.display.VirtualDisplayConfig; +import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -41,9 +45,9 @@ import android.util.ExceptionUtils; import android.util.Slog; import android.util.SparseArray; import android.widget.Toast; -import android.window.DisplayWindowPolicyController; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; import com.android.server.SystemService; import com.android.server.companion.virtual.VirtualDeviceImpl.PendingTrampoline; @@ -203,6 +207,7 @@ public class VirtualDeviceManagerService extends SystemService { } } + @VisibleForTesting class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub implements VirtualDeviceImpl.PendingTrampolineCallback { @@ -265,6 +270,50 @@ public class VirtualDeviceManagerService extends SystemService { } } + @Override // Binder call + public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig, + IVirtualDisplayCallback callback, IVirtualDevice virtualDevice, String packageName) + throws RemoteException { + final int callingUid = getCallingUid(); + if (!PermissionUtils.validateCallingPackageName(getContext(), packageName)) { + throw new SecurityException( + "Package name " + packageName + " does not belong to calling uid " + + callingUid); + } + VirtualDeviceImpl virtualDeviceImpl; + synchronized (mVirtualDeviceManagerLock) { + virtualDeviceImpl = mVirtualDevices.get(virtualDevice.getAssociationId()); + if (virtualDeviceImpl == null) { + throw new SecurityException("Invalid VirtualDevice"); + } + } + if (virtualDeviceImpl.getOwnerUid() != callingUid) { + throw new SecurityException( + "uid " + callingUid + + " is not the owner of the supplied VirtualDevice"); + } + GenericWindowPolicyController gwpc; + final long token = Binder.clearCallingIdentity(); + try { + gwpc = virtualDeviceImpl.createWindowPolicyController(); + } finally { + Binder.restoreCallingIdentity(token); + } + + DisplayManagerInternal displayManager = getLocalService( + DisplayManagerInternal.class); + int displayId = displayManager.createVirtualDisplay(virtualDisplayConfig, callback, + virtualDevice, gwpc, packageName); + + final long tokenTwo = Binder.clearCallingIdentity(); + try { + virtualDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, displayId); + return displayId; + } finally { + Binder.restoreCallingIdentity(tokenTwo); + } + } + @Nullable private AssociationInfo getAssociationInfo(String packageName, int associationId) { final int callingUserId = getCallingUserHandle().getIdentifier(); @@ -336,14 +385,6 @@ public class VirtualDeviceManagerService extends SystemService { } } - @Override - public DisplayWindowPolicyController onVirtualDisplayCreated(IVirtualDevice virtualDevice, - int displayId) { - synchronized (mVirtualDeviceManagerLock) { - return ((VirtualDeviceImpl) virtualDevice).onVirtualDisplayCreatedLocked(displayId); - } - } - @Override public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) { synchronized (mVirtualDeviceManagerLock) { diff --git a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java index 94d3d15aec33..f2b4d42c8758 100644 --- a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java +++ b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java @@ -17,7 +17,6 @@ package com.android.server.companion.virtual; import android.companion.virtual.IVirtualDevice; -import android.window.DisplayWindowPolicyController; /** * Virtual device manager local service interface. @@ -30,17 +29,6 @@ public abstract class VirtualDeviceManagerInternal { */ public abstract boolean isValidVirtualDevice(IVirtualDevice virtualDevice); - /** - * Notify a virtual display is created. - * - * @param virtualDevice The virtual device where the virtual display located. - * @param displayId The display id of the created virtual display. - * - * @return The {@link DisplayWindowPolicyController} of the virtual device. - */ - public abstract DisplayWindowPolicyController onVirtualDisplayCreated( - IVirtualDevice virtualDevice, int displayId); - /** * Notify a virtual display is removed. * diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index e77693650eda..ec7ccc4843c9 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -1231,7 +1231,7 @@ public final class DisplayManagerService extends SystemService { private int createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig, IVirtualDisplayCallback callback, IMediaProjection projection, - IVirtualDevice virtualDevice, String packageName) { + IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, String packageName) { final int callingUid = Binder.getCallingUid(); if (!validatePackageName(callingUid, packageName)) { throw new SecurityException("packageName must match the calling uid"); @@ -1351,8 +1351,13 @@ public final class DisplayManagerService extends SystemService { final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { - return createVirtualDisplayLocked(callback, projection, virtualDevice, callingUid, + final int displayId = createVirtualDisplayLocked(callback, projection, callingUid, packageName, surface, flags, virtualDisplayConfig); + if (displayId != Display.INVALID_DISPLAY && virtualDevice != null && dwpc != null) { + mDisplayWindowPolicyControllers.put(displayId, + Pair.create(virtualDevice, dwpc)); + } + return displayId; } } finally { Binder.restoreCallingIdentity(token); @@ -1360,8 +1365,7 @@ public final class DisplayManagerService extends SystemService { } private int createVirtualDisplayLocked(IVirtualDisplayCallback callback, - IMediaProjection projection, IVirtualDevice virtualDevice, - int callingUid, String packageName, Surface surface, + IMediaProjection projection, int callingUid, String packageName, Surface surface, int flags, VirtualDisplayConfig virtualDisplayConfig) { if (mVirtualDisplayAdapter == null) { Slog.w(TAG, "Rejecting request to create private virtual display " @@ -1389,16 +1393,7 @@ public final class DisplayManagerService extends SystemService { final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); if (display != null) { - final int displayId = display.getDisplayIdLocked(); - if (virtualDevice != null) { - final VirtualDeviceManagerInternal vdm = - getLocalService(VirtualDeviceManagerInternal.class); - final DisplayWindowPolicyController controller = - vdm.onVirtualDisplayCreated(virtualDevice, displayId); - mDisplayWindowPolicyControllers.put(displayId, - Pair.create(virtualDevice, controller)); - } - return displayId; + return display.getDisplayIdLocked(); } // Something weird happened and the logical display was not created. @@ -3066,9 +3061,9 @@ public final class DisplayManagerService extends SystemService { @Override // Binder call public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig, IVirtualDisplayCallback callback, IMediaProjection projection, - IVirtualDevice virtualDeviceToken, String packageName) { + String packageName) { return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection, - virtualDeviceToken, packageName); + null, null, packageName); } @Override // Binder call @@ -3534,7 +3529,8 @@ public final class DisplayManagerService extends SystemService { return !Float.isNaN(refreshRate) && (refreshRate > 0.0f); } - private final class LocalService extends DisplayManagerInternal { + @VisibleForTesting + final class LocalService extends DisplayManagerInternal { @Override public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, @@ -3549,6 +3545,14 @@ public final class DisplayManagerService extends SystemService { mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS); } + @Override + public int createVirtualDisplay(VirtualDisplayConfig config, + IVirtualDisplayCallback callback, IVirtualDevice virtualDevice, + DisplayWindowPolicyController dwpc, String packageName) { + return createVirtualDisplayInternal(config, callback, null, virtualDevice, dwpc, + packageName); + } + @Override public boolean requestPowerState(int groupId, DisplayPowerRequest request, boolean waitForNegativeProximity) { diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java index f9671e56fe12..f242fda15f06 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java @@ -228,36 +228,36 @@ public class VirtualDeviceManagerServiceTest { @Test public void onVirtualDisplayRemovedLocked_doesNotThrowException() { - final int displayId = 2; - mDeviceImpl.onVirtualDisplayCreatedLocked(displayId); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); // This call should not throw any exceptions. - mDeviceImpl.onVirtualDisplayRemovedLocked(displayId); + mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID); } @Test public void onVirtualDisplayCreatedLocked_wakeLockIsAcquired() throws RemoteException { - final int displayId = 2; - mDeviceImpl.onVirtualDisplayCreatedLocked(displayId); verify(mIPowerManagerMock, never()).acquireWakeLock(any(Binder.class), anyInt(), nullable(String.class), nullable(String.class), nullable(WorkSource.class), nullable(String.class), anyInt(), eq(null)); - TestableLooper.get(this).processAllMessages(); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(), nullable(String.class), nullable(String.class), nullable(WorkSource.class), - nullable(String.class), eq(displayId), eq(null)); + nullable(String.class), eq(DISPLAY_ID), eq(null)); } @Test public void onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired() throws RemoteException { - final int displayId = 2; - mDeviceImpl.onVirtualDisplayCreatedLocked(displayId); + GenericWindowPolicyController gwpc = mDeviceImpl.createWindowPolicyController(); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); assertThrows(IllegalStateException.class, - () -> mDeviceImpl.onVirtualDisplayCreatedLocked(displayId)); + () -> mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID)); TestableLooper.get(this).processAllMessages(); verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(), nullable(String.class), nullable(String.class), nullable(WorkSource.class), - nullable(String.class), eq(displayId), eq(null)); + nullable(String.class), eq(DISPLAY_ID), eq(null)); } @Test @@ -269,30 +269,30 @@ public class VirtualDeviceManagerServiceTest { @Test public void onVirtualDisplayRemovedLocked_wakeLockIsReleased() throws RemoteException { - final int displayId = 2; - mDeviceImpl.onVirtualDisplayCreatedLocked(displayId); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); ArgumentCaptor wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class); TestableLooper.get(this).processAllMessages(); verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(), anyInt(), nullable(String.class), nullable(String.class), nullable(WorkSource.class), - nullable(String.class), eq(displayId), eq(null)); + nullable(String.class), eq(DISPLAY_ID), eq(null)); IBinder wakeLock = wakeLockCaptor.getValue(); - mDeviceImpl.onVirtualDisplayRemovedLocked(displayId); + mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID); verify(mIPowerManagerMock, Mockito.times(1)).releaseWakeLock(eq(wakeLock), anyInt()); } @Test public void addVirtualDisplay_displayNotReleased_wakeLockIsReleased() throws RemoteException { - final int displayId = 2; - mDeviceImpl.onVirtualDisplayCreatedLocked(displayId); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); ArgumentCaptor wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class); TestableLooper.get(this).processAllMessages(); verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(), anyInt(), nullable(String.class), nullable(String.class), nullable(WorkSource.class), - nullable(String.class), eq(displayId), eq(null)); + nullable(String.class), eq(DISPLAY_ID), eq(null)); IBinder wakeLock = wakeLockCaptor.getValue(); // Close the VirtualDevice without first notifying it of the VirtualDisplay removal. @@ -416,7 +416,8 @@ public class VirtualDeviceManagerServiceTest { @Test public void onAudioSessionStarting_hasVirtualAudioController() { - mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback); @@ -425,7 +426,8 @@ public class VirtualDeviceManagerServiceTest { @Test public void onAudioSessionEnded_noVirtualAudioController() { - mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback); mDeviceImpl.onAudioSessionEnded(); @@ -435,7 +437,8 @@ public class VirtualDeviceManagerServiceTest { @Test public void close_cleanVirtualAudioController() { - mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback); mDeviceImpl.close(); @@ -659,7 +662,8 @@ public class VirtualDeviceManagerServiceTest { @Test public void openNonBlockedAppOnVirtualDisplay_doesNotStartBlockedAlertActivity() { - mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( DISPLAY_ID); doNothing().when(mContext).startActivityAsUser(any(), any(), any()); @@ -677,7 +681,8 @@ public class VirtualDeviceManagerServiceTest { @Test public void openPermissionControllerOnVirtualDisplay_startBlockedAlertActivity() { - mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( DISPLAY_ID); doNothing().when(mContext).startActivityAsUser(any(), any(), any()); @@ -695,7 +700,8 @@ public class VirtualDeviceManagerServiceTest { @Test public void openSettingsOnVirtualDisplay_startBlockedAlertActivity() { - mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( DISPLAY_ID); doNothing().when(mContext).startActivityAsUser(any(), any(), any()); @@ -713,7 +719,8 @@ public class VirtualDeviceManagerServiceTest { @Test public void openVendingOnVirtualDisplay_startBlockedAlertActivity() { - mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( DISPLAY_ID); doNothing().when(mContext).startActivityAsUser(any(), any(), any()); @@ -731,7 +738,8 @@ public class VirtualDeviceManagerServiceTest { @Test public void openGoogleDialerOnVirtualDisplay_startBlockedAlertActivity() { - mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( DISPLAY_ID); doNothing().when(mContext).startActivityAsUser(any(), any(), any()); @@ -749,7 +757,8 @@ public class VirtualDeviceManagerServiceTest { @Test public void openGoogleMapsOnVirtualDisplay_startBlockedAlertActivity() { - mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID); + mDeviceImpl.onVirtualDisplayCreatedLocked( + mDeviceImpl.createWindowPolicyController(), DISPLAY_ID); GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get( DISPLAY_ID); doNothing().when(mContext).startActivityAsUser(any(), any(), any()); diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java index 6f48368c6ab2..1e97c1c5c5bc 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -45,6 +45,7 @@ import android.hardware.display.BrightnessConfiguration; import android.hardware.display.Curve; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; +import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayViewport; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; @@ -63,6 +64,7 @@ import android.view.DisplayEventReceiver; import android.view.DisplayInfo; import android.view.Surface; import android.view.SurfaceControl; +import android.window.DisplayWindowPolicyController; import androidx.test.InstrumentationRegistry; import androidx.test.core.app.ApplicationProvider; @@ -220,7 +222,7 @@ public class DisplayManagerServiceTest { builder.setUniqueId(uniqueId); builder.setFlags(flags); int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, - null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME); + null /* projection */, PACKAGE_NAME); displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); @@ -346,7 +348,7 @@ public class DisplayManagerServiceTest { builder.setFlags(flags); builder.setUniqueId(uniqueId); int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, - null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME); + null /* projection */, PACKAGE_NAME); displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); @@ -586,8 +588,7 @@ public class DisplayManagerServiceTest { VIRTUAL_DISPLAY_NAME, width, height, dpi); builder.setUniqueId(uniqueId); final int firstDisplayId = binderService.createVirtualDisplay(builder.build(), - mMockAppToken /* callback */, null /* projection */, null /* virtualDeviceToken */, - PACKAGE_NAME); + mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME); // The second virtual display requests to mirror the first virtual display. final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2"; @@ -598,7 +599,7 @@ public class DisplayManagerServiceTest { builder2.setDisplayIdToMirror(firstDisplayId); final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(), mMockAppToken2 /* callback */, null /* projection */, - null /* virtualDeviceToken */, PACKAGE_NAME); + PACKAGE_NAME); displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); // flush the handler @@ -636,8 +637,7 @@ public class DisplayManagerServiceTest { builder.setSurface(surface); builder.setUniqueId(uniqueId); final int displayId = binderService.createVirtualDisplay(builder.build(), - mMockAppToken /* callback */, null /* projection */, null /* virtualDeviceToken */, - PACKAGE_NAME); + mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME); displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); @@ -669,7 +669,7 @@ public class DisplayManagerServiceTest { builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP"); int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, - null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME); + null /* projection */, PACKAGE_NAME); displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */); DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId); @@ -700,7 +700,7 @@ public class DisplayManagerServiceTest { try { bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, - null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME); + null /* projection */, PACKAGE_NAME); fail("Creating virtual display with VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP without " + "ADD_TRUSTED_DISPLAY permission should throw SecurityException."); } catch (SecurityException e) { @@ -716,6 +716,8 @@ public class DisplayManagerServiceTest { public void testOwnDisplayGroup_allowCreationWithVirtualDevice() { DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); + DisplayManagerInternal localService = displayManager.new LocalService(); + registerDefaultDisplays(displayManager); DisplayManagerService.BinderService bs = displayManager.new BinderService(); @@ -733,8 +735,9 @@ public class DisplayManagerServiceTest { when(mMockVirtualDeviceManagerInternal.isValidVirtualDevice(virtualDevice)) .thenReturn(true); - int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */, - null /* projection */, virtualDevice /* virtualDeviceToken */, PACKAGE_NAME); + int displayId = localService.createVirtualDisplay(builder.build(), + mMockAppToken /* callback */, virtualDevice /* virtualDeviceToken */, + mock(DisplayWindowPolicyController.class), PACKAGE_NAME); displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */); DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId); -- cgit v1.2.3-59-g8ed1b