Merge "Allow Overlay Display to take display flags" into rvc-dev

This commit is contained in:
Chris Li
2020-04-30 07:12:12 +00:00
committed by Android (Google) Code Review
2 changed files with 154 additions and 28 deletions

View File

@@ -10737,13 +10737,33 @@ public final class Settings {
* The associated value is a specially formatted string that describes the * The associated value is a specially formatted string that describes the
* size and density of simulated secondary display devices. * size and density of simulated secondary display devices.
* <p> * <p>
* Format: {width}x{height}/{dpi};... * Format:
* <pre>
* [display1];[display2];...
* </pre>
* with each display specified as:
* <pre>
* [mode1]|[mode2]|...,[flag1],[flag2],...
* </pre>
* with each mode specified as:
* <pre>
* [width]x[height]/[densityDpi]
* </pre>
* Supported flags:
* <ul>
* <li><pre>secure</pre>: creates a secure display</li>
* <li><pre>own_content_only</pre>: only shows this display's own content</li>
* <li><pre>should_show_system_decorations</pre>: supports system decorations</li>
* </ul>
* </p><p> * </p><p>
* Example: * Example:
* <ul> * <ul>
* <li><code>1280x720/213</code>: make one overlay that is 1280x720 at 213dpi.</li> * <li><code>1280x720/213</code>: make one overlay that is 1280x720 at 213dpi.</li>
* <li><code>1920x1080/320;1280x720/213</code>: make two overlays, the first * <li><code>1920x1080/320,secure;1280x720/213</code>: make two overlays, the first at
* at 1080p and the second at 720p.</li> * 1080p and secure; the second at 720p.</li>
* <li><code>1920x1080/320|3840x2160/640</code>: make one overlay that is 1920x1080 at
* 213dpi by default, but can also be upscaled to 3840x2160 at 640dpi by the system if the
* display device allows.</li>
* <li>If the value is empty, then no overlay display devices are created.</li> * <li>If the value is empty, then no overlay display devices are created.</li>
* </ul></p> * </ul></p>
* *

View File

@@ -16,12 +16,14 @@
package com.android.server.display; package com.android.server.display;
import android.annotation.Nullable;
import android.content.Context; import android.content.Context;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Slog; import android.util.Slog;
import android.view.Display; 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 * {@link android.provider.Settings.Global#OVERLAY_DISPLAY_DEVICES} setting. This setting should be
* formatted as follows: * formatted as follows:
* <pre> * <pre>
* [display1];[display2];...
* </pre>
* with each display specified as:
* <pre>
* [mode1]|[mode2]|...,[flag1],[flag2],... * [mode1]|[mode2]|...,[flag1],[flag2],...
* </pre> * </pre>
* with each mode specified as: * with each mode specified as:
@@ -63,22 +69,56 @@ import java.util.regex.Pattern;
* Supported flags: * Supported flags:
* <ul> * <ul>
* <li><pre>secure</pre>: creates a secure display</li> * <li><pre>secure</pre>: creates a secure display</li>
* <li><pre>own_content_only</pre>: only shows this display's own content</li>
* <li><pre>should_show_system_decorations</pre>: supports system decorations</li>
* </ul> * </ul>
* </p> * </p><p>
* Example:
* <ul>
* <li><code>1280x720/213</code>: make one overlay that is 1280x720 at 213dpi.</li>
* <li><code>1920x1080/320,secure;1280x720/213</code>: make two overlays, the first at 1080p and
* secure; the second at 720p.</li>
* <li><code>1920x1080/320|3840x2160/640</code>: make one overlay that is 1920x1080 at
* 213dpi by default, but can also be upscaled to 3840x2160 at 640dpi by the system if the
* display device allows.</li>
* <li>If the value is empty, then no overlay display devices are created.</li>
* </ul></p>
*/ */
final class OverlayDisplayAdapter extends DisplayAdapter { final class OverlayDisplayAdapter extends DisplayAdapter {
static final String TAG = "OverlayDisplayAdapter"; static final String TAG = "OverlayDisplayAdapter";
static final boolean DEBUG = false; 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_WIDTH = 100;
private static final int MIN_HEIGHT = 100; private static final int MIN_HEIGHT = 100;
private static final int MAX_WIDTH = 4096; private static final int MAX_WIDTH = 4096;
private static final int MAX_HEIGHT = 4096; private static final int MAX_HEIGHT = 4096;
private static final Pattern DISPLAY_PATTERN = private static final String DISPLAY_SPLITTER = ";";
Pattern.compile("([^,]+)(,[a-z]+)*"); private static final String MODE_SPLITTER = "\\|";
private static final Pattern MODE_PATTERN = private static final String FLAG_SPLITTER = ",";
Pattern.compile("(\\d+)x(\\d+)/(\\d+)");
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. // Unique id prefix for overlay displays.
private static final String UNIQUE_ID_PREFIX = "overlay:"; private static final String UNIQUE_ID_PREFIX = "overlay:";
@@ -154,7 +194,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
} }
int count = 0; int count = 0;
for (String part : value.split(";")) { for (String part : value.split(DISPLAY_SPLITTER)) {
Matcher displayMatcher = DISPLAY_PATTERN.matcher(part); Matcher displayMatcher = DISPLAY_PATTERN.matcher(part);
if (displayMatcher.matches()) { if (displayMatcher.matches()) {
if (count >= 4) { if (count >= 4) {
@@ -164,7 +204,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
String modeString = displayMatcher.group(1); String modeString = displayMatcher.group(1);
String flagString = displayMatcher.group(2); String flagString = displayMatcher.group(2);
ArrayList<OverlayMode> modes = new ArrayList<>(); ArrayList<OverlayMode> modes = new ArrayList<>();
for (String mode : modeString.split("\\|")) { for (String mode : modeString.split(MODE_SPLITTER)) {
Matcher modeMatcher = MODE_PATTERN.matcher(mode); Matcher modeMatcher = MODE_PATTERN.matcher(mode);
if (modeMatcher.matches()) { if (modeMatcher.matches()) {
try { try {
@@ -192,12 +232,13 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
com.android.internal.R.string.display_manager_overlay_display_name, com.android.internal.R.string.display_manager_overlay_display_name,
number); number);
int gravity = chooseOverlayGravity(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 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; continue;
} }
} }
@@ -223,7 +264,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
private final String mName; private final String mName;
private final float mRefreshRate; private final float mRefreshRate;
private final long mDisplayPresentationDeadlineNanos; private final long mDisplayPresentationDeadlineNanos;
private final boolean mSecure; private final OverlayFlags mFlags;
private final List<OverlayMode> mRawModes; private final List<OverlayMode> mRawModes;
private final Display.Mode[] mModes; private final Display.Mode[] mModes;
private final int mDefaultMode; private final int mDefaultMode;
@@ -234,16 +275,15 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
private DisplayDeviceInfo mInfo; private DisplayDeviceInfo mInfo;
private int mActiveMode; private int mActiveMode;
public OverlayDisplayDevice(IBinder displayToken, String name, OverlayDisplayDevice(IBinder displayToken, String name,
List<OverlayMode> modes, int activeMode, int defaultMode, List<OverlayMode> modes, int activeMode, int defaultMode,
float refreshRate, long presentationDeadlineNanos, float refreshRate, long presentationDeadlineNanos,
boolean secure, int state, OverlayFlags flags, int state, SurfaceTexture surfaceTexture, int number) {
SurfaceTexture surfaceTexture, int number) {
super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number); super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number);
mName = name; mName = name;
mRefreshRate = refreshRate; mRefreshRate = refreshRate;
mDisplayPresentationDeadlineNanos = presentationDeadlineNanos; mDisplayPresentationDeadlineNanos = presentationDeadlineNanos;
mSecure = secure; mFlags = flags;
mState = state; mState = state;
mSurfaceTexture = surfaceTexture; mSurfaceTexture = surfaceTexture;
mRawModes = modes; mRawModes = modes;
@@ -304,9 +344,15 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos + mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos +
1000000000L / (int) mRefreshRate; // display's deadline + 1 frame 1000000000L / (int) mRefreshRate; // display's deadline + 1 frame
mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION; mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION;
if (mSecure) { if (mFlags.mSecure) {
mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; 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.type = Display.TYPE_OVERLAY;
mInfo.touch = DisplayDeviceInfo.TOUCH_VIRTUAL; mInfo.touch = DisplayDeviceInfo.TOUCH_VIRTUAL;
mInfo.state = mState; mInfo.state = mState;
@@ -363,19 +409,23 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
private final String mName; private final String mName;
private final List<OverlayMode> mModes; private final List<OverlayMode> mModes;
private final int mGravity; private final int mGravity;
private final boolean mSecure; private final OverlayFlags mFlags;
private final int mNumber; private final int mNumber;
private OverlayDisplayWindow mWindow; private OverlayDisplayWindow mWindow;
private OverlayDisplayDevice mDevice; private OverlayDisplayDevice mDevice;
private int mActiveMode; private int mActiveMode;
public OverlayDisplayHandle(String name, List<OverlayMode> modes, int gravity, OverlayDisplayHandle(
boolean secure, int number) { String name,
List<OverlayMode> modes,
int gravity,
OverlayFlags flags,
int number) {
mName = name; mName = name;
mModes = modes; mModes = modes;
mGravity = gravity; mGravity = gravity;
mSecure = secure; mFlags = flags;
mNumber = number; mNumber = number;
mActiveMode = 0; mActiveMode = 0;
@@ -405,10 +455,10 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate, public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate,
long presentationDeadlineNanos, int state) { long presentationDeadlineNanos, int state) {
synchronized (getSyncRoot()) { synchronized (getSyncRoot()) {
IBinder displayToken = SurfaceControl.createDisplay(mName, mSecure); IBinder displayToken = SurfaceControl.createDisplay(mName, mFlags.mSecure);
mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode, mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode,
DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos, DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos,
mSecure, state, surfaceTexture, mNumber) { mFlags, state, surfaceTexture, mNumber) {
@Override @Override
public void onModeChangedLocked(int index) { public void onModeChangedLocked(int index) {
onActiveModeChangedLocked(index); onActiveModeChangedLocked(index);
@@ -446,7 +496,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
pw.println(" mModes=" + Arrays.toString(mModes.toArray())); pw.println(" mModes=" + Arrays.toString(mModes.toArray()));
pw.println(" mActiveMode=" + mActiveMode); pw.println(" mActiveMode=" + mActiveMode);
pw.println(" mGravity=" + mGravity); pw.println(" mGravity=" + mGravity);
pw.println(" mSecure=" + mSecure); pw.println(" mFlags=" + mFlags);
pw.println(" mNumber=" + mNumber); pw.println(" mNumber=" + mNumber);
// Try to dump the window state. // Try to dump the window state.
@@ -463,8 +513,8 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
public void run() { public void run() {
OverlayMode mode = mModes.get(mActiveMode); OverlayMode mode = mModes.get(mActiveMode);
OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(), OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(),
mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity, mSecure, mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity,
OverlayDisplayHandle.this); mFlags.mSecure, OverlayDisplayHandle.this);
window.show(); window.show();
synchronized (getSyncRoot()) { synchronized (getSyncRoot()) {
@@ -531,4 +581,60 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
.toString(); .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();
}
}
} }