summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/display/DisplayManager.java30
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java26
-rw-r--r--core/java/android/hardware/display/IDisplayManager.aidl7
-rw-r--r--core/java/android/hardware/display/VirtualDisplayConfig.aidl19
-rw-r--r--core/java/android/hardware/display/VirtualDisplayConfig.java491
-rw-r--r--media/java/android/media/projection/MediaProjection.java50
-rw-r--r--services/core/java/com/android/server/display/DisplayDevice.java8
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java54
-rw-r--r--services/core/java/com/android/server/display/VirtualDisplayAdapter.java48
-rw-r--r--services/core/java/com/android/server/vr/Vr2dDisplay.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java107
11 files changed, 777 insertions, 72 deletions
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 65f45d895027..ea5cc7f2e8bc 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -634,17 +634,39 @@ public final class DisplayManager {
public VirtualDisplay createVirtualDisplay(@NonNull String name,
int width, int height, int densityDpi, @Nullable Surface surface, int flags,
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
- return createVirtualDisplay(null /* projection */, name, width, height, densityDpi, surface,
- flags, callback, handler, null /* uniqueId */);
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+ height, densityDpi);
+ builder.setFlags(flags);
+ if (surface != null) {
+ builder.setSurface(surface);
+ }
+ return createVirtualDisplay(null /* projection */, builder.build(), callback, handler);
}
+ // TODO : Remove this hidden API after remove all callers. (Refer to MultiDisplayService)
/** @hide */
public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection,
@NonNull String name, int width, int height, int densityDpi, @Nullable Surface surface,
int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler,
@Nullable String uniqueId) {
- return mGlobal.createVirtualDisplay(mContext, projection,
- name, width, height, densityDpi, surface, flags, callback, handler, uniqueId);
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+ height, densityDpi);
+ builder.setFlags(flags);
+ if (uniqueId != null) {
+ builder.setUniqueId(uniqueId);
+ }
+ if (surface != null) {
+ builder.setSurface(surface);
+ }
+ return createVirtualDisplay(projection, builder.build(), callback, handler);
+ }
+
+ /** @hide */
+ public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection,
+ @NonNull VirtualDisplayConfig virtualDisplayConfig,
+ @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
+ return mGlobal.createVirtualDisplay(mContext, projection, virtualDisplayConfig, callback,
+ handler);
}
/**
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 526db85b47d4..4d645e6052a7 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -451,35 +451,26 @@ public final class DisplayManagerGlobal {
}
}
- public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
- String name, int width, int height, int densityDpi, Surface surface, int flags,
- VirtualDisplay.Callback callback, Handler handler, String uniqueId) {
- if (TextUtils.isEmpty(name)) {
- throw new IllegalArgumentException("name must be non-null and non-empty");
- }
- if (width <= 0 || height <= 0 || densityDpi <= 0) {
- throw new IllegalArgumentException("width, height, and densityDpi must be "
- + "greater than 0");
- }
-
+ public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection,
+ @NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback,
+ Handler handler) {
VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
int displayId;
try {
- displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
- context.getPackageName(), name, width, height, densityDpi, surface, flags,
- uniqueId);
+ displayId = mDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper,
+ projectionToken, context.getPackageName());
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
if (displayId < 0) {
- Log.e(TAG, "Could not create virtual display: " + name);
+ Log.e(TAG, "Could not create virtual display: " + virtualDisplayConfig.getName());
return null;
}
Display display = getRealDisplay(displayId);
if (display == null) {
Log.wtf(TAG, "Could not obtain display info for newly created "
- + "virtual display: " + name);
+ + "virtual display: " + virtualDisplayConfig.getName());
try {
mDm.releaseVirtualDisplay(callbackWrapper);
} catch (RemoteException ex) {
@@ -487,7 +478,8 @@ public final class DisplayManagerGlobal {
}
return null;
}
- return new VirtualDisplay(this, display, callbackWrapper, surface);
+ return new VirtualDisplay(this, display, callbackWrapper,
+ virtualDisplayConfig.getSurface());
}
public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index d22188ec5d7f..c697106d0c17 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -22,6 +22,7 @@ import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.Curve;
import android.hardware.display.IDisplayManagerCallback;
import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
import android.media.projection.IMediaProjection;
@@ -71,9 +72,9 @@ interface IDisplayManager {
// Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
// MediaProjection token for certain combinations of flags.
- int createVirtualDisplay(in IVirtualDisplayCallback callback,
- in IMediaProjection projectionToken, String packageName, String name,
- int width, int height, int densityDpi, in Surface surface, int flags, String uniqueId);
+ int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig,
+ in IVirtualDisplayCallback callback, in IMediaProjection projectionToken,
+ String packageName);
// No permissions required, but must be same Uid as the creator.
void resizeVirtualDisplay(in IVirtualDisplayCallback token,
diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.aidl b/core/java/android/hardware/display/VirtualDisplayConfig.aidl
new file mode 100644
index 000000000000..c28f1dfb9806
--- /dev/null
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.display;
+
+parcelable VirtualDisplayConfig;
diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.java b/core/java/android/hardware/display/VirtualDisplayConfig.java
new file mode 100644
index 000000000000..10e1c7c2e0df
--- /dev/null
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.java
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.display;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.projection.MediaProjection;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.Surface;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Holds configuration used to create {@link VirtualDisplay} instances. See
+ * {@link MediaProjection#createVirtualDisplay(VirtualDisplayConfig, VirtualDisplay.Callback, Handler)}.
+ *
+ * @hide
+ */
+@DataClass(genParcelable = true, genAidl = true, genBuilder = true)
+public final class VirtualDisplayConfig implements Parcelable {
+ /**
+ * The name of the virtual display, must be non-empty.
+ */
+ @NonNull
+ private String mName;
+
+ /**
+ * The width of the virtual display in pixels. Must be greater than 0.
+ */
+ @IntRange(from = 1)
+ private int mWidth;
+
+ /**
+ * The height of the virtual display in pixels. Must be greater than 0.
+ */
+ @IntRange(from = 1)
+ private int mHeight;
+
+ /**
+ * The density of the virtual display in dpi. Must be greater than 0.
+ */
+ @IntRange(from = 1)
+ private int mDensityDpi;
+
+ /**
+ * A combination of virtual display flags.
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
+ * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+ */
+ private int mFlags = 0;
+
+ /**
+ * The surface to which the content of the virtual display should be rendered, or null if
+ * there is none initially.
+ */
+ @Nullable
+ private Surface mSurface = null;
+
+ /**
+ * The unique identifier for the display. Shouldn't be displayed to the user.
+ * @hide
+ */
+ @Nullable
+ private String mUniqueId = null;
+
+ /**
+ * The id of the display that the virtual display should mirror, or
+ * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+ */
+ private int mDisplayIdToMirror = DEFAULT_DISPLAY;
+
+
+
+ // Code below generated by codegen v1.0.15.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ VirtualDisplayConfig(
+ @NonNull String name,
+ @IntRange(from = 1) int width,
+ @IntRange(from = 1) int height,
+ @IntRange(from = 1) int densityDpi,
+ int flags,
+ @Nullable Surface surface,
+ @Nullable String uniqueId,
+ int displayIdToMirror) {
+ this.mName = name;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mName);
+ this.mWidth = width;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mWidth,
+ "from", 1);
+ this.mHeight = height;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mHeight,
+ "from", 1);
+ this.mDensityDpi = densityDpi;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mDensityDpi,
+ "from", 1);
+ this.mFlags = flags;
+ this.mSurface = surface;
+ this.mUniqueId = uniqueId;
+ this.mDisplayIdToMirror = displayIdToMirror;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The name of the virtual display, must be non-empty.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getName() {
+ return mName;
+ }
+
+ /**
+ * The width of the virtual display in pixels. Must be greater than 0.
+ */
+ @DataClass.Generated.Member
+ public @IntRange(from = 1) int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * The height of the virtual display in pixels. Must be greater than 0.
+ */
+ @DataClass.Generated.Member
+ public @IntRange(from = 1) int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * The density of the virtual display in dpi. Must be greater than 0.
+ */
+ @DataClass.Generated.Member
+ public @IntRange(from = 1) int getDensityDpi() {
+ return mDensityDpi;
+ }
+
+ /**
+ * A combination of virtual display flags.
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
+ * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+ */
+ @DataClass.Generated.Member
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * The surface to which the content of the virtual display should be rendered, or null if
+ * there is none initially.
+ */
+ @DataClass.Generated.Member
+ public @Nullable Surface getSurface() {
+ return mSurface;
+ }
+
+ /**
+ * The unique identifier for the display. Shouldn't be displayed to the user.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getUniqueId() {
+ return mUniqueId;
+ }
+
+ /**
+ * The id of the display that the virtual display should mirror, or
+ * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+ */
+ @DataClass.Generated.Member
+ public int getDisplayIdToMirror() {
+ return mDisplayIdToMirror;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ int flg = 0;
+ if (mSurface != null) flg |= 0x20;
+ if (mUniqueId != null) flg |= 0x40;
+ dest.writeInt(flg);
+ dest.writeString(mName);
+ dest.writeInt(mWidth);
+ dest.writeInt(mHeight);
+ dest.writeInt(mDensityDpi);
+ dest.writeInt(mFlags);
+ if (mSurface != null) dest.writeTypedObject(mSurface, flags);
+ if (mUniqueId != null) dest.writeString(mUniqueId);
+ dest.writeInt(mDisplayIdToMirror);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ VirtualDisplayConfig(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ int flg = in.readInt();
+ String name = in.readString();
+ int width = in.readInt();
+ int height = in.readInt();
+ int densityDpi = in.readInt();
+ int flags = in.readInt();
+ Surface surface = (flg & 0x20) == 0 ? null : (Surface) in.readTypedObject(Surface.CREATOR);
+ String uniqueId = (flg & 0x40) == 0 ? null : in.readString();
+ int displayIdToMirror = in.readInt();
+
+ this.mName = name;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mName);
+ this.mWidth = width;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mWidth,
+ "from", 1);
+ this.mHeight = height;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mHeight,
+ "from", 1);
+ this.mDensityDpi = densityDpi;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mDensityDpi,
+ "from", 1);
+ this.mFlags = flags;
+ this.mSurface = surface;
+ this.mUniqueId = uniqueId;
+ this.mDisplayIdToMirror = displayIdToMirror;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<VirtualDisplayConfig> CREATOR
+ = new Parcelable.Creator<VirtualDisplayConfig>() {
+ @Override
+ public VirtualDisplayConfig[] newArray(int size) {
+ return new VirtualDisplayConfig[size];
+ }
+
+ @Override
+ public VirtualDisplayConfig createFromParcel(@NonNull Parcel in) {
+ return new VirtualDisplayConfig(in);
+ }
+ };
+
+ /**
+ * A builder for {@link VirtualDisplayConfig}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private @NonNull String mName;
+ private @IntRange(from = 1) int mWidth;
+ private @IntRange(from = 1) int mHeight;
+ private @IntRange(from = 1) int mDensityDpi;
+ private int mFlags;
+ private @Nullable Surface mSurface;
+ private @Nullable String mUniqueId;
+ private int mDisplayIdToMirror;
+
+ private long mBuilderFieldsSet = 0L;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @param name
+ * The name of the virtual display, must be non-empty.
+ * @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.
+ */
+ public Builder(
+ @NonNull String name,
+ @IntRange(from = 1) int width,
+ @IntRange(from = 1) int height,
+ @IntRange(from = 1) int densityDpi) {
+ mName = name;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mName);
+ mWidth = width;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mWidth,
+ "from", 1);
+ mHeight = height;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mHeight,
+ "from", 1);
+ mDensityDpi = densityDpi;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mDensityDpi,
+ "from", 1);
+ }
+
+ /**
+ * The name of the virtual display, must be non-empty.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setName(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mName = value;
+ return this;
+ }
+
+ /**
+ * The width of the virtual display in pixels. Must be greater than 0.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setWidth(@IntRange(from = 1) int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mWidth = value;
+ return this;
+ }
+
+ /**
+ * The height of the virtual display in pixels. Must be greater than 0.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setHeight(@IntRange(from = 1) int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mHeight = value;
+ return this;
+ }
+
+ /**
+ * The density of the virtual display in dpi. Must be greater than 0.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setDensityDpi(@IntRange(from = 1) int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mDensityDpi = value;
+ return this;
+ }
+
+ /**
+ * A combination of virtual display flags.
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
+ * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
+ * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setFlags(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mFlags = value;
+ return this;
+ }
+
+ /**
+ * The surface to which the content of the virtual display should be rendered, or null if
+ * there is none initially.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setSurface(@NonNull Surface value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mSurface = value;
+ return this;
+ }
+
+ /**
+ * The unique identifier for the display. Shouldn't be displayed to the user.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setUniqueId(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40;
+ mUniqueId = value;
+ return this;
+ }
+
+ /**
+ * The id of the display that the virtual display should mirror, or
+ * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setDisplayIdToMirror(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x80;
+ mDisplayIdToMirror = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull VirtualDisplayConfig build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x100; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x10) == 0) {
+ mFlags = 0;
+ }
+ if ((mBuilderFieldsSet & 0x20) == 0) {
+ mSurface = null;
+ }
+ if ((mBuilderFieldsSet & 0x40) == 0) {
+ mUniqueId = null;
+ }
+ if ((mBuilderFieldsSet & 0x80) == 0) {
+ mDisplayIdToMirror = DEFAULT_DISPLAY;
+ }
+ VirtualDisplayConfig o = new VirtualDisplayConfig(
+ mName,
+ mWidth,
+ mHeight,
+ mDensityDpi,
+ mFlags,
+ mSurface,
+ mUniqueId,
+ mDisplayIdToMirror);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x100) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1585179350902L,
+ codegenVersion = "1.0.15",
+ sourceFile = "frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java",
+ inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange(from=1L) int mWidth\nprivate @android.annotation.IntRange(from=1L) int mHeight\nprivate @android.annotation.IntRange(from=1L) int mDensityDpi\nprivate int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 632cfb0f1e30..37e141537c79 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
+import android.hardware.display.VirtualDisplayConfig;
import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjectionCallback;
import android.os.Handler;
@@ -100,11 +101,18 @@ public final class MediaProjection {
int width, int height, int dpi, boolean isSecure, @Nullable Surface surface,
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
- int flags = isSecure ? DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE : 0;
- return dm.createVirtualDisplay(this, name, width, height, dpi, surface,
- flags | DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR |
- DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION, callback, handler,
- null /* uniqueId */);
+ int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
+ | DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
+ if (isSecure) {
+ flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
+ }
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+ height, dpi);
+ builder.setFlags(flags);
+ if (surface != null) {
+ builder.setSurface(surface);
+ }
+ return dm.createVirtualDisplay(this, builder.build(), callback, handler);
}
/**
@@ -133,9 +141,35 @@ public final class MediaProjection {
public VirtualDisplay createVirtualDisplay(@NonNull String name,
int width, int height, int dpi, int flags, @Nullable Surface surface,
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
- DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
- return dm.createVirtualDisplay(this, name, width, height, dpi, surface, flags, callback,
- handler, null /* uniqueId */);
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+ height, dpi);
+ builder.setFlags(flags);
+ if (surface != null) {
+ builder.setSurface(surface);
+ }
+ return createVirtualDisplay(builder.build(), callback, handler);
+ }
+
+ /**
+ * Creates a {@link android.hardware.display.VirtualDisplay} to capture the
+ * contents of the screen.
+ *
+ * @param virtualDisplayConfig The arguments for the virtual display configuration. See
+ * {@link VirtualDisplayConfig} for using it.
+ * @param callback Callback to call when the virtual display's state
+ * changes, or null if none.
+ * @param handler The {@link android.os.Handler} on which the callback should be
+ * invoked, or null if the callback should be invoked on the calling
+ * thread's main {@link android.os.Looper}.
+ *
+ * @see android.hardware.display.VirtualDisplay
+ * @hide
+ */
+ @Nullable
+ public VirtualDisplay createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig,
+ @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
+ DisplayManager dm = mContext.getSystemService(DisplayManager.class);
+ return dm.createVirtualDisplay(this, virtualDisplayConfig, callback, handler);
}
/**
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 63a8d7c92441..696daca79092 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -19,6 +19,7 @@ package com.android.server.display;
import android.graphics.Rect;
import android.hardware.display.DisplayViewport;
import android.os.IBinder;
+import android.view.Display;
import android.view.DisplayAddress;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -78,6 +79,13 @@ abstract class DisplayDevice {
}
/**
+ * Gets the id of the display to mirror.
+ */
+ public int getDisplayIdToMirrorLocked() {
+ return Display.DEFAULT_DISPLAY;
+ }
+
+ /**
* Gets the name of the display device.
*
* @return The display device name.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a23205124f74..3afbf661f97e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -57,6 +57,7 @@ import android.hardware.display.DisplayedContentSamplingAttributes;
import android.hardware.display.IDisplayManager;
import android.hardware.display.IDisplayManagerCallback;
import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
import android.hardware.display.WifiDisplayStatus;
import android.hardware.input.InputManagerInternal;
import android.media.projection.IMediaProjection;
@@ -794,8 +795,8 @@ public final class DisplayManagerService extends SystemService {
}
private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
- IMediaProjection projection, int callingUid, String packageName, String name, int width,
- int height, int densityDpi, Surface surface, int flags, String uniqueId) {
+ IMediaProjection projection, int callingUid, String packageName, Surface surface,
+ int flags, VirtualDisplayConfig virtualDisplayConfig) {
synchronized (mSyncRoot) {
if (mVirtualDisplayAdapter == null) {
Slog.w(TAG, "Rejecting request to create private virtual display "
@@ -804,8 +805,8 @@ public final class DisplayManagerService extends SystemService {
}
DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
- callback, projection, callingUid, packageName, name, width, height, densityDpi,
- surface, flags, uniqueId);
+ callback, projection, callingUid, packageName, surface, flags,
+ virtualDisplayConfig);
if (device == null) {
return -1;
}
@@ -1480,8 +1481,8 @@ public final class DisplayManagerService extends SystemService {
if (!ownContent) {
if (display != null && !display.hasContentLocked()) {
// If the display does not have any content of its own, then
- // automatically mirror the default logical display contents.
- display = null;
+ // automatically mirror the requested logical display contents if possible.
+ display = mLogicalDisplays.get(device.getDisplayIdToMirrorLocked());
}
if (display == null) {
display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
@@ -1729,6 +1730,28 @@ public final class DisplayManagerService extends SystemService {
}
}
+ @VisibleForTesting
+ int getDisplayIdToMirrorInternal(int displayId) {
+ synchronized (mSyncRoot) {
+ LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display != null) {
+ DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
+ return displayDevice.getDisplayIdToMirrorLocked();
+ }
+ return Display.INVALID_DISPLAY;
+ }
+ }
+
+ @VisibleForTesting
+ Surface getVirtualDisplaySurfaceInternal(IBinder appToken) {
+ synchronized (mSyncRoot) {
+ if (mVirtualDisplayAdapter == null) {
+ return null;
+ }
+ return mVirtualDisplayAdapter.getVirtualDisplaySurfaceLocked(appToken);
+ }
+ }
+
private final class DisplayManagerHandler extends Handler {
public DisplayManagerHandler(Looper looper) {
super(looper, null, true /*async*/);
@@ -2050,10 +2073,8 @@ public final class DisplayManagerService extends SystemService {
}
@Override // Binder call
- public int createVirtualDisplay(IVirtualDisplayCallback callback,
- IMediaProjection projection, String packageName, String name,
- int width, int height, int densityDpi, Surface surface, int flags,
- String uniqueId) {
+ public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
+ IVirtualDisplayCallback callback, IMediaProjection projection, String packageName) {
final int callingUid = Binder.getCallingUid();
if (!validatePackageName(callingUid, packageName)) {
throw new SecurityException("packageName must match the calling uid");
@@ -2061,13 +2082,12 @@ public final class DisplayManagerService extends SystemService {
if (callback == null) {
throw new IllegalArgumentException("appToken must not be null");
}
- if (TextUtils.isEmpty(name)) {
- throw new IllegalArgumentException("name must be non-null and non-empty");
- }
- if (width <= 0 || height <= 0 || densityDpi <= 0) {
- throw new IllegalArgumentException("width, height, and densityDpi must be "
- + "greater than 0");
+ if (virtualDisplayConfig == null) {
+ throw new IllegalArgumentException("virtualDisplayConfig must not be null");
}
+ final Surface surface = virtualDisplayConfig.getSurface();
+ int flags = virtualDisplayConfig.getFlags();
+
if (surface != null && surface.isSingleBuffered()) {
throw new IllegalArgumentException("Surface can't be single-buffered");
}
@@ -2128,7 +2148,7 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
- name, width, height, densityDpi, surface, flags, uniqueId);
+ surface, flags, virtualDisplayConfig);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index f4f2eadfaa8e..ccd88483593a 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -28,6 +28,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPO
import android.content.Context;
import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjectionCallback;
import android.os.Handler;
@@ -84,22 +85,24 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
}
public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback,
- IMediaProjection projection, int ownerUid, String ownerPackageName, String name,
- int width, int height, int densityDpi, Surface surface, int flags, String uniqueId) {
+ IMediaProjection projection, int ownerUid, String ownerPackageName, Surface surface,
+ int flags, VirtualDisplayConfig virtualDisplayConfig) {
+ String name = virtualDisplayConfig.getName();
boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
IBinder appToken = callback.asBinder();
IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure);
final String baseUniqueId =
UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ",";
final int uniqueIndex = getNextUniqueIndex(baseUniqueId);
+ String uniqueId = virtualDisplayConfig.getUniqueId();
if (uniqueId == null) {
uniqueId = baseUniqueId + uniqueIndex;
} else {
uniqueId = UNIQUE_ID_PREFIX + ownerPackageName + ":" + uniqueId;
}
VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
- ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags,
- new Callback(callback, mHandler), uniqueId, uniqueIndex);
+ ownerUid, ownerPackageName, surface, flags, new Callback(callback, mHandler),
+ uniqueId, uniqueIndex, virtualDisplayConfig);
mVirtualDisplayDevices.put(appToken, device);
@@ -127,6 +130,14 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
}
}
+ @VisibleForTesting
+ Surface getVirtualDisplaySurfaceLocked(IBinder appToken) {
+ VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
+ if (device != null) {
+ return device.getSurfaceLocked();
+ }
+ return null;
+ }
public void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) {
VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
@@ -214,20 +225,21 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
private int mUniqueIndex;
private Display.Mode mMode;
private boolean mIsDisplayOn;
+ private int mDisplayIdToMirror;
public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
- int ownerUid, String ownerPackageName,
- String name, int width, int height, int densityDpi, Surface surface, int flags,
- Callback callback, String uniqueId, int uniqueIndex) {
+ int ownerUid, String ownerPackageName, Surface surface, int flags,
+ Callback callback, String uniqueId, int uniqueIndex,
+ VirtualDisplayConfig virtualDisplayConfig) {
super(VirtualDisplayAdapter.this, displayToken, uniqueId);
mAppToken = appToken;
mOwnerUid = ownerUid;
mOwnerPackageName = ownerPackageName;
- mName = name;
- mWidth = width;
- mHeight = height;
- mMode = createMode(width, height, REFRESH_RATE);
- mDensityDpi = densityDpi;
+ mName = virtualDisplayConfig.getName();
+ mWidth = virtualDisplayConfig.getWidth();
+ mHeight = virtualDisplayConfig.getHeight();
+ mMode = createMode(mWidth, mHeight, REFRESH_RATE);
+ mDensityDpi = virtualDisplayConfig.getDensityDpi();
mSurface = surface;
mFlags = flags;
mCallback = callback;
@@ -235,6 +247,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
mPendingChanges |= PENDING_SURFACE_CHANGE;
mUniqueIndex = uniqueIndex;
mIsDisplayOn = surface != null;
+ mDisplayIdToMirror = virtualDisplayConfig.getDisplayIdToMirror();
}
@Override
@@ -260,6 +273,16 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
}
@Override
+ public int getDisplayIdToMirrorLocked() {
+ return mDisplayIdToMirror;
+ }
+
+ @VisibleForTesting
+ Surface getSurfaceLocked() {
+ return mSurface;
+ }
+
+ @Override
public boolean hasStableUniqueId() {
return false;
}
@@ -332,6 +355,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
pw.println("mFlags=" + mFlags);
pw.println("mDisplayState=" + Display.stateToString(mDisplayState));
pw.println("mStopped=" + mStopped);
+ pw.println("mDisplayIdToMirror=" + mDisplayIdToMirror);
}
diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java
index a16dbb726613..3f2b5c231dca 100644
--- a/services/core/java/com/android/server/vr/Vr2dDisplay.java
+++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java
@@ -11,6 +11,7 @@ import android.content.IntentFilter;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
+import android.hardware.display.VirtualDisplayConfig;
import android.media.ImageReader;
import android.os.Handler;
import android.os.RemoteException;
@@ -295,10 +296,12 @@ class Vr2dDisplay {
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+ DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi);
+ builder.setUniqueId(UNIQUE_DISPLAY_ID);
+ builder.setFlags(flags);
mVirtualDisplay = mDisplayManager.createVirtualDisplay(null /* projection */,
- DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi,
- null /* surface */, flags, null /* callback */, null /* handler */,
- UNIQUE_DISPLAY_ID);
+ builder.build(), null /* callback */, null /* handler */);
if (mVirtualDisplay != null) {
updateDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 702718569871..7ad39b440e14 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -34,14 +34,17 @@ import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.InputManagerInternal;
import android.os.Handler;
import android.os.IBinder;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.Surface;
import android.view.SurfaceControl;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -67,6 +70,8 @@ import java.util.stream.LongStream;
public class DisplayManagerServiceTest {
private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
+ private static final String VIRTUAL_DISPLAY_NAME = "Test Virtual Display";
+ private static final String PACKAGE_NAME = "com.android.frameworks.servicestests";
private Context mContext;
@@ -97,6 +102,7 @@ public class DisplayManagerServiceTest {
@Mock InputManagerInternal mMockInputManagerInternal;
@Mock IVirtualDisplayCallback.Stub mMockAppToken;
+ @Mock IVirtualDisplayCallback.Stub mMockAppToken2;
@Mock WindowManagerInternal mMockWindowManagerInternal;
@Mock LightsManager mMockLightsManager;
@Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
@@ -135,10 +141,12 @@ public class DisplayManagerServiceTest {
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
- int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
- null /* projection */, "com.android.frameworks.servicestests",
- "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
- uniqueId);
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+ VIRTUAL_DISPLAY_NAME, width, height, dpi);
+ builder.setUniqueId(uniqueId);
+ builder.setFlags(flags);
+ int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
+ null /* projection */, PACKAGE_NAME);
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -241,10 +249,12 @@ public class DisplayManagerServiceTest {
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
- int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
- null /* projection */, "com.android.frameworks.servicestests",
- "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
- uniqueId);
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+ VIRTUAL_DISPLAY_NAME, width, height, dpi);
+ builder.setFlags(flags);
+ builder.setUniqueId(uniqueId);
+ int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
+ null /* projection */, PACKAGE_NAME);
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -409,6 +419,87 @@ public class DisplayManagerServiceTest {
assertTrue(samples.length == 0 || LongStream.of(samples).sum() == numPixels);
}
+ /**
+ * Tests that the virtual display is created with
+ * {@link VirtualDisplayConfig.Builder#setDisplayIdToMirror(int)}
+ */
+ @Test
+ @FlakyTest(bugId = 127687569)
+ public void testCreateVirtualDisplay_displayIdToMirror() throws Exception {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+ registerDefaultDisplays(displayManager);
+
+ // This is effectively the DisplayManager service published to ServiceManager.
+ DisplayManagerService.BinderService binderService = displayManager.new BinderService();
+
+ final String uniqueId = "uniqueId --- displayIdToMirrorTest";
+ final int width = 600;
+ final int height = 800;
+ final int dpi = 320;
+
+ when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+ VIRTUAL_DISPLAY_NAME, width, height, dpi);
+ builder.setUniqueId(uniqueId);
+ final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
+ mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
+
+ // The second virtual display requests to mirror the first virtual display.
+ final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
+ when(mMockAppToken2.asBinder()).thenReturn(mMockAppToken2);
+ final VirtualDisplayConfig.Builder builder2 = new VirtualDisplayConfig.Builder(
+ VIRTUAL_DISPLAY_NAME, width, height, dpi).setUniqueId(uniqueId2);
+ builder2.setUniqueId(uniqueId2);
+ builder2.setDisplayIdToMirror(firstDisplayId);
+ final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
+ mMockAppToken2 /* callback */, null /* projection */, PACKAGE_NAME);
+ displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
+
+ // flush the handler
+ displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
+
+ // The displayId to mirror should be a default display if there is none initially.
+ assertEquals(displayManager.getDisplayIdToMirrorInternal(firstDisplayId),
+ Display.DEFAULT_DISPLAY);
+ assertEquals(displayManager.getDisplayIdToMirrorInternal(secondDisplayId),
+ firstDisplayId);
+ }
+
+ /**
+ * Tests that the virtual display is created with
+ * {@link VirtualDisplayConfig.Builder#setSurface(Surface)}
+ */
+ @Test
+ @FlakyTest(bugId = 127687569)
+ public void testCreateVirtualDisplay_setSurface() throws Exception {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+ registerDefaultDisplays(displayManager);
+
+ // This is effectively the DisplayManager service published to ServiceManager.
+ DisplayManagerService.BinderService binderService = displayManager.new BinderService();
+
+ final String uniqueId = "uniqueId --- setSurface";
+ final int width = 600;
+ final int height = 800;
+ final int dpi = 320;
+ final Surface surface = new Surface();
+
+ when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+ VIRTUAL_DISPLAY_NAME, width, height, dpi);
+ builder.setSurface(surface);
+ builder.setUniqueId(uniqueId);
+ final int displayId = binderService.createVirtualDisplay(builder.build(),
+ mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
+
+ displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
+
+ // flush the handler
+ displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
+
+ assertEquals(displayManager.getVirtualDisplaySurfaceInternal(mMockAppToken), surface);
+ }
+
private void registerDefaultDisplays(DisplayManagerService displayManager) {
Handler handler = displayManager.getDisplayHandler();
// Would prefer to call displayManager.onStart() directly here but it performs binderService