Merge "[wm] VirtualDisplayConfig to mirror the non-default display" into rvc-dev am: 8885e4f115
Change-Id: Ib2d3395f416c82bd54e06986bc6cf407b0fd5d07
This commit is contained in:
@@ -634,17 +634,39 @@ public final class DisplayManager {
|
|||||||
public VirtualDisplay createVirtualDisplay(@NonNull String name,
|
public VirtualDisplay createVirtualDisplay(@NonNull String name,
|
||||||
int width, int height, int densityDpi, @Nullable Surface surface, int flags,
|
int width, int height, int densityDpi, @Nullable Surface surface, int flags,
|
||||||
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
||||||
return createVirtualDisplay(null /* projection */, name, width, height, densityDpi, surface,
|
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
|
||||||
flags, callback, handler, null /* uniqueId */);
|
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 */
|
/** @hide */
|
||||||
public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection,
|
public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection,
|
||||||
@NonNull String name, int width, int height, int densityDpi, @Nullable Surface surface,
|
@NonNull String name, int width, int height, int densityDpi, @Nullable Surface surface,
|
||||||
int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler,
|
int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler,
|
||||||
@Nullable String uniqueId) {
|
@Nullable String uniqueId) {
|
||||||
return mGlobal.createVirtualDisplay(mContext, projection,
|
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
|
||||||
name, width, height, densityDpi, surface, flags, callback, handler, uniqueId);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -451,35 +451,26 @@ public final class DisplayManagerGlobal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
|
public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection,
|
||||||
String name, int width, int height, int densityDpi, Surface surface, int flags,
|
@NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback,
|
||||||
VirtualDisplay.Callback callback, Handler handler, String uniqueId) {
|
Handler handler) {
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
|
VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
|
||||||
IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
|
IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
|
||||||
int displayId;
|
int displayId;
|
||||||
try {
|
try {
|
||||||
displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
|
displayId = mDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper,
|
||||||
context.getPackageName(), name, width, height, densityDpi, surface, flags,
|
projectionToken, context.getPackageName());
|
||||||
uniqueId);
|
|
||||||
} catch (RemoteException ex) {
|
} catch (RemoteException ex) {
|
||||||
throw ex.rethrowFromSystemServer();
|
throw ex.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
if (displayId < 0) {
|
if (displayId < 0) {
|
||||||
Log.e(TAG, "Could not create virtual display: " + name);
|
Log.e(TAG, "Could not create virtual display: " + virtualDisplayConfig.getName());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Display display = getRealDisplay(displayId);
|
Display display = getRealDisplay(displayId);
|
||||||
if (display == null) {
|
if (display == null) {
|
||||||
Log.wtf(TAG, "Could not obtain display info for newly created "
|
Log.wtf(TAG, "Could not obtain display info for newly created "
|
||||||
+ "virtual display: " + name);
|
+ "virtual display: " + virtualDisplayConfig.getName());
|
||||||
try {
|
try {
|
||||||
mDm.releaseVirtualDisplay(callbackWrapper);
|
mDm.releaseVirtualDisplay(callbackWrapper);
|
||||||
} catch (RemoteException ex) {
|
} catch (RemoteException ex) {
|
||||||
@@ -487,7 +478,8 @@ public final class DisplayManagerGlobal {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new VirtualDisplay(this, display, callbackWrapper, surface);
|
return new VirtualDisplay(this, display, callbackWrapper,
|
||||||
|
virtualDisplayConfig.getSurface());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
|
public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import android.hardware.display.BrightnessConfiguration;
|
|||||||
import android.hardware.display.Curve;
|
import android.hardware.display.Curve;
|
||||||
import android.hardware.display.IDisplayManagerCallback;
|
import android.hardware.display.IDisplayManagerCallback;
|
||||||
import android.hardware.display.IVirtualDisplayCallback;
|
import android.hardware.display.IVirtualDisplayCallback;
|
||||||
|
import android.hardware.display.VirtualDisplayConfig;
|
||||||
import android.hardware.display.WifiDisplay;
|
import android.hardware.display.WifiDisplay;
|
||||||
import android.hardware.display.WifiDisplayStatus;
|
import android.hardware.display.WifiDisplayStatus;
|
||||||
import android.media.projection.IMediaProjection;
|
import android.media.projection.IMediaProjection;
|
||||||
@@ -71,9 +72,9 @@ interface IDisplayManager {
|
|||||||
|
|
||||||
// Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
|
// Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
|
||||||
// MediaProjection token for certain combinations of flags.
|
// MediaProjection token for certain combinations of flags.
|
||||||
int createVirtualDisplay(in IVirtualDisplayCallback callback,
|
int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig,
|
||||||
in IMediaProjection projectionToken, String packageName, String name,
|
in IVirtualDisplayCallback callback, in IMediaProjection projectionToken,
|
||||||
int width, int height, int densityDpi, in Surface surface, int flags, String uniqueId);
|
String packageName);
|
||||||
|
|
||||||
// No permissions required, but must be same Uid as the creator.
|
// No permissions required, but must be same Uid as the creator.
|
||||||
void resizeVirtualDisplay(in IVirtualDisplayCallback token,
|
void resizeVirtualDisplay(in IVirtualDisplayCallback token,
|
||||||
|
|||||||
19
core/java/android/hardware/display/VirtualDisplayConfig.aidl
Normal file
19
core/java/android/hardware/display/VirtualDisplayConfig.aidl
Normal file
@@ -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;
|
||||||
491
core/java/android/hardware/display/VirtualDisplayConfig.java
Normal file
491
core/java/android/hardware/display/VirtualDisplayConfig.java
Normal file
@@ -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
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.hardware.display.VirtualDisplay;
|
import android.hardware.display.VirtualDisplay;
|
||||||
|
import android.hardware.display.VirtualDisplayConfig;
|
||||||
import android.media.projection.IMediaProjection;
|
import android.media.projection.IMediaProjection;
|
||||||
import android.media.projection.IMediaProjectionCallback;
|
import android.media.projection.IMediaProjectionCallback;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -100,11 +101,18 @@ public final class MediaProjection {
|
|||||||
int width, int height, int dpi, boolean isSecure, @Nullable Surface surface,
|
int width, int height, int dpi, boolean isSecure, @Nullable Surface surface,
|
||||||
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
||||||
DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
|
DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
|
||||||
int flags = isSecure ? DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE : 0;
|
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
|
||||||
return dm.createVirtualDisplay(this, name, width, height, dpi, surface,
|
| DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
|
||||||
flags | DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR |
|
if (isSecure) {
|
||||||
DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION, callback, handler,
|
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
|
||||||
null /* uniqueId */);
|
}
|
||||||
|
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,
|
public VirtualDisplay createVirtualDisplay(@NonNull String name,
|
||||||
int width, int height, int dpi, int flags, @Nullable Surface surface,
|
int width, int height, int dpi, int flags, @Nullable Surface surface,
|
||||||
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
||||||
DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
|
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
|
||||||
return dm.createVirtualDisplay(this, name, width, height, dpi, surface, flags, callback,
|
height, dpi);
|
||||||
handler, null /* uniqueId */);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.server.display;
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.hardware.display.DisplayViewport;
|
import android.hardware.display.DisplayViewport;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.view.Display;
|
||||||
import android.view.DisplayAddress;
|
import android.view.DisplayAddress;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
@@ -77,6 +78,13 @@ abstract class DisplayDevice {
|
|||||||
return mDisplayToken;
|
return mDisplayToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id of the display to mirror.
|
||||||
|
*/
|
||||||
|
public int getDisplayIdToMirrorLocked() {
|
||||||
|
return Display.DEFAULT_DISPLAY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name of the display device.
|
* Gets the name of the display device.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import android.hardware.display.DisplayedContentSamplingAttributes;
|
|||||||
import android.hardware.display.IDisplayManager;
|
import android.hardware.display.IDisplayManager;
|
||||||
import android.hardware.display.IDisplayManagerCallback;
|
import android.hardware.display.IDisplayManagerCallback;
|
||||||
import android.hardware.display.IVirtualDisplayCallback;
|
import android.hardware.display.IVirtualDisplayCallback;
|
||||||
|
import android.hardware.display.VirtualDisplayConfig;
|
||||||
import android.hardware.display.WifiDisplayStatus;
|
import android.hardware.display.WifiDisplayStatus;
|
||||||
import android.hardware.input.InputManagerInternal;
|
import android.hardware.input.InputManagerInternal;
|
||||||
import android.media.projection.IMediaProjection;
|
import android.media.projection.IMediaProjection;
|
||||||
@@ -794,8 +795,8 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
|
private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
|
||||||
IMediaProjection projection, int callingUid, String packageName, String name, int width,
|
IMediaProjection projection, int callingUid, String packageName, Surface surface,
|
||||||
int height, int densityDpi, Surface surface, int flags, String uniqueId) {
|
int flags, VirtualDisplayConfig virtualDisplayConfig) {
|
||||||
synchronized (mSyncRoot) {
|
synchronized (mSyncRoot) {
|
||||||
if (mVirtualDisplayAdapter == null) {
|
if (mVirtualDisplayAdapter == null) {
|
||||||
Slog.w(TAG, "Rejecting request to create private virtual display "
|
Slog.w(TAG, "Rejecting request to create private virtual display "
|
||||||
@@ -804,8 +805,8 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
|
DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
|
||||||
callback, projection, callingUid, packageName, name, width, height, densityDpi,
|
callback, projection, callingUid, packageName, surface, flags,
|
||||||
surface, flags, uniqueId);
|
virtualDisplayConfig);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1480,8 +1481,8 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
if (!ownContent) {
|
if (!ownContent) {
|
||||||
if (display != null && !display.hasContentLocked()) {
|
if (display != null && !display.hasContentLocked()) {
|
||||||
// If the display does not have any content of its own, then
|
// If the display does not have any content of its own, then
|
||||||
// automatically mirror the default logical display contents.
|
// automatically mirror the requested logical display contents if possible.
|
||||||
display = null;
|
display = mLogicalDisplays.get(device.getDisplayIdToMirrorLocked());
|
||||||
}
|
}
|
||||||
if (display == null) {
|
if (display == null) {
|
||||||
display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
|
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 {
|
private final class DisplayManagerHandler extends Handler {
|
||||||
public DisplayManagerHandler(Looper looper) {
|
public DisplayManagerHandler(Looper looper) {
|
||||||
super(looper, null, true /*async*/);
|
super(looper, null, true /*async*/);
|
||||||
@@ -2050,10 +2073,8 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override // Binder call
|
@Override // Binder call
|
||||||
public int createVirtualDisplay(IVirtualDisplayCallback callback,
|
public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
|
||||||
IMediaProjection projection, String packageName, String name,
|
IVirtualDisplayCallback callback, IMediaProjection projection, String packageName) {
|
||||||
int width, int height, int densityDpi, Surface surface, int flags,
|
|
||||||
String uniqueId) {
|
|
||||||
final int callingUid = Binder.getCallingUid();
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (!validatePackageName(callingUid, packageName)) {
|
if (!validatePackageName(callingUid, packageName)) {
|
||||||
throw new SecurityException("packageName must match the calling uid");
|
throw new SecurityException("packageName must match the calling uid");
|
||||||
@@ -2061,13 +2082,12 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
throw new IllegalArgumentException("appToken must not be null");
|
throw new IllegalArgumentException("appToken must not be null");
|
||||||
}
|
}
|
||||||
if (TextUtils.isEmpty(name)) {
|
if (virtualDisplayConfig == null) {
|
||||||
throw new IllegalArgumentException("name must be non-null and non-empty");
|
throw new IllegalArgumentException("virtualDisplayConfig must not be null");
|
||||||
}
|
|
||||||
if (width <= 0 || height <= 0 || densityDpi <= 0) {
|
|
||||||
throw new IllegalArgumentException("width, height, and densityDpi must be "
|
|
||||||
+ "greater than 0");
|
|
||||||
}
|
}
|
||||||
|
final Surface surface = virtualDisplayConfig.getSurface();
|
||||||
|
int flags = virtualDisplayConfig.getFlags();
|
||||||
|
|
||||||
if (surface != null && surface.isSingleBuffered()) {
|
if (surface != null && surface.isSingleBuffered()) {
|
||||||
throw new IllegalArgumentException("Surface can't be single-buffered");
|
throw new IllegalArgumentException("Surface can't be single-buffered");
|
||||||
}
|
}
|
||||||
@@ -2128,7 +2148,7 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
|
return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
|
||||||
name, width, height, densityDpi, surface, flags, uniqueId);
|
surface, flags, virtualDisplayConfig);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(token);
|
Binder.restoreCallingIdentity(token);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPO
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.display.IVirtualDisplayCallback;
|
import android.hardware.display.IVirtualDisplayCallback;
|
||||||
|
import android.hardware.display.VirtualDisplayConfig;
|
||||||
import android.media.projection.IMediaProjection;
|
import android.media.projection.IMediaProjection;
|
||||||
import android.media.projection.IMediaProjectionCallback;
|
import android.media.projection.IMediaProjectionCallback;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -84,22 +85,24 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback,
|
public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback,
|
||||||
IMediaProjection projection, int ownerUid, String ownerPackageName, String name,
|
IMediaProjection projection, int ownerUid, String ownerPackageName, Surface surface,
|
||||||
int width, int height, int densityDpi, Surface surface, int flags, String uniqueId) {
|
int flags, VirtualDisplayConfig virtualDisplayConfig) {
|
||||||
|
String name = virtualDisplayConfig.getName();
|
||||||
boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
|
boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
|
||||||
IBinder appToken = callback.asBinder();
|
IBinder appToken = callback.asBinder();
|
||||||
IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure);
|
IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure);
|
||||||
final String baseUniqueId =
|
final String baseUniqueId =
|
||||||
UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ",";
|
UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ",";
|
||||||
final int uniqueIndex = getNextUniqueIndex(baseUniqueId);
|
final int uniqueIndex = getNextUniqueIndex(baseUniqueId);
|
||||||
|
String uniqueId = virtualDisplayConfig.getUniqueId();
|
||||||
if (uniqueId == null) {
|
if (uniqueId == null) {
|
||||||
uniqueId = baseUniqueId + uniqueIndex;
|
uniqueId = baseUniqueId + uniqueIndex;
|
||||||
} else {
|
} else {
|
||||||
uniqueId = UNIQUE_ID_PREFIX + ownerPackageName + ":" + uniqueId;
|
uniqueId = UNIQUE_ID_PREFIX + ownerPackageName + ":" + uniqueId;
|
||||||
}
|
}
|
||||||
VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
|
VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
|
||||||
ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags,
|
ownerUid, ownerPackageName, surface, flags, new Callback(callback, mHandler),
|
||||||
new Callback(callback, mHandler), uniqueId, uniqueIndex);
|
uniqueId, uniqueIndex, virtualDisplayConfig);
|
||||||
|
|
||||||
mVirtualDisplayDevices.put(appToken, device);
|
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) {
|
public void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) {
|
||||||
VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
|
VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
|
||||||
@@ -214,20 +225,21 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
|
|||||||
private int mUniqueIndex;
|
private int mUniqueIndex;
|
||||||
private Display.Mode mMode;
|
private Display.Mode mMode;
|
||||||
private boolean mIsDisplayOn;
|
private boolean mIsDisplayOn;
|
||||||
|
private int mDisplayIdToMirror;
|
||||||
|
|
||||||
public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
|
public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
|
||||||
int ownerUid, String ownerPackageName,
|
int ownerUid, String ownerPackageName, Surface surface, int flags,
|
||||||
String name, int width, int height, int densityDpi, Surface surface, int flags,
|
Callback callback, String uniqueId, int uniqueIndex,
|
||||||
Callback callback, String uniqueId, int uniqueIndex) {
|
VirtualDisplayConfig virtualDisplayConfig) {
|
||||||
super(VirtualDisplayAdapter.this, displayToken, uniqueId);
|
super(VirtualDisplayAdapter.this, displayToken, uniqueId);
|
||||||
mAppToken = appToken;
|
mAppToken = appToken;
|
||||||
mOwnerUid = ownerUid;
|
mOwnerUid = ownerUid;
|
||||||
mOwnerPackageName = ownerPackageName;
|
mOwnerPackageName = ownerPackageName;
|
||||||
mName = name;
|
mName = virtualDisplayConfig.getName();
|
||||||
mWidth = width;
|
mWidth = virtualDisplayConfig.getWidth();
|
||||||
mHeight = height;
|
mHeight = virtualDisplayConfig.getHeight();
|
||||||
mMode = createMode(width, height, REFRESH_RATE);
|
mMode = createMode(mWidth, mHeight, REFRESH_RATE);
|
||||||
mDensityDpi = densityDpi;
|
mDensityDpi = virtualDisplayConfig.getDensityDpi();
|
||||||
mSurface = surface;
|
mSurface = surface;
|
||||||
mFlags = flags;
|
mFlags = flags;
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
@@ -235,6 +247,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
|
|||||||
mPendingChanges |= PENDING_SURFACE_CHANGE;
|
mPendingChanges |= PENDING_SURFACE_CHANGE;
|
||||||
mUniqueIndex = uniqueIndex;
|
mUniqueIndex = uniqueIndex;
|
||||||
mIsDisplayOn = surface != null;
|
mIsDisplayOn = surface != null;
|
||||||
|
mDisplayIdToMirror = virtualDisplayConfig.getDisplayIdToMirror();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -259,6 +272,16 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDisplayIdToMirrorLocked() {
|
||||||
|
return mDisplayIdToMirror;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
Surface getSurfaceLocked() {
|
||||||
|
return mSurface;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasStableUniqueId() {
|
public boolean hasStableUniqueId() {
|
||||||
return false;
|
return false;
|
||||||
@@ -332,6 +355,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
|
|||||||
pw.println("mFlags=" + mFlags);
|
pw.println("mFlags=" + mFlags);
|
||||||
pw.println("mDisplayState=" + Display.stateToString(mDisplayState));
|
pw.println("mDisplayState=" + Display.stateToString(mDisplayState));
|
||||||
pw.println("mStopped=" + mStopped);
|
pw.println("mStopped=" + mStopped);
|
||||||
|
pw.println("mDisplayIdToMirror=" + mDisplayIdToMirror);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import android.content.IntentFilter;
|
|||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.hardware.display.VirtualDisplay;
|
import android.hardware.display.VirtualDisplay;
|
||||||
|
import android.hardware.display.VirtualDisplayConfig;
|
||||||
import android.media.ImageReader;
|
import android.media.ImageReader;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@@ -295,10 +296,12 @@ class Vr2dDisplay {
|
|||||||
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
|
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
|
||||||
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
|
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 */,
|
mVirtualDisplay = mDisplayManager.createVirtualDisplay(null /* projection */,
|
||||||
DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi,
|
builder.build(), null /* callback */, null /* handler */);
|
||||||
null /* surface */, flags, null /* callback */, null /* handler */,
|
|
||||||
UNIQUE_DISPLAY_ID);
|
|
||||||
|
|
||||||
if (mVirtualDisplay != null) {
|
if (mVirtualDisplay != null) {
|
||||||
updateDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
|
updateDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
|
||||||
|
|||||||
@@ -34,14 +34,17 @@ import android.hardware.display.DisplayViewport;
|
|||||||
import android.hardware.display.DisplayedContentSample;
|
import android.hardware.display.DisplayedContentSample;
|
||||||
import android.hardware.display.DisplayedContentSamplingAttributes;
|
import android.hardware.display.DisplayedContentSamplingAttributes;
|
||||||
import android.hardware.display.IVirtualDisplayCallback;
|
import android.hardware.display.IVirtualDisplayCallback;
|
||||||
|
import android.hardware.display.VirtualDisplayConfig;
|
||||||
import android.hardware.input.InputManagerInternal;
|
import android.hardware.input.InputManagerInternal;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
|
import android.view.Surface;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
import androidx.test.filters.FlakyTest;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -67,6 +70,8 @@ import java.util.stream.LongStream;
|
|||||||
public class DisplayManagerServiceTest {
|
public class DisplayManagerServiceTest {
|
||||||
private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
|
private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
|
||||||
private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
|
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;
|
private Context mContext;
|
||||||
|
|
||||||
@@ -97,6 +102,7 @@ public class DisplayManagerServiceTest {
|
|||||||
|
|
||||||
@Mock InputManagerInternal mMockInputManagerInternal;
|
@Mock InputManagerInternal mMockInputManagerInternal;
|
||||||
@Mock IVirtualDisplayCallback.Stub mMockAppToken;
|
@Mock IVirtualDisplayCallback.Stub mMockAppToken;
|
||||||
|
@Mock IVirtualDisplayCallback.Stub mMockAppToken2;
|
||||||
@Mock WindowManagerInternal mMockWindowManagerInternal;
|
@Mock WindowManagerInternal mMockWindowManagerInternal;
|
||||||
@Mock LightsManager mMockLightsManager;
|
@Mock LightsManager mMockLightsManager;
|
||||||
@Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
|
@Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
|
||||||
@@ -135,10 +141,12 @@ public class DisplayManagerServiceTest {
|
|||||||
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
|
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
|
||||||
|
|
||||||
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
||||||
int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
|
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
|
||||||
null /* projection */, "com.android.frameworks.servicestests",
|
VIRTUAL_DISPLAY_NAME, width, height, dpi);
|
||||||
"Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
|
builder.setUniqueId(uniqueId);
|
||||||
uniqueId);
|
builder.setFlags(flags);
|
||||||
|
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
|
||||||
|
null /* projection */, PACKAGE_NAME);
|
||||||
|
|
||||||
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
||||||
|
|
||||||
@@ -241,10 +249,12 @@ public class DisplayManagerServiceTest {
|
|||||||
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
|
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
|
||||||
|
|
||||||
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
|
||||||
int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
|
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
|
||||||
null /* projection */, "com.android.frameworks.servicestests",
|
VIRTUAL_DISPLAY_NAME, width, height, dpi);
|
||||||
"Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
|
builder.setFlags(flags);
|
||||||
uniqueId);
|
builder.setUniqueId(uniqueId);
|
||||||
|
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
|
||||||
|
null /* projection */, PACKAGE_NAME);
|
||||||
|
|
||||||
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
|
||||||
|
|
||||||
@@ -409,6 +419,87 @@ public class DisplayManagerServiceTest {
|
|||||||
assertTrue(samples.length == 0 || LongStream.of(samples).sum() == numPixels);
|
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) {
|
private void registerDefaultDisplays(DisplayManagerService displayManager) {
|
||||||
Handler handler = displayManager.getDisplayHandler();
|
Handler handler = displayManager.getDisplayHandler();
|
||||||
// Would prefer to call displayManager.onStart() directly here but it performs binderService
|
// Would prefer to call displayManager.onStart() directly here but it performs binderService
|
||||||
|
|||||||
Reference in New Issue
Block a user