Loading core/java/android/companion/virtual/VirtualDeviceManager.java +106 −0 Original line number Diff line number Diff line Loading @@ -16,21 +16,32 @@ package android.companion.virtual; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.companion.AssociationInfo; import android.content.Context; import android.graphics.Point; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.hardware.display.VirtualDisplayConfig; import android.hardware.input.VirtualKeyboard; import android.hardware.input.VirtualMouse; import android.hardware.input.VirtualTouchscreen; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.view.Surface; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * System level service for managing virtual devices. Loading @@ -44,6 +55,31 @@ public final class VirtualDeviceManager { private static final boolean DEBUG = false; private static final String LOG_TAG = "VirtualDeviceManager"; /** @hide */ @IntDef(prefix = "DISPLAY_FLAG_", flag = true, value = {DISPLAY_FLAG_TRUSTED}) @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface DisplayFlags {} /** * Indicates that the display is trusted to show system decorations and receive inputs without * users' touch. * * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED * @hide // TODO(b/194949534): Unhide this API */ public static final int DISPLAY_FLAG_TRUSTED = 1; private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS = DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; private final IVirtualDeviceManager mService; private final Context mContext; Loading Loading @@ -92,6 +128,56 @@ public final class VirtualDeviceManager { mVirtualDevice = virtualDevice; } /** * Creates a virtual display for this virtual device. All displays created on the same * device belongs to the same display group. * * @param width The width of the virtual display in pixels, must be greater than 0. * @param height The height of the virtual display in pixels, must be greater than 0. * @param densityDpi The density of the virtual display in dpi, must be greater than 0. * @param surface The surface to which the content of the virtual display should * be rendered, or null if there is none initially. The surface can also be set later using * {@link VirtualDisplay#setSurface(Surface)}. * @param flags Either 0, or {@link #DISPLAY_FLAG_TRUSTED}. * @param callback Callback to call when the state of the {@link VirtualDisplay} changes * @param handler The handler on which the listener should be invoked, or null * if the listener should be invoked on the calling thread's looper. * @return The newly created virtual display, or {@code null} if the application could * not create the virtual display. * * @see DisplayManager#createVirtualDisplay * @hide */ // TODO(b/194949534): Unhide this API // Suppress "ExecutorRegistration" because DisplayManager.createVirtualDisplay takes a // handler @SuppressLint("ExecutorRegistration") @Nullable public VirtualDisplay createVirtualDisplay( int width, int height, int densityDpi, @Nullable Surface surface, @DisplayFlags int flags, @Nullable Handler handler, @Nullable VirtualDisplay.Callback callback) { // 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, handler); } /** * Closes the virtual device, stopping and tearing down any virtual displays, * audio policies, and event injection that's currently in progress. Loading Loading @@ -186,5 +272,25 @@ public final class VirtualDeviceManager { throw e.rethrowFromSystemServer(); } } private int getVirtualDisplayFlags(@DisplayFlags int flags) { int virtualDisplayFlags = DEFAULT_VIRTUAL_DISPLAY_FLAGS; if ((flags & DISPLAY_FLAG_TRUSTED) != 0) { virtualDisplayFlags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; } return virtualDisplayFlags; } private String getVirtualDisplayName() { try { // Currently this just use the association ID, which means all of the virtual // displays created using the same virtual device will have the same name. The name // should only be used for informational purposes, and not for identifying the // display in code. return "VirtualDevice_" + mVirtualDevice.getAssociationId(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } } services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +3 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @VisibleForTesting final List<Integer> mVirtualDisplayIds = new ArrayList<>(); private final OnDeviceCloseListener mListener; private final IBinder mAppToken; /** * A mapping from the virtual display ID to its corresponding Loading @@ -74,6 +75,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mContext = context; mAssociationInfo = associationInfo; mOwnerUid = ownerUid; mAppToken = token; if (inputController == null) { mInputController = new InputController(mVirtualDeviceLock); } else { Loading @@ -95,6 +97,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @Override // Binder call public void close() { mListener.onClose(mAssociationInfo.getId()); mAppToken.unlinkToDeath(this, 0); mInputController.close(); } Loading Loading
core/java/android/companion/virtual/VirtualDeviceManager.java +106 −0 Original line number Diff line number Diff line Loading @@ -16,21 +16,32 @@ package android.companion.virtual; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.companion.AssociationInfo; import android.content.Context; import android.graphics.Point; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.hardware.display.VirtualDisplayConfig; import android.hardware.input.VirtualKeyboard; import android.hardware.input.VirtualMouse; import android.hardware.input.VirtualTouchscreen; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.view.Surface; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * System level service for managing virtual devices. Loading @@ -44,6 +55,31 @@ public final class VirtualDeviceManager { private static final boolean DEBUG = false; private static final String LOG_TAG = "VirtualDeviceManager"; /** @hide */ @IntDef(prefix = "DISPLAY_FLAG_", flag = true, value = {DISPLAY_FLAG_TRUSTED}) @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface DisplayFlags {} /** * Indicates that the display is trusted to show system decorations and receive inputs without * users' touch. * * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED * @hide // TODO(b/194949534): Unhide this API */ public static final int DISPLAY_FLAG_TRUSTED = 1; private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS = DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; private final IVirtualDeviceManager mService; private final Context mContext; Loading Loading @@ -92,6 +128,56 @@ public final class VirtualDeviceManager { mVirtualDevice = virtualDevice; } /** * Creates a virtual display for this virtual device. All displays created on the same * device belongs to the same display group. * * @param width The width of the virtual display in pixels, must be greater than 0. * @param height The height of the virtual display in pixels, must be greater than 0. * @param densityDpi The density of the virtual display in dpi, must be greater than 0. * @param surface The surface to which the content of the virtual display should * be rendered, or null if there is none initially. The surface can also be set later using * {@link VirtualDisplay#setSurface(Surface)}. * @param flags Either 0, or {@link #DISPLAY_FLAG_TRUSTED}. * @param callback Callback to call when the state of the {@link VirtualDisplay} changes * @param handler The handler on which the listener should be invoked, or null * if the listener should be invoked on the calling thread's looper. * @return The newly created virtual display, or {@code null} if the application could * not create the virtual display. * * @see DisplayManager#createVirtualDisplay * @hide */ // TODO(b/194949534): Unhide this API // Suppress "ExecutorRegistration" because DisplayManager.createVirtualDisplay takes a // handler @SuppressLint("ExecutorRegistration") @Nullable public VirtualDisplay createVirtualDisplay( int width, int height, int densityDpi, @Nullable Surface surface, @DisplayFlags int flags, @Nullable Handler handler, @Nullable VirtualDisplay.Callback callback) { // 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, handler); } /** * Closes the virtual device, stopping and tearing down any virtual displays, * audio policies, and event injection that's currently in progress. Loading Loading @@ -186,5 +272,25 @@ public final class VirtualDeviceManager { throw e.rethrowFromSystemServer(); } } private int getVirtualDisplayFlags(@DisplayFlags int flags) { int virtualDisplayFlags = DEFAULT_VIRTUAL_DISPLAY_FLAGS; if ((flags & DISPLAY_FLAG_TRUSTED) != 0) { virtualDisplayFlags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; } return virtualDisplayFlags; } private String getVirtualDisplayName() { try { // Currently this just use the association ID, which means all of the virtual // displays created using the same virtual device will have the same name. The name // should only be used for informational purposes, and not for identifying the // display in code. return "VirtualDevice_" + mVirtualDevice.getAssociationId(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } }
services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +3 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @VisibleForTesting final List<Integer> mVirtualDisplayIds = new ArrayList<>(); private final OnDeviceCloseListener mListener; private final IBinder mAppToken; /** * A mapping from the virtual display ID to its corresponding Loading @@ -74,6 +75,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mContext = context; mAssociationInfo = associationInfo; mOwnerUid = ownerUid; mAppToken = token; if (inputController == null) { mInputController = new InputController(mVirtualDeviceLock); } else { Loading @@ -95,6 +97,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @Override // Binder call public void close() { mListener.onClose(mAssociationInfo.getId()); mAppToken.unlinkToDeath(this, 0); mInputController.close(); } Loading