Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f44e20e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add VDM.createVirtualDisplay"

parents 5d8375c4 24219576
Loading
Loading
Loading
Loading
+106 −0
Original line number Diff line number Diff line
@@ -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.
@@ -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;

@@ -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.
@@ -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();
            }
        }
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -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
@@ -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 {
@@ -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();
    }