From 1ac23bbf925da05a8bbc43ecf37dd67e702c7853 Mon Sep 17 00:00:00 2001 From: Chris Li Date: Mon, 20 Apr 2020 22:39:53 -0700 Subject: [PATCH] Allow Overlay Display to take display flags Before, CTS test used WindowManager#shouldShowSystemDecors() to set show system decorations after overlay display launched, which wouldn't enable system decorations without relaunching. Now, we can set those flag before display launch similar to what VirtualDisplayHelper does. Bug: 153624902 Bug: 154158053 Test: atest CtsWindowManagerDeviceTestCases:MultiDisplayClientTests Test: atest CtsWindowManagerDeviceTestCases:MultiDisplaySystemDecorationTests Change-Id: I83c21a74c722a23ac77141305a08d9f67c5bbcf0 --- core/java/android/provider/Settings.java | 26 ++- .../server/display/OverlayDisplayAdapter.java | 156 +++++++++++++++--- 2 files changed, 154 insertions(+), 28 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 78b0910ad01ac..b280c5d63cd7a 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10737,13 +10737,33 @@ public final class Settings { * The associated value is a specially formatted string that describes the * size and density of simulated secondary display devices. *

- * Format: {width}x{height}/{dpi};... + * Format: + *

+         * [display1];[display2];...
+         * 
+ * with each display specified as: + *
+         * [mode1]|[mode2]|...,[flag1],[flag2],...
+         * 
+ * with each mode specified as: + *
+         * [width]x[height]/[densityDpi]
+         * 
+ * Supported flags: + * *

* Example: *

* diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java index c8e5f6c8f53b2..8fb384070e259 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java @@ -16,12 +16,14 @@ package com.android.server.display; +import android.annotation.Nullable; import android.content.Context; import android.database.ContentObserver; import android.graphics.SurfaceTexture; import android.os.Handler; import android.os.IBinder; import android.provider.Settings; +import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Slog; import android.view.Display; @@ -54,6 +56,10 @@ import java.util.regex.Pattern; * {@link android.provider.Settings.Global#OVERLAY_DISPLAY_DEVICES} setting. This setting should be * formatted as follows: *
+ * [display1];[display2];...
+ * 
+ * with each display specified as: + *
  * [mode1]|[mode2]|...,[flag1],[flag2],...
  * 
* with each mode specified as: @@ -63,22 +69,56 @@ import java.util.regex.Pattern; * Supported flags: * - *

+ *

+ * Example: + *

*/ final class OverlayDisplayAdapter extends DisplayAdapter { static final String TAG = "OverlayDisplayAdapter"; static final boolean DEBUG = false; + /** + * When this flag is set, the overlay display is considered secure. + * @see DisplayDeviceInfo#FLAG_SECURE + */ + private static final String OVERLAY_DISPLAY_FLAG_SECURE = "secure"; + + /** + * When this flag is set, only show this display's own content; do not mirror the content of + * another display. + * @see DisplayDeviceInfo#FLAG_OWN_CONTENT_ONLY + */ + private static final String OVERLAY_DISPLAY_FLAG_OWN_CONTENT_ONLY = "own_content_only"; + + /** + * When this flag is set, the overlay display should support system decorations. + * @see DisplayDeviceInfo#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS + */ + private static final String OVERLAY_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = + "should_show_system_decorations"; + private static final int MIN_WIDTH = 100; private static final int MIN_HEIGHT = 100; private static final int MAX_WIDTH = 4096; private static final int MAX_HEIGHT = 4096; - private static final Pattern DISPLAY_PATTERN = - Pattern.compile("([^,]+)(,[a-z]+)*"); - private static final Pattern MODE_PATTERN = - Pattern.compile("(\\d+)x(\\d+)/(\\d+)"); + private static final String DISPLAY_SPLITTER = ";"; + private static final String MODE_SPLITTER = "\\|"; + private static final String FLAG_SPLITTER = ","; + + private static final Pattern DISPLAY_PATTERN = Pattern.compile("([^,]+)(,[,_a-z]+)*"); + private static final Pattern MODE_PATTERN = Pattern.compile("(\\d+)x(\\d+)/(\\d+)"); // Unique id prefix for overlay displays. private static final String UNIQUE_ID_PREFIX = "overlay:"; @@ -154,7 +194,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { } int count = 0; - for (String part : value.split(";")) { + for (String part : value.split(DISPLAY_SPLITTER)) { Matcher displayMatcher = DISPLAY_PATTERN.matcher(part); if (displayMatcher.matches()) { if (count >= 4) { @@ -164,7 +204,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { String modeString = displayMatcher.group(1); String flagString = displayMatcher.group(2); ArrayList modes = new ArrayList<>(); - for (String mode : modeString.split("\\|")) { + for (String mode : modeString.split(MODE_SPLITTER)) { Matcher modeMatcher = MODE_PATTERN.matcher(mode); if (modeMatcher.matches()) { try { @@ -192,12 +232,13 @@ final class OverlayDisplayAdapter extends DisplayAdapter { com.android.internal.R.string.display_manager_overlay_display_name, number); int gravity = chooseOverlayGravity(number); - boolean secure = flagString != null && flagString.contains(",secure"); + OverlayFlags flags = OverlayFlags.parseFlags(flagString); Slog.i(TAG, "Showing overlay display device #" + number - + ": name=" + name + ", modes=" + Arrays.toString(modes.toArray())); + + ": name=" + name + ", modes=" + Arrays.toString(modes.toArray()) + + ", flags=" + flags); - mOverlays.add(new OverlayDisplayHandle(name, modes, gravity, secure, number)); + mOverlays.add(new OverlayDisplayHandle(name, modes, gravity, flags, number)); continue; } } @@ -223,7 +264,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { private final String mName; private final float mRefreshRate; private final long mDisplayPresentationDeadlineNanos; - private final boolean mSecure; + private final OverlayFlags mFlags; private final List mRawModes; private final Display.Mode[] mModes; private final int mDefaultMode; @@ -234,16 +275,15 @@ final class OverlayDisplayAdapter extends DisplayAdapter { private DisplayDeviceInfo mInfo; private int mActiveMode; - public OverlayDisplayDevice(IBinder displayToken, String name, + OverlayDisplayDevice(IBinder displayToken, String name, List modes, int activeMode, int defaultMode, float refreshRate, long presentationDeadlineNanos, - boolean secure, int state, - SurfaceTexture surfaceTexture, int number) { + OverlayFlags flags, int state, SurfaceTexture surfaceTexture, int number) { super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number); mName = name; mRefreshRate = refreshRate; mDisplayPresentationDeadlineNanos = presentationDeadlineNanos; - mSecure = secure; + mFlags = flags; mState = state; mSurfaceTexture = surfaceTexture; mRawModes = modes; @@ -304,9 +344,15 @@ final class OverlayDisplayAdapter extends DisplayAdapter { mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos + 1000000000L / (int) mRefreshRate; // display's deadline + 1 frame mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION; - if (mSecure) { + if (mFlags.mSecure) { mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; } + if (mFlags.mOwnContentOnly) { + mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; + } + if (mFlags.mShouldShowSystemDecorations) { + mInfo.flags |= DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; + } mInfo.type = Display.TYPE_OVERLAY; mInfo.touch = DisplayDeviceInfo.TOUCH_VIRTUAL; mInfo.state = mState; @@ -363,19 +409,23 @@ final class OverlayDisplayAdapter extends DisplayAdapter { private final String mName; private final List mModes; private final int mGravity; - private final boolean mSecure; + private final OverlayFlags mFlags; private final int mNumber; private OverlayDisplayWindow mWindow; private OverlayDisplayDevice mDevice; private int mActiveMode; - public OverlayDisplayHandle(String name, List modes, int gravity, - boolean secure, int number) { + OverlayDisplayHandle( + String name, + List modes, + int gravity, + OverlayFlags flags, + int number) { mName = name; mModes = modes; mGravity = gravity; - mSecure = secure; + mFlags = flags; mNumber = number; mActiveMode = 0; @@ -405,10 +455,10 @@ final class OverlayDisplayAdapter extends DisplayAdapter { public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate, long presentationDeadlineNanos, int state) { synchronized (getSyncRoot()) { - IBinder displayToken = SurfaceControl.createDisplay(mName, mSecure); + IBinder displayToken = SurfaceControl.createDisplay(mName, mFlags.mSecure); mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode, DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos, - mSecure, state, surfaceTexture, mNumber) { + mFlags, state, surfaceTexture, mNumber) { @Override public void onModeChangedLocked(int index) { onActiveModeChangedLocked(index); @@ -446,7 +496,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { pw.println(" mModes=" + Arrays.toString(mModes.toArray())); pw.println(" mActiveMode=" + mActiveMode); pw.println(" mGravity=" + mGravity); - pw.println(" mSecure=" + mSecure); + pw.println(" mFlags=" + mFlags); pw.println(" mNumber=" + mNumber); // Try to dump the window state. @@ -463,8 +513,8 @@ final class OverlayDisplayAdapter extends DisplayAdapter { public void run() { OverlayMode mode = mModes.get(mActiveMode); OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(), - mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity, mSecure, - OverlayDisplayHandle.this); + mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity, + mFlags.mSecure, OverlayDisplayHandle.this); window.show(); synchronized (getSyncRoot()) { @@ -531,4 +581,60 @@ final class OverlayDisplayAdapter extends DisplayAdapter { .toString(); } } + + /** Represents the flags of the overlay display. */ + private static final class OverlayFlags { + /** See {@link #OVERLAY_DISPLAY_FLAG_SECURE}. */ + final boolean mSecure; + + /** See {@link #OVERLAY_DISPLAY_FLAG_OWN_CONTENT_ONLY}. */ + final boolean mOwnContentOnly; + + /** See {@link #OVERLAY_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS}. */ + final boolean mShouldShowSystemDecorations; + + OverlayFlags( + boolean secure, + boolean ownContentOnly, + boolean shouldShowSystemDecorations) { + mSecure = secure; + mOwnContentOnly = ownContentOnly; + mShouldShowSystemDecorations = shouldShowSystemDecorations; + } + + static OverlayFlags parseFlags(@Nullable String flagString) { + if (TextUtils.isEmpty(flagString)) { + return new OverlayFlags( + false /* secure */, + false /* ownContentOnly */, + false /* shouldShowSystemDecorations */); + } + + boolean secure = false; + boolean ownContentOnly = false; + boolean shouldShowSystemDecorations = false; + for (String flag: flagString.split(FLAG_SPLITTER)) { + if (OVERLAY_DISPLAY_FLAG_SECURE.equals(flag)) { + secure = true; + } + if (OVERLAY_DISPLAY_FLAG_OWN_CONTENT_ONLY.equals(flag)) { + ownContentOnly = true; + } + if (OVERLAY_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS.equals(flag)) { + shouldShowSystemDecorations = true; + } + } + return new OverlayFlags(secure, ownContentOnly, shouldShowSystemDecorations); + } + + @Override + public String toString() { + return new StringBuilder("{") + .append("secure=").append(mSecure) + .append(", ownContentOnly=").append(mOwnContentOnly) + .append(", shouldShowSystemDecorations=").append(mShouldShowSystemDecorations) + .append("}") + .toString(); + } + } }