Loading services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +104 −70 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import android.util.SparseIntArray; 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; Loading Loading @@ -1411,8 +1412,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return mirroredDisplayId == Display.INVALID_DISPLAY ? displayId : mirroredDisplayId; } @GuardedBy("mVirtualDeviceLock") private GenericWindowPolicyController createWindowPolicyControllerLocked( private GenericWindowPolicyController createWindowPolicyController( @NonNull Set<String> displayCategories) { final boolean activityLaunchAllowedByDefault = getDevicePolicy(POLICY_TYPE_ACTIVITY) == DEVICE_POLICY_DEFAULT; Loading @@ -1421,11 +1421,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub final boolean showTasksInHostDeviceRecents = getDevicePolicy(POLICY_TYPE_RECENTS) == DEVICE_POLICY_DEFAULT; synchronized (mVirtualDeviceLock) { if (mActivityListenerAdapter == null) { mActivityListenerAdapter = new GwpcActivityListener(); } final GenericWindowPolicyController gwpc = new GenericWindowPolicyController( return new GenericWindowPolicyController( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, mAttributionSource, Loading @@ -1441,8 +1442,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub displayCategories, showTasksInHostDeviceRecents, mParams.getHomeComponent()); gwpc.registerRunningAppsChangedListener(/* listener= */ this); return gwpc; } } @Override // Binder call Loading @@ -1450,55 +1450,54 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @NonNull IVirtualDisplayCallback callback) { checkCallerIsDeviceOwner(); int displayId; boolean showPointer; boolean isTrustedDisplay; GenericWindowPolicyController gwpc; synchronized (mVirtualDeviceLock) { gwpc = createWindowPolicyControllerLocked(virtualDisplayConfig.getDisplayCategories()); displayId = mDisplayManagerInternal.createVirtualDisplay(virtualDisplayConfig, callback, this, gwpc, mOwnerPackageName); boolean isMirrorDisplay = mDisplayManagerInternal.getDisplayIdToMirror(displayId) != Display.INVALID_DISPLAY; gwpc.setDisplayId(displayId, isMirrorDisplay); isTrustedDisplay = (mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED) == Display.FLAG_TRUSTED; if (!isTrustedDisplay && getDevicePolicy(POLICY_TYPE_CLIPBOARD) != DEVICE_POLICY_DEFAULT) { throw new SecurityException("All displays must be trusted for devices with " + "custom clipboard policy."); final boolean isTrustedDisplay = (virtualDisplayConfig.getFlags() & DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED) == DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; if (!isTrustedDisplay && getDevicePolicy(POLICY_TYPE_CLIPBOARD) != DEVICE_POLICY_DEFAULT) { throw new SecurityException( "All displays must be trusted for devices with custom clipboard policy."); } if (mVirtualDisplays.contains(displayId)) { gwpc.unregisterRunningAppsChangedListener(this); throw new IllegalStateException( "Virtual device already has a virtual display with ID " + displayId); GenericWindowPolicyController gwpc = createWindowPolicyController(virtualDisplayConfig.getDisplayCategories()); // Create the display outside of the lock to avoid deadlock. DisplayManagerService will // acquire the global WM lock while creating the display. At the same time, WM may query // VDM and this virtual device to get policies, display ownership, etc. int displayId = mDisplayManagerInternal.createVirtualDisplay(virtualDisplayConfig, callback, this, gwpc, mOwnerPackageName); if (displayId == Display.INVALID_DISPLAY) { return displayId; } PowerManager.WakeLock wakeLock = isTrustedDisplay ? createAndAcquireWakeLockForDisplay(displayId) : null; mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock, isTrustedDisplay, isMirrorDisplay)); // DisplayManagerService will call onVirtualDisplayCreated() after the display is created, // while holding its own lock to ensure that this device knows about the display before any // other display listeners are notified about the display creation. VirtualDisplayWrapper displayWrapper; boolean showPointer; synchronized (mVirtualDeviceLock) { if (!mVirtualDisplays.contains(displayId)) { throw new IllegalStateException("Virtual device was not notified about the " + "creation of display with ID " + displayId); } displayWrapper = mVirtualDisplays.get(displayId); showPointer = mDefaultShowPointerIcon; } displayWrapper.acquireWakeLock(); gwpc.registerRunningAppsChangedListener(/* listener= */ this); final long token = Binder.clearCallingIdentity(); try { Binder.withCleanCallingIdentity(() -> { mInputController.setMouseScalingEnabled(false, displayId); mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false, displayId); if (isTrustedDisplay) { if (displayWrapper.isTrusted()) { mInputController.setShowPointerIcon(showPointer, displayId); mInputController.setDisplayImePolicy(displayId, WindowManager.DISPLAY_IME_POLICY_LOCAL); } else { gwpc.setShowInHostDeviceRecents(true); } } finally { Binder.restoreCallingIdentity(token); } }); Counter.logIncrementWithUid( "virtual_devices.value_virtual_display_created_count", Loading @@ -1506,7 +1505,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return displayId; } private PowerManager.WakeLock createAndAcquireWakeLockForDisplay(int displayId) { private PowerManager.WakeLock createWakeLockForDisplay(int displayId) { if (Flags.deviceAwareDisplayPower()) { return null; } Loading @@ -1516,7 +1515,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub PowerManager.WakeLock wakeLock = powerManager.newWakeLock( PowerManager.SCREEN_BRIGHT_WAKE_LOCK, TAG + ":" + displayId, displayId); wakeLock.acquire(); return wakeLock; } finally { Binder.restoreCallingIdentity(token); Loading Loading @@ -1561,8 +1559,37 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return result; } void onVirtualDisplayRemoved(int displayId) { /* This is callback invoked by VirtualDeviceManagerService when VirtualDisplay was released /** * DisplayManagerService is notifying this virtual device about the display creation. This * should happen before the DisplayManagerInternal#createVirtualDisplay() call above * returns. * This is called while holding the DisplayManagerService lock, so no heavy-weight work must * be done here and especially *** no calls to WindowManager! *** */ public void onVirtualDisplayCreated(int displayId, IVirtualDisplayCallback callback, DisplayWindowPolicyController dwpc) { final boolean isMirrorDisplay = mDisplayManagerInternal.getDisplayIdToMirror(displayId) != Display.INVALID_DISPLAY; final boolean isTrustedDisplay = (mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED) == Display.FLAG_TRUSTED; GenericWindowPolicyController gwpc = (GenericWindowPolicyController) dwpc; gwpc.setDisplayId(displayId, isMirrorDisplay); PowerManager.WakeLock wakeLock = isTrustedDisplay ? createWakeLockForDisplay(displayId) : null; synchronized (mVirtualDeviceLock) { if (mVirtualDisplays.contains(displayId)) { Slog.wtf(TAG, "Virtual device already has a virtual display with ID " + displayId); return; } mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock, isTrustedDisplay, isMirrorDisplay)); } } /** * This is callback invoked by VirtualDeviceManagerService when VirtualDisplay was released * by DisplayManager (most probably caused by someone calling VirtualDisplay.close()). * At this point, the display is already released, but we still need to release the * corresponding wakeLock and unregister the RunningAppsChangedListener from corresponding Loading @@ -1572,6 +1599,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub * this callback won't be invoked because the display is removed from * VirtualDeviceManagerService before any resources are released. */ void onVirtualDisplayRemoved(int displayId) { VirtualDisplayWrapper virtualDisplayWrapper; synchronized (mVirtualDeviceLock) { virtualDisplayWrapper = mVirtualDisplays.removeReturnOld(displayId); Loading Loading @@ -1847,6 +1875,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return mWindowPolicyController; } void acquireWakeLock() { if (mWakeLock != null && !mWakeLock.isHeld()) { mWakeLock.acquire(); } } void releaseWakeLock() { if (mWakeLock != null && mWakeLock.isHeld()) { mWakeLock.release(); Loading services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +12 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,6 @@ import android.companion.virtual.IVirtualDeviceSoundEffectListener; import android.companion.virtual.VirtualDevice; import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.flags.Flags; import android.companion.virtual.sensor.VirtualSensor; import android.companion.virtualnative.IVirtualDeviceManagerNative; import android.compat.annotation.ChangeId; Loading @@ -49,6 +48,7 @@ import android.content.AttributionSource; import android.content.Context; import android.content.Intent; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.IVirtualDisplayCallback; import android.os.Binder; import android.os.Build; import android.os.Handler; Loading @@ -67,6 +67,7 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.widget.Toast; import android.window.DisplayWindowPolicyController; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -750,6 +751,16 @@ public class VirtualDeviceManagerService extends SystemService { return result; } @Override public void onVirtualDisplayCreated(IVirtualDevice virtualDevice, int displayId, IVirtualDisplayCallback callback, DisplayWindowPolicyController dwpc) { VirtualDeviceImpl virtualDeviceImpl = getVirtualDeviceForId( ((VirtualDeviceImpl) virtualDevice).getDeviceId()); if (virtualDeviceImpl != null) { virtualDeviceImpl.onVirtualDisplayCreated(displayId, callback, dwpc); } } @Override public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) { VirtualDeviceImpl virtualDeviceImpl = getVirtualDeviceForId( Loading services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java +13 −0 Original line number Diff line number Diff line Loading @@ -24,8 +24,10 @@ import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.sensor.VirtualSensor; import android.content.Context; import android.hardware.display.IVirtualDisplayCallback; import android.os.LocaleList; import android.util.ArraySet; import android.window.DisplayWindowPolicyController; import java.util.Set; import java.util.function.Consumer; Loading Loading @@ -103,6 +105,17 @@ public abstract class VirtualDeviceManagerInternal { */ public abstract @NonNull ArraySet<Integer> getDeviceIdsForUid(int uid); /** * Notifies that a virtual display was created. * * @param virtualDevice The virtual device that owns the virtual display. * @param displayId The display id of the created virtual display. * @param callback The callback of the virtual display. * @param dwpc The DisplayWindowPolicyController of the created virtual display. */ public abstract void onVirtualDisplayCreated(IVirtualDevice virtualDevice, int displayId, IVirtualDisplayCallback callback, DisplayWindowPolicyController dwpc); /** * Notifies that a virtual display is removed. * Loading services/core/java/com/android/server/display/DisplayManagerService.java +12 −0 Original line number Diff line number Diff line Loading @@ -2041,6 +2041,7 @@ public final class DisplayManagerService extends SystemService { packageName, displayUniqueId, virtualDevice, dwpc, surface, flags, virtualDisplayConfig); Loading Loading @@ -2135,6 +2136,7 @@ public final class DisplayManagerService extends SystemService { String packageName, String uniqueId, IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, Surface surface, int flags, VirtualDisplayConfig virtualDisplayConfig) { Loading Loading @@ -2188,6 +2190,16 @@ public final class DisplayManagerService extends SystemService { final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); if (display != null) { // Notify the virtual device that the display has been created. This needs to be called // in this locked section before the repository had the chance to notify any listeners // to ensure that the device is aware of the new display before others know about it. if (virtualDevice != null) { final VirtualDeviceManagerInternal vdm = getLocalService(VirtualDeviceManagerInternal.class); vdm.onVirtualDisplayCreated( virtualDevice, display.getDisplayIdLocked(), callback, dwpc); } return display.getDisplayIdLocked(); } Loading services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +25 −8 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.hardware.Sensor; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.IDisplayManager; Loading Loading @@ -173,8 +174,7 @@ public class VirtualDeviceManagerServiceTest { private static final int FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES = 0x00000; private static final int VIRTUAL_DEVICE_ID_1 = 42; private static final int VIRTUAL_DEVICE_ID_2 = 43; private static final VirtualDisplayConfig VIRTUAL_DISPLAY_CONFIG = new VirtualDisplayConfig.Builder("virtual_display", 640, 480, 400).build(); private static final VirtualDpadConfig DPAD_CONFIG = new VirtualDpadConfig.Builder() .setVendorId(VENDOR_ID) Loading Loading @@ -284,7 +284,12 @@ public class VirtualDeviceManagerServiceTest { private Intent createRestrictedActivityBlockedIntent(Set<String> displayCategories, String targetDisplayCategory) { when(mDisplayManagerInternalMock.createVirtualDisplay(any(), any(), any(), any(), eq(VIRTUAL_DEVICE_OWNER_PACKAGE))).thenReturn(DISPLAY_ID_1); eq(VIRTUAL_DEVICE_OWNER_PACKAGE))) .thenAnswer(inv -> { mLocalService.onVirtualDisplayCreated( mDeviceImpl, DISPLAY_ID_1, inv.getArgument(1), inv.getArgument(3)); return DISPLAY_ID_1; }); VirtualDisplayConfig config = new VirtualDisplayConfig.Builder("display", 640, 480, 420).setDisplayCategories(displayCategories).build(); mDeviceImpl.createVirtualDisplay(config, mVirtualDisplayCallback); Loading Loading @@ -997,8 +1002,7 @@ public class VirtualDeviceManagerServiceTest { public void onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired() throws RemoteException { addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1, Display.FLAG_TRUSTED); assertThrows(IllegalStateException.class, () -> addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1)); addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1, Display.FLAG_TRUSTED); TestableLooper.get(this).processAllMessages(); verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(), nullable(String.class), nullable(String.class), nullable(WorkSource.class), Loading Loading @@ -1871,8 +1875,6 @@ public class VirtualDeviceManagerServiceTest { } private void addVirtualDisplay(VirtualDeviceImpl virtualDevice, int displayId, int flags) { when(mDisplayManagerInternalMock.createVirtualDisplay(any(), eq(mVirtualDisplayCallback), eq(virtualDevice), any(), any())).thenReturn(displayId); final String uniqueId = UNIQUE_ID + displayId; doAnswer(inv -> { final DisplayInfo displayInfo = new DisplayInfo(); Loading @@ -1880,7 +1882,22 @@ public class VirtualDeviceManagerServiceTest { displayInfo.flags = flags; return displayInfo; }).when(mDisplayManagerInternalMock).getDisplayInfo(eq(displayId)); virtualDevice.createVirtualDisplay(VIRTUAL_DISPLAY_CONFIG, mVirtualDisplayCallback); when(mDisplayManagerInternalMock.createVirtualDisplay(any(), eq(mVirtualDisplayCallback), eq(virtualDevice), any(), any())).thenAnswer(inv -> { mLocalService.onVirtualDisplayCreated( virtualDevice, displayId, mVirtualDisplayCallback, inv.getArgument(3)); return displayId; }); final int virtualDisplayFlags = (flags & Display.FLAG_TRUSTED) == 0 ? 0 : DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; VirtualDisplayConfig virtualDisplayConfig = new VirtualDisplayConfig.Builder("virtual_display", 640, 480, 400) .setFlags(virtualDisplayFlags) .build(); virtualDevice.createVirtualDisplay(virtualDisplayConfig, mVirtualDisplayCallback); mInputManagerMockHelper.addDisplayIdMapping(uniqueId, displayId); } Loading Loading
services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +104 −70 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import android.util.SparseIntArray; 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; Loading Loading @@ -1411,8 +1412,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return mirroredDisplayId == Display.INVALID_DISPLAY ? displayId : mirroredDisplayId; } @GuardedBy("mVirtualDeviceLock") private GenericWindowPolicyController createWindowPolicyControllerLocked( private GenericWindowPolicyController createWindowPolicyController( @NonNull Set<String> displayCategories) { final boolean activityLaunchAllowedByDefault = getDevicePolicy(POLICY_TYPE_ACTIVITY) == DEVICE_POLICY_DEFAULT; Loading @@ -1421,11 +1421,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub final boolean showTasksInHostDeviceRecents = getDevicePolicy(POLICY_TYPE_RECENTS) == DEVICE_POLICY_DEFAULT; synchronized (mVirtualDeviceLock) { if (mActivityListenerAdapter == null) { mActivityListenerAdapter = new GwpcActivityListener(); } final GenericWindowPolicyController gwpc = new GenericWindowPolicyController( return new GenericWindowPolicyController( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, mAttributionSource, Loading @@ -1441,8 +1442,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub displayCategories, showTasksInHostDeviceRecents, mParams.getHomeComponent()); gwpc.registerRunningAppsChangedListener(/* listener= */ this); return gwpc; } } @Override // Binder call Loading @@ -1450,55 +1450,54 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @NonNull IVirtualDisplayCallback callback) { checkCallerIsDeviceOwner(); int displayId; boolean showPointer; boolean isTrustedDisplay; GenericWindowPolicyController gwpc; synchronized (mVirtualDeviceLock) { gwpc = createWindowPolicyControllerLocked(virtualDisplayConfig.getDisplayCategories()); displayId = mDisplayManagerInternal.createVirtualDisplay(virtualDisplayConfig, callback, this, gwpc, mOwnerPackageName); boolean isMirrorDisplay = mDisplayManagerInternal.getDisplayIdToMirror(displayId) != Display.INVALID_DISPLAY; gwpc.setDisplayId(displayId, isMirrorDisplay); isTrustedDisplay = (mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED) == Display.FLAG_TRUSTED; if (!isTrustedDisplay && getDevicePolicy(POLICY_TYPE_CLIPBOARD) != DEVICE_POLICY_DEFAULT) { throw new SecurityException("All displays must be trusted for devices with " + "custom clipboard policy."); final boolean isTrustedDisplay = (virtualDisplayConfig.getFlags() & DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED) == DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; if (!isTrustedDisplay && getDevicePolicy(POLICY_TYPE_CLIPBOARD) != DEVICE_POLICY_DEFAULT) { throw new SecurityException( "All displays must be trusted for devices with custom clipboard policy."); } if (mVirtualDisplays.contains(displayId)) { gwpc.unregisterRunningAppsChangedListener(this); throw new IllegalStateException( "Virtual device already has a virtual display with ID " + displayId); GenericWindowPolicyController gwpc = createWindowPolicyController(virtualDisplayConfig.getDisplayCategories()); // Create the display outside of the lock to avoid deadlock. DisplayManagerService will // acquire the global WM lock while creating the display. At the same time, WM may query // VDM and this virtual device to get policies, display ownership, etc. int displayId = mDisplayManagerInternal.createVirtualDisplay(virtualDisplayConfig, callback, this, gwpc, mOwnerPackageName); if (displayId == Display.INVALID_DISPLAY) { return displayId; } PowerManager.WakeLock wakeLock = isTrustedDisplay ? createAndAcquireWakeLockForDisplay(displayId) : null; mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock, isTrustedDisplay, isMirrorDisplay)); // DisplayManagerService will call onVirtualDisplayCreated() after the display is created, // while holding its own lock to ensure that this device knows about the display before any // other display listeners are notified about the display creation. VirtualDisplayWrapper displayWrapper; boolean showPointer; synchronized (mVirtualDeviceLock) { if (!mVirtualDisplays.contains(displayId)) { throw new IllegalStateException("Virtual device was not notified about the " + "creation of display with ID " + displayId); } displayWrapper = mVirtualDisplays.get(displayId); showPointer = mDefaultShowPointerIcon; } displayWrapper.acquireWakeLock(); gwpc.registerRunningAppsChangedListener(/* listener= */ this); final long token = Binder.clearCallingIdentity(); try { Binder.withCleanCallingIdentity(() -> { mInputController.setMouseScalingEnabled(false, displayId); mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false, displayId); if (isTrustedDisplay) { if (displayWrapper.isTrusted()) { mInputController.setShowPointerIcon(showPointer, displayId); mInputController.setDisplayImePolicy(displayId, WindowManager.DISPLAY_IME_POLICY_LOCAL); } else { gwpc.setShowInHostDeviceRecents(true); } } finally { Binder.restoreCallingIdentity(token); } }); Counter.logIncrementWithUid( "virtual_devices.value_virtual_display_created_count", Loading @@ -1506,7 +1505,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return displayId; } private PowerManager.WakeLock createAndAcquireWakeLockForDisplay(int displayId) { private PowerManager.WakeLock createWakeLockForDisplay(int displayId) { if (Flags.deviceAwareDisplayPower()) { return null; } Loading @@ -1516,7 +1515,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub PowerManager.WakeLock wakeLock = powerManager.newWakeLock( PowerManager.SCREEN_BRIGHT_WAKE_LOCK, TAG + ":" + displayId, displayId); wakeLock.acquire(); return wakeLock; } finally { Binder.restoreCallingIdentity(token); Loading Loading @@ -1561,8 +1559,37 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return result; } void onVirtualDisplayRemoved(int displayId) { /* This is callback invoked by VirtualDeviceManagerService when VirtualDisplay was released /** * DisplayManagerService is notifying this virtual device about the display creation. This * should happen before the DisplayManagerInternal#createVirtualDisplay() call above * returns. * This is called while holding the DisplayManagerService lock, so no heavy-weight work must * be done here and especially *** no calls to WindowManager! *** */ public void onVirtualDisplayCreated(int displayId, IVirtualDisplayCallback callback, DisplayWindowPolicyController dwpc) { final boolean isMirrorDisplay = mDisplayManagerInternal.getDisplayIdToMirror(displayId) != Display.INVALID_DISPLAY; final boolean isTrustedDisplay = (mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED) == Display.FLAG_TRUSTED; GenericWindowPolicyController gwpc = (GenericWindowPolicyController) dwpc; gwpc.setDisplayId(displayId, isMirrorDisplay); PowerManager.WakeLock wakeLock = isTrustedDisplay ? createWakeLockForDisplay(displayId) : null; synchronized (mVirtualDeviceLock) { if (mVirtualDisplays.contains(displayId)) { Slog.wtf(TAG, "Virtual device already has a virtual display with ID " + displayId); return; } mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock, isTrustedDisplay, isMirrorDisplay)); } } /** * This is callback invoked by VirtualDeviceManagerService when VirtualDisplay was released * by DisplayManager (most probably caused by someone calling VirtualDisplay.close()). * At this point, the display is already released, but we still need to release the * corresponding wakeLock and unregister the RunningAppsChangedListener from corresponding Loading @@ -1572,6 +1599,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub * this callback won't be invoked because the display is removed from * VirtualDeviceManagerService before any resources are released. */ void onVirtualDisplayRemoved(int displayId) { VirtualDisplayWrapper virtualDisplayWrapper; synchronized (mVirtualDeviceLock) { virtualDisplayWrapper = mVirtualDisplays.removeReturnOld(displayId); Loading Loading @@ -1847,6 +1875,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return mWindowPolicyController; } void acquireWakeLock() { if (mWakeLock != null && !mWakeLock.isHeld()) { mWakeLock.acquire(); } } void releaseWakeLock() { if (mWakeLock != null && mWakeLock.isHeld()) { mWakeLock.release(); Loading
services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +12 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,6 @@ import android.companion.virtual.IVirtualDeviceSoundEffectListener; import android.companion.virtual.VirtualDevice; import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.flags.Flags; import android.companion.virtual.sensor.VirtualSensor; import android.companion.virtualnative.IVirtualDeviceManagerNative; import android.compat.annotation.ChangeId; Loading @@ -49,6 +48,7 @@ import android.content.AttributionSource; import android.content.Context; import android.content.Intent; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.IVirtualDisplayCallback; import android.os.Binder; import android.os.Build; import android.os.Handler; Loading @@ -67,6 +67,7 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.widget.Toast; import android.window.DisplayWindowPolicyController; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -750,6 +751,16 @@ public class VirtualDeviceManagerService extends SystemService { return result; } @Override public void onVirtualDisplayCreated(IVirtualDevice virtualDevice, int displayId, IVirtualDisplayCallback callback, DisplayWindowPolicyController dwpc) { VirtualDeviceImpl virtualDeviceImpl = getVirtualDeviceForId( ((VirtualDeviceImpl) virtualDevice).getDeviceId()); if (virtualDeviceImpl != null) { virtualDeviceImpl.onVirtualDisplayCreated(displayId, callback, dwpc); } } @Override public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) { VirtualDeviceImpl virtualDeviceImpl = getVirtualDeviceForId( Loading
services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java +13 −0 Original line number Diff line number Diff line Loading @@ -24,8 +24,10 @@ import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.sensor.VirtualSensor; import android.content.Context; import android.hardware.display.IVirtualDisplayCallback; import android.os.LocaleList; import android.util.ArraySet; import android.window.DisplayWindowPolicyController; import java.util.Set; import java.util.function.Consumer; Loading Loading @@ -103,6 +105,17 @@ public abstract class VirtualDeviceManagerInternal { */ public abstract @NonNull ArraySet<Integer> getDeviceIdsForUid(int uid); /** * Notifies that a virtual display was created. * * @param virtualDevice The virtual device that owns the virtual display. * @param displayId The display id of the created virtual display. * @param callback The callback of the virtual display. * @param dwpc The DisplayWindowPolicyController of the created virtual display. */ public abstract void onVirtualDisplayCreated(IVirtualDevice virtualDevice, int displayId, IVirtualDisplayCallback callback, DisplayWindowPolicyController dwpc); /** * Notifies that a virtual display is removed. * Loading
services/core/java/com/android/server/display/DisplayManagerService.java +12 −0 Original line number Diff line number Diff line Loading @@ -2041,6 +2041,7 @@ public final class DisplayManagerService extends SystemService { packageName, displayUniqueId, virtualDevice, dwpc, surface, flags, virtualDisplayConfig); Loading Loading @@ -2135,6 +2136,7 @@ public final class DisplayManagerService extends SystemService { String packageName, String uniqueId, IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, Surface surface, int flags, VirtualDisplayConfig virtualDisplayConfig) { Loading Loading @@ -2188,6 +2190,16 @@ public final class DisplayManagerService extends SystemService { final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); if (display != null) { // Notify the virtual device that the display has been created. This needs to be called // in this locked section before the repository had the chance to notify any listeners // to ensure that the device is aware of the new display before others know about it. if (virtualDevice != null) { final VirtualDeviceManagerInternal vdm = getLocalService(VirtualDeviceManagerInternal.class); vdm.onVirtualDisplayCreated( virtualDevice, display.getDisplayIdLocked(), callback, dwpc); } return display.getDisplayIdLocked(); } Loading
services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +25 −8 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.hardware.Sensor; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.IDisplayManager; Loading Loading @@ -173,8 +174,7 @@ public class VirtualDeviceManagerServiceTest { private static final int FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES = 0x00000; private static final int VIRTUAL_DEVICE_ID_1 = 42; private static final int VIRTUAL_DEVICE_ID_2 = 43; private static final VirtualDisplayConfig VIRTUAL_DISPLAY_CONFIG = new VirtualDisplayConfig.Builder("virtual_display", 640, 480, 400).build(); private static final VirtualDpadConfig DPAD_CONFIG = new VirtualDpadConfig.Builder() .setVendorId(VENDOR_ID) Loading Loading @@ -284,7 +284,12 @@ public class VirtualDeviceManagerServiceTest { private Intent createRestrictedActivityBlockedIntent(Set<String> displayCategories, String targetDisplayCategory) { when(mDisplayManagerInternalMock.createVirtualDisplay(any(), any(), any(), any(), eq(VIRTUAL_DEVICE_OWNER_PACKAGE))).thenReturn(DISPLAY_ID_1); eq(VIRTUAL_DEVICE_OWNER_PACKAGE))) .thenAnswer(inv -> { mLocalService.onVirtualDisplayCreated( mDeviceImpl, DISPLAY_ID_1, inv.getArgument(1), inv.getArgument(3)); return DISPLAY_ID_1; }); VirtualDisplayConfig config = new VirtualDisplayConfig.Builder("display", 640, 480, 420).setDisplayCategories(displayCategories).build(); mDeviceImpl.createVirtualDisplay(config, mVirtualDisplayCallback); Loading Loading @@ -997,8 +1002,7 @@ public class VirtualDeviceManagerServiceTest { public void onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired() throws RemoteException { addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1, Display.FLAG_TRUSTED); assertThrows(IllegalStateException.class, () -> addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1)); addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1, Display.FLAG_TRUSTED); TestableLooper.get(this).processAllMessages(); verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(), nullable(String.class), nullable(String.class), nullable(WorkSource.class), Loading Loading @@ -1871,8 +1875,6 @@ public class VirtualDeviceManagerServiceTest { } private void addVirtualDisplay(VirtualDeviceImpl virtualDevice, int displayId, int flags) { when(mDisplayManagerInternalMock.createVirtualDisplay(any(), eq(mVirtualDisplayCallback), eq(virtualDevice), any(), any())).thenReturn(displayId); final String uniqueId = UNIQUE_ID + displayId; doAnswer(inv -> { final DisplayInfo displayInfo = new DisplayInfo(); Loading @@ -1880,7 +1882,22 @@ public class VirtualDeviceManagerServiceTest { displayInfo.flags = flags; return displayInfo; }).when(mDisplayManagerInternalMock).getDisplayInfo(eq(displayId)); virtualDevice.createVirtualDisplay(VIRTUAL_DISPLAY_CONFIG, mVirtualDisplayCallback); when(mDisplayManagerInternalMock.createVirtualDisplay(any(), eq(mVirtualDisplayCallback), eq(virtualDevice), any(), any())).thenAnswer(inv -> { mLocalService.onVirtualDisplayCreated( virtualDevice, displayId, mVirtualDisplayCallback, inv.getArgument(3)); return displayId; }); final int virtualDisplayFlags = (flags & Display.FLAG_TRUSTED) == 0 ? 0 : DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; VirtualDisplayConfig virtualDisplayConfig = new VirtualDisplayConfig.Builder("virtual_display", 640, 480, 400) .setFlags(virtualDisplayFlags) .build(); virtualDevice.createVirtualDisplay(virtualDisplayConfig, mVirtualDisplayCallback); mInputManagerMockHelper.addDisplayIdMapping(uniqueId, displayId); } Loading