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

Commit 7d00affc authored by Jeff Brown's avatar Jeff Brown
Browse files

Support public virtual displays.

Refactor the new private virtual display API to also support
creating public virtual displays with various characteristics.
This feature requires special permissions and is only intended
for use by the system.

Change-Id: I44dd19f37cf76ea6d6e313afe42f4a412bd96663
parent 040f44d0
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -40,6 +40,9 @@ package android {
    field public static final java.lang.String CALL_PHONE = "android.permission.CALL_PHONE";
    field public static final java.lang.String CALL_PRIVILEGED = "android.permission.CALL_PRIVILEGED";
    field public static final java.lang.String CAMERA = "android.permission.CAMERA";
    field public static final java.lang.String CAPTURE_AUDIO_OUTPUT = "android.permission.CAPTURE_AUDIO_OUTPUT";
    field public static final java.lang.String CAPTURE_SECURE_VIDEO_OUTPUT = "android.permission.CAPTURE_SECURE_VIDEO_OUTPUT";
    field public static final java.lang.String CAPTURE_VIDEO_OUTPUT = "android.permission.CAPTURE_VIDEO_OUTPUT";
    field public static final java.lang.String CHANGE_COMPONENT_ENABLED_STATE = "android.permission.CHANGE_COMPONENT_ENABLED_STATE";
    field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION";
    field public static final java.lang.String CHANGE_NETWORK_STATE = "android.permission.CHANGE_NETWORK_STATE";
@@ -10798,13 +10801,16 @@ package android.hardware.camera2 {
package android.hardware.display {
  public final class DisplayManager {
    method public android.hardware.display.VirtualDisplay createPrivateVirtualDisplay(java.lang.String, int, int, int, android.view.Surface);
    method public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, android.view.Surface, int);
    method public android.view.Display getDisplay(int);
    method public android.view.Display[] getDisplays();
    method public android.view.Display[] getDisplays(java.lang.String);
    method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler);
    method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
    field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
    field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
    field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
    field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4
  }
  public static abstract interface DisplayManager.DisplayListener {
@@ -25610,6 +25616,7 @@ package android.view {
    method public deprecated int getWidth();
    method public boolean isValid();
    field public static final int DEFAULT_DISPLAY = 0; // 0x0
    field public static final int FLAG_PRESENTATION = 8; // 0x8
    field public static final int FLAG_PRIVATE = 4; // 0x4
    field public static final int FLAG_SECURE = 2; // 0x2
    field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
+130 −24
Original line number Diff line number Diff line
@@ -69,16 +69,110 @@ public final class DisplayManager {
     * Display category: Presentation displays.
     * <p>
     * This category can be used to identify secondary displays that are suitable for
     * use as presentation displays.
     * use as presentation displays such as HDMI or Wireless displays.  Applications
     * may automatically project their content to presentation displays to provide
     * richer second screen experiences.
     * </p>
     *
     * @see android.app.Presentation for information about presenting content
     * on secondary displays.
     * @see Display#FLAG_PRESENTATION
     * @see #getDisplays(String)
     */
    public static final String DISPLAY_CATEGORY_PRESENTATION =
            "android.hardware.display.category.PRESENTATION";

    /**
     * Virtual display flag: Create a public display.
     *
     * <h3>Public virtual displays</h3>
     * <p>
     * When this flag is set, the virtual display is public.
     * </p><p>
     * A public virtual display behaves just like most any other display that is connected
     * to the system such as an HDMI or Wireless display.  Applications can open
     * windows on the display and the system may mirror the contents of other displays
     * onto it.
     * </p><p>
     * Creating a public virtual display requires the
     * {@link android.Manifest.permission#CAPTURE_VIDEO_OUTPUT}
     * or {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT} permission.
     * These permissions are reserved for use by system components and are not available to
     * third-party applications.
     * </p>
     *
     * <h3>Private virtual displays</h3>
     * <p>
     * When this flag is not set, the virtual display is private as defined by the
     * {@link Display#FLAG_PRIVATE} display flag.
     * </p>
     * A private virtual display belongs to the application that created it.
     * Only the a owner of a private virtual display is allowed to place windows upon it.
     * The private virtual display also does not participate in display mirroring: it will
     * neither receive mirrored content from another display nor allow its own content to
     * be mirrored elsewhere.  More precisely, the only processes that are allowed to
     * enumerate or interact with the private display are those that have the same UID as the
     * application that originally created the private virtual display.
      * </p>
     *
     * @see #createVirtualDisplay
     */
    public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1 << 0;

    /**
     * Virtual display flag: Create a presentation display.
     *
     * <h3>Presentation virtual displays</h3>
     * <p>
     * When this flag is set, the virtual display is registered as a presentation
     * display in the {@link #DISPLAY_CATEGORY_PRESENTATION presentation display category}.
     * Applications may automatically project their content to presentation displays
     * to provide richer second screen experiences.
     * </p>
     *
     * <h3>Non-presentation virtual displays</h3>
     * <p>
     * When this flag is not set, the virtual display is not registered as a presentation
     * display.  Applications can still project their content on the display but they
     * will typically not do so automatically.  This option is appropriate for
     * more special-purpose displays.
     * </p>
     *
     * @see android.app.Presentation for information about presenting content
     * on secondary displays.
     * @see #createVirtualDisplay
     * @see #DISPLAY_CATEGORY_PRESENTATION
     * @see Display#FLAG_PRESENTATION
     */
    public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 1 << 1;

    /**
     * Virtual display flag: Create a secure display.
     *
     * <h3>Secure virtual displays</h3>
     * <p>
     * When this flag is set, the virtual display is considered secure as defined
     * by the {@link Display#FLAG_SECURE} display flag.  The caller promises to take
     * reasonable measures, such as over-the-air encryption, to prevent the contents
     * of the display from being intercepted or recorded on a persistent medium.
     * </p><p>
     * Creating a secure virtual display requires the
     * {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT} permission.
     * This permission is reserved for use by system components and is not available to
     * third-party applications.
     * </p>
     *
     * <h3>Non-secure virtual displays</h3>
     * <p>
     * When this flag is not set, the virtual display is considered unsecure.
     * The content of secure windows will be blanked if shown on this display.
     * </p>
     *
     * @see Display#FLAG_SECURE for information about secure displays.
     * @see #createVirtualDisplay
     */
    public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 1 << 2;

    /** @hide */
    public DisplayManager(Context context) {
        mContext = context;
@@ -130,12 +224,12 @@ public final class DisplayManager {
        synchronized (mLock) {
            try {
                if (category == null) {
                    addMatchingDisplaysLocked(mTempDisplays, displayIds, -1);
                    addAllDisplaysLocked(mTempDisplays, displayIds);
                } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI);
                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
                    addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL);
                    addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
                    addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI);
                    addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
                    addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL);
                }
                return mTempDisplays.toArray(new Display[mTempDisplays.size()]);
            } finally {
@@ -144,12 +238,22 @@ public final class DisplayManager {
        }
    }

    private void addMatchingDisplaysLocked(
    private void addAllDisplaysLocked(ArrayList<Display> displays, int[] displayIds) {
        for (int i = 0; i < displayIds.length; i++) {
            Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/);
            if (display != null) {
                displays.add(display);
            }
        }
    }

    private void addPresentationDisplaysLocked(
            ArrayList<Display> displays, int[] displayIds, int matchType) {
        for (int i = 0; i < displayIds.length; i++) {
            Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/);
            if (display != null
                    && (matchType < 0 || display.getType() == matchType)) {
                    && (display.getFlags() & Display.FLAG_PRESENTATION) != 0
                    && display.getType() == matchType) {
                displays.add(display);
            }
        }
@@ -277,23 +381,19 @@ public final class DisplayManager {
    }

    /**
     * Creates a private virtual display.
     * Creates a virtual display.
     * <p>
     * The content of a virtual display is rendered to a {@link Surface} provided
     * by the application that created the virtual display.
     * by the application.
     * </p><p>
     * Only the application that created a private virtual display is allowed to
     * place windows upon it.  The private virtual display also does not participate
     * in display mirroring: it will neither receive mirrored content from another
     * display nor allow its own content to be mirrored elsewhere.  More precisely,
     * the only processes that are allowed to enumerate or interact with a private
     * display are those that have the same UID as the application that originally
     * created the private virtual display.
     * </p><p>
     * The private virtual display should be {@link VirtualDisplay#release released}
     * when no longer needed.  Because a private virtual display renders to a surface
     * The virtual display should be {@link VirtualDisplay#release released}
     * when no longer needed.  Because a virtual display renders to a surface
     * provided by the application, it will be released automatically when the
     * process terminates and all remaining windows on it will be forcibly removed.
     * </p><p>
     * The behavior of the virtual display depends on the flags that are provided
     * to this method.  By default, virtual displays are created to be private,
     * non-presentation and unsecure.  Permissions may be required to use certain flags.
     * </p>
     *
     * @param name The name of the virtual display, must be non-empty.
@@ -302,13 +402,19 @@ public final class DisplayManager {
     * @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, must be non-null.
     * @param flags A combination of virtual display flags:
     * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION}
     * or {@link #VIRTUAL_DISPLAY_FLAG_SECURE}.
     * @return The newly created virtual display, or null if the application could
     * not create the virtual display.
     *
     * @throws SecurityException if the caller does not have permission to create
     * a virtual display with the specified flags.
     */
    public VirtualDisplay createPrivateVirtualDisplay(String name,
            int width, int height, int densityDpi, Surface surface) {
        return mGlobal.createPrivateVirtualDisplay(mContext,
                name, width, height, densityDpi, surface);
    public VirtualDisplay createVirtualDisplay(String name,
            int width, int height, int densityDpi, Surface surface, int flags) {
        return mGlobal.createVirtualDisplay(mContext,
                name, width, height, densityDpi, surface, flags);
    }

    /**
+7 −7
Original line number Diff line number Diff line
@@ -329,8 +329,8 @@ public final class DisplayManagerGlobal {
        }
    }

    public VirtualDisplay createPrivateVirtualDisplay(Context context, String name,
            int width, int height, int densityDpi, Surface surface) {
    public VirtualDisplay createVirtualDisplay(Context context, String name,
            int width, int height, int densityDpi, Surface surface, int flags) {
        if (TextUtils.isEmpty(name)) {
            throw new IllegalArgumentException("name must be non-null and non-empty");
        }
@@ -345,20 +345,20 @@ public final class DisplayManagerGlobal {
        Binder token = new Binder();
        int displayId;
        try {
            displayId = mDm.createPrivateVirtualDisplay(token, context.getPackageName(),
                    name, width, height, densityDpi, surface);
            displayId = mDm.createVirtualDisplay(token, context.getPackageName(),
                    name, width, height, densityDpi, surface, flags);
        } catch (RemoteException ex) {
            Log.e(TAG, "Could not create private virtual display: " + name, ex);
            Log.e(TAG, "Could not create virtual display: " + name, ex);
            return null;
        }
        if (displayId < 0) {
            Log.e(TAG, "Could not create private virtual display: " + name);
            Log.e(TAG, "Could not create virtual display: " + name);
            return null;
        }
        Display display = getRealDisplay(displayId);
        if (display == null) {
            Log.wtf(TAG, "Could not obtain display info for newly created "
                    + "private virtual display: " + name);
                    + "virtual display: " + name);
            try {
                mDm.releaseVirtualDisplay(token);
            } catch (RemoteException ex) {
+4 −3
Original line number Diff line number Diff line
@@ -48,9 +48,10 @@ interface IDisplayManager {
    // No permissions required.
    WifiDisplayStatus getWifiDisplayStatus();

    // No permissions required.
    int createPrivateVirtualDisplay(IBinder token, String packageName,
            String name, int width, int height, int densityDpi, in Surface surface);
    // Requires CAPTURE_VIDEO_OUTPUT or CAPTURE_SECURE_VIDEO_OUTPUT for certain
    // combinations of flags.
    int createVirtualDisplay(IBinder token, String packageName,
            String name, int width, int height, int densityDpi, in Surface surface, int flags);

    // No permissions required but must be same Uid as the creator.
    void releaseVirtualDisplay(in IBinder token);
+1 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ import android.view.Display;
/**
 * Represents a virtual display.
 *
 * @see DisplayManager#createPrivateVirtualDisplay
 * @see DisplayManager#createVirtualDisplay
 */
public final class VirtualDisplay {
    private final DisplayManagerGlobal mGlobal;
Loading