Loading core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -19321,7 +19321,9 @@ package android.hardware.display { public final class DisplayManager { method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int); method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int); method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler); method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int, @Nullable android.os.Handler, @Nullable android.hardware.display.VirtualDisplay.Callback); method public android.view.Display getDisplay(int); method public android.view.Display[] getDisplays(); method public android.view.Display[] getDisplays(String); core/java/android/hardware/display/DisplayManager.java +89 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import java.util.concurrent.Executor; public final class DisplayManager { private static final String TAG = "DisplayManager"; private static final boolean DEBUG = false; private static final boolean ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE = false; private final Context mContext; private final DisplayManagerGlobal mGlobal; Loading Loading @@ -936,6 +937,24 @@ public final class DisplayManager { return createVirtualDisplay(name, width, height, densityDpi, surface, flags, null, null); } /** * Creates a virtual display. * * @see #createVirtualDisplay(String, int, int, int, float, Surface, int, * Handler, VirtualDisplay.Callback) */ @Nullable public VirtualDisplay createVirtualDisplay(@NonNull String name, @IntRange(from = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi, float requestedRefreshRate, @Nullable Surface surface, @VirtualDisplayFlag int flags) { return createVirtualDisplay(name, width, height, densityDpi, requestedRefreshRate, surface, flags, null, null); } /** * Creates a virtual display. * <p> Loading Loading @@ -987,12 +1006,82 @@ public final class DisplayManager { @VirtualDisplayFlag int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) { return createVirtualDisplay(name, width, height, densityDpi, 0.0f, surface, flags, handler, callback); } /** * Creates a virtual display. * <p> * The content of a virtual display is rendered to a {@link Surface} provided * by the application. * </p><p> * The virtual display should be {@link VirtualDisplay#release released} * when no longer needed. Because a virtual display renders to a surface * provided by the application, it will be released automatically when the * process terminates and all remaining windows on it will be forcibly removed. * </p><p> * The behavior of the virtual display depends on the flags that are provided * to this method. By default, virtual displays are created to be private, * non-presentation and unsecure. Permissions may be required to use certain flags. * </p><p> * As of {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}, the surface may * be attached or detached dynamically using {@link VirtualDisplay#setSurface}. * Previously, the surface had to be non-null when {@link #createVirtualDisplay} * was called and could not be changed for the lifetime of the display. * </p><p> * Detaching the surface that backs a virtual display has a similar effect to * turning off the screen. * </p> * * @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. * @param requestedRefreshRate The requested refresh rate in frames per second. * For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on * 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded * up or down to a divisor of the physical display. If 0 is specified, the virtual * display is refreshed at the physical display refresh rate. * @param surface The surface to which the content of the virtual display should * be rendered, or null if there is none initially. * @param flags A combination of virtual display flags: * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION}, * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}, * or {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}. * @param handler The handler on which the listener should be invoked, or null * if the listener should be invoked on the calling thread's looper. * @param callback Callback to call when the state of the {@link VirtualDisplay} changes * @return The newly created virtual display, or null if the application could * not create the virtual display. * * @throws SecurityException if the caller does not have permission to create * a virtual display with the specified flags. */ @Nullable public VirtualDisplay createVirtualDisplay(@NonNull String name, @IntRange(from = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi, float requestedRefreshRate, @Nullable Surface surface, @VirtualDisplayFlag int flags, @Nullable Handler handler, @Nullable VirtualDisplay.Callback callback) { if (!ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE && requestedRefreshRate != 0.0f) { Slog.e(TAG, "Please turn on ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE to use the new api"); return null; } final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width, height, densityDpi); builder.setFlags(flags); if (surface != null) { builder.setSurface(surface); } if (requestedRefreshRate != 0.0f) { builder.setRequestedRefreshRate(requestedRefreshRate); } return createVirtualDisplay(null /* projection */, builder.build(), callback, handler, null /* windowContext */); } Loading core/java/android/hardware/display/VirtualDisplayConfig.java +46 −6 Original line number Diff line number Diff line Loading @@ -109,6 +109,13 @@ public final class VirtualDisplayConfig implements Parcelable { @DataClass.PluralOf("displayCategory") @NonNull private List<String> mDisplayCategories = new ArrayList<>(); /** * The refresh rate of a virtual display in frames per second. * If this value is non-zero, this is the requested refresh rate to set. * If this value is zero, the system chooses a default refresh rate. */ private float mRequestedRefreshRate = 0.0f; // Code below generated by codegen v1.0.23. Loading @@ -135,7 +142,8 @@ public final class VirtualDisplayConfig implements Parcelable { @Nullable String uniqueId, int displayIdToMirror, boolean windowManagerMirroring, @NonNull List<String> displayCategories) { @NonNull List<String> displayCategories, float requestedRefreshRate) { this.mName = name; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mName); Loading @@ -161,6 +169,7 @@ public final class VirtualDisplayConfig implements Parcelable { this.mDisplayCategories = displayCategories; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mDisplayCategories); this.mRequestedRefreshRate = requestedRefreshRate; // onConstructed(); // You can define this method to get a callback } Loading Loading @@ -256,6 +265,16 @@ public final class VirtualDisplayConfig implements Parcelable { return mDisplayCategories; } /** * The refresh rate of a virtual display in frames per second. * If this value is none zero, this is the requested refresh rate to set. * If this value is zero, the system chooses a default refresh rate. */ @DataClass.Generated.Member public float getRequestedRefreshRate() { return mRequestedRefreshRate; } @Override @DataClass.Generated.Member public void writeToParcel(@NonNull Parcel dest, int flags) { Loading @@ -276,6 +295,7 @@ public final class VirtualDisplayConfig implements Parcelable { if (mUniqueId != null) dest.writeString(mUniqueId); dest.writeInt(mDisplayIdToMirror); dest.writeStringList(mDisplayCategories); dest.writeFloat(mRequestedRefreshRate); } @Override Loading @@ -301,6 +321,7 @@ public final class VirtualDisplayConfig implements Parcelable { int displayIdToMirror = in.readInt(); List<String> displayCategories = new ArrayList<>(); in.readStringList(displayCategories); float requestedRefreshRate = in.readFloat(); this.mName = name; com.android.internal.util.AnnotationValidations.validate( Loading @@ -327,6 +348,7 @@ public final class VirtualDisplayConfig implements Parcelable { this.mDisplayCategories = displayCategories; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mDisplayCategories); this.mRequestedRefreshRate = requestedRefreshRate; // onConstructed(); // You can define this method to get a callback } Loading Loading @@ -362,6 +384,7 @@ public final class VirtualDisplayConfig implements Parcelable { private int mDisplayIdToMirror; private boolean mWindowManagerMirroring; private @NonNull List<String> mDisplayCategories; private float mRequestedRefreshRate; private long mBuilderFieldsSet = 0L; Loading Loading @@ -528,10 +551,23 @@ public final class VirtualDisplayConfig implements Parcelable { return this; } /** * The refresh rate of a virtual display in frames per second. * If this value is none zero, this is the requested refresh rate to set. * If this value is zero, the system chooses a default refresh rate. */ @DataClass.Generated.Member public @NonNull Builder setRequestedRefreshRate(float value) { checkNotUsed(); mBuilderFieldsSet |= 0x400; mRequestedRefreshRate = value; return this; } /** Builds the instance. This builder should not be touched after calling this! */ public @NonNull VirtualDisplayConfig build() { checkNotUsed(); mBuilderFieldsSet |= 0x400; // Mark builder used mBuilderFieldsSet |= 0x800; // Mark builder used if ((mBuilderFieldsSet & 0x10) == 0) { mFlags = 0; Loading @@ -551,6 +587,9 @@ public final class VirtualDisplayConfig implements Parcelable { if ((mBuilderFieldsSet & 0x200) == 0) { mDisplayCategories = new ArrayList<>(); } if ((mBuilderFieldsSet & 0x400) == 0) { mRequestedRefreshRate = 0.0f; } VirtualDisplayConfig o = new VirtualDisplayConfig( mName, mWidth, Loading @@ -561,12 +600,13 @@ public final class VirtualDisplayConfig implements Parcelable { mUniqueId, mDisplayIdToMirror, mWindowManagerMirroring, mDisplayCategories); mDisplayCategories, mRequestedRefreshRate); return o; } private void checkNotUsed() { if ((mBuilderFieldsSet & 0x400) != 0) { if ((mBuilderFieldsSet & 0x800) != 0) { throw new IllegalStateException( "This Builder should not be reused. Use a new Builder instance instead"); } Loading @@ -574,10 +614,10 @@ public final class VirtualDisplayConfig implements Parcelable { } @DataClass.Generated( time = 1668534501320L, time = 1671047069703L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java", inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nprivate boolean mWindowManagerMirroring\nprivate @com.android.internal.util.DataClass.PluralOf(\"displayCategory\") @android.annotation.NonNull java.util.List<java.lang.String> mDisplayCategories\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)") inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nprivate boolean mWindowManagerMirroring\nprivate @com.android.internal.util.DataClass.PluralOf(\"displayCategory\") @android.annotation.NonNull java.util.List<java.lang.String> mDisplayCategories\nprivate float mRequestedRefreshRate\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() {} Loading services/core/java/com/android/server/display/DisplayControl.java +21 −2 Original line number Diff line number Diff line Loading @@ -28,7 +28,8 @@ import java.util.Objects; * Calls into SurfaceFlinger for Display creation and deletion. */ public class DisplayControl { private static native IBinder nativeCreateDisplay(String name, boolean secure); private static native IBinder nativeCreateDisplay(String name, boolean secure, float requestedRefreshRate); private static native void nativeDestroyDisplay(IBinder displayToken); private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes); private static native long[] nativeGetPhysicalDisplayIds(); Loading @@ -46,7 +47,25 @@ public class DisplayControl { */ public static IBinder createDisplay(String name, boolean secure) { Objects.requireNonNull(name, "name must not be null"); return nativeCreateDisplay(name, secure); return nativeCreateDisplay(name, secure, 0.0f); } /** * Create a display in SurfaceFlinger. * * @param name The name of the display * @param secure Whether this display is secure. * @param requestedRefreshRate The requested refresh rate in frames per second. * For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on * 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded * up or down to a divisor of the physical display. If 0 is specified, the virtual * display is refreshed at the physical display refresh rate. * @return The token reference for the display in SurfaceFlinger. */ public static IBinder createDisplay(String name, boolean secure, float requestedRefreshRate) { Objects.requireNonNull(name, "name must not be null"); return nativeCreateDisplay(name, secure, requestedRefreshRate); } /** Loading services/core/java/com/android/server/display/VirtualDisplayAdapter.java +26 −6 Original line number Diff line number Diff line Loading @@ -106,7 +106,8 @@ public class VirtualDisplayAdapter extends DisplayAdapter { String name = virtualDisplayConfig.getName(); boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0; IBinder appToken = callback.asBinder(); IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure); IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure, virtualDisplayConfig.getRequestedRefreshRate()); final String baseUniqueId = UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ","; final int uniqueIndex = getNextUniqueIndex(baseUniqueId); Loading Loading @@ -247,6 +248,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { private int mWidth; private int mHeight; private int mDensityDpi; private float mRequestedRefreshRate; private Surface mSurface; private DisplayDeviceInfo mInfo; private int mDisplayState; Loading @@ -270,8 +272,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { mName = virtualDisplayConfig.getName(); mWidth = virtualDisplayConfig.getWidth(); mHeight = virtualDisplayConfig.getHeight(); mMode = createMode(mWidth, mHeight, REFRESH_RATE); mDensityDpi = virtualDisplayConfig.getDensityDpi(); mRequestedRefreshRate = virtualDisplayConfig.getRequestedRefreshRate(); mMode = createMode(mWidth, mHeight, getRefreshRate()); mSurface = surface; mFlags = flags; mCallback = callback; Loading Loading @@ -410,7 +413,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { sendTraversalRequestLocked(); mWidth = width; mHeight = height; mMode = createMode(width, height, REFRESH_RATE); mMode = createMode(width, height, getRefreshRate()); mDensityDpi = densityDpi; mInfo = null; mPendingChanges |= PENDING_RESIZE; Loading Loading @@ -438,9 +441,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { pw.println("mStopped=" + mStopped); pw.println("mDisplayIdToMirror=" + mDisplayIdToMirror); pw.println("mWindowManagerMirroring=" + mIsWindowManagerMirroring); pw.println("mRequestedRefreshRate=" + mRequestedRefreshRate); } @Override public DisplayDeviceInfo getDisplayDeviceInfoLocked() { if (mInfo == null) { Loading @@ -456,7 +459,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { mInfo.densityDpi = mDensityDpi; mInfo.xDpi = mDensityDpi; mInfo.yDpi = mDensityDpi; mInfo.presentationDeadlineNanos = 1000000000L / (int) REFRESH_RATE; // 1 frame mInfo.presentationDeadlineNanos = 1000000000L / (int) getRefreshRate(); // 1 frame mInfo.flags = 0; if ((mFlags & VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) { mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE Loading Loading @@ -554,6 +557,10 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } return mInfo; } private float getRefreshRate() { return (mRequestedRefreshRate != 0.0f) ? mRequestedRefreshRate : REFRESH_RATE; } } private static class Callback extends Handler { Loading Loading @@ -632,6 +639,19 @@ public class VirtualDisplayAdapter extends DisplayAdapter { @VisibleForTesting public interface SurfaceControlDisplayFactory { public IBinder createDisplay(String name, boolean secure); /** * Create a virtual display in SurfaceFlinger. * * @param name The name of the display * @param secure Whether this display is secure. * @param requestedRefreshRate * The refresh rate, frames per second, to request on the virtual display. * It should be a divisor of refresh rate of the leader physical display * that drives VSYNC, e.g. 30/60fps on 120fps display. If an arbitrary refresh * rate is specified, SurfaceFlinger rounds up or down to match a divisor of * the refresh rate of the leader physical display. * @return The token reference for the display in SurfaceFlinger. */ IBinder createDisplay(String name, boolean secure, float requestedRefreshRate); } } Loading
core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -19321,7 +19321,9 @@ package android.hardware.display { public final class DisplayManager { method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int); method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int); method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler); method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int, @Nullable android.os.Handler, @Nullable android.hardware.display.VirtualDisplay.Callback); method public android.view.Display getDisplay(int); method public android.view.Display[] getDisplays(); method public android.view.Display[] getDisplays(String);
core/java/android/hardware/display/DisplayManager.java +89 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import java.util.concurrent.Executor; public final class DisplayManager { private static final String TAG = "DisplayManager"; private static final boolean DEBUG = false; private static final boolean ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE = false; private final Context mContext; private final DisplayManagerGlobal mGlobal; Loading Loading @@ -936,6 +937,24 @@ public final class DisplayManager { return createVirtualDisplay(name, width, height, densityDpi, surface, flags, null, null); } /** * Creates a virtual display. * * @see #createVirtualDisplay(String, int, int, int, float, Surface, int, * Handler, VirtualDisplay.Callback) */ @Nullable public VirtualDisplay createVirtualDisplay(@NonNull String name, @IntRange(from = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi, float requestedRefreshRate, @Nullable Surface surface, @VirtualDisplayFlag int flags) { return createVirtualDisplay(name, width, height, densityDpi, requestedRefreshRate, surface, flags, null, null); } /** * Creates a virtual display. * <p> Loading Loading @@ -987,12 +1006,82 @@ public final class DisplayManager { @VirtualDisplayFlag int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) { return createVirtualDisplay(name, width, height, densityDpi, 0.0f, surface, flags, handler, callback); } /** * Creates a virtual display. * <p> * The content of a virtual display is rendered to a {@link Surface} provided * by the application. * </p><p> * The virtual display should be {@link VirtualDisplay#release released} * when no longer needed. Because a virtual display renders to a surface * provided by the application, it will be released automatically when the * process terminates and all remaining windows on it will be forcibly removed. * </p><p> * The behavior of the virtual display depends on the flags that are provided * to this method. By default, virtual displays are created to be private, * non-presentation and unsecure. Permissions may be required to use certain flags. * </p><p> * As of {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}, the surface may * be attached or detached dynamically using {@link VirtualDisplay#setSurface}. * Previously, the surface had to be non-null when {@link #createVirtualDisplay} * was called and could not be changed for the lifetime of the display. * </p><p> * Detaching the surface that backs a virtual display has a similar effect to * turning off the screen. * </p> * * @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. * @param requestedRefreshRate The requested refresh rate in frames per second. * For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on * 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded * up or down to a divisor of the physical display. If 0 is specified, the virtual * display is refreshed at the physical display refresh rate. * @param surface The surface to which the content of the virtual display should * be rendered, or null if there is none initially. * @param flags A combination of virtual display flags: * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION}, * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}, * or {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}. * @param handler The handler on which the listener should be invoked, or null * if the listener should be invoked on the calling thread's looper. * @param callback Callback to call when the state of the {@link VirtualDisplay} changes * @return The newly created virtual display, or null if the application could * not create the virtual display. * * @throws SecurityException if the caller does not have permission to create * a virtual display with the specified flags. */ @Nullable public VirtualDisplay createVirtualDisplay(@NonNull String name, @IntRange(from = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi, float requestedRefreshRate, @Nullable Surface surface, @VirtualDisplayFlag int flags, @Nullable Handler handler, @Nullable VirtualDisplay.Callback callback) { if (!ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE && requestedRefreshRate != 0.0f) { Slog.e(TAG, "Please turn on ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE to use the new api"); return null; } final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width, height, densityDpi); builder.setFlags(flags); if (surface != null) { builder.setSurface(surface); } if (requestedRefreshRate != 0.0f) { builder.setRequestedRefreshRate(requestedRefreshRate); } return createVirtualDisplay(null /* projection */, builder.build(), callback, handler, null /* windowContext */); } Loading
core/java/android/hardware/display/VirtualDisplayConfig.java +46 −6 Original line number Diff line number Diff line Loading @@ -109,6 +109,13 @@ public final class VirtualDisplayConfig implements Parcelable { @DataClass.PluralOf("displayCategory") @NonNull private List<String> mDisplayCategories = new ArrayList<>(); /** * The refresh rate of a virtual display in frames per second. * If this value is non-zero, this is the requested refresh rate to set. * If this value is zero, the system chooses a default refresh rate. */ private float mRequestedRefreshRate = 0.0f; // Code below generated by codegen v1.0.23. Loading @@ -135,7 +142,8 @@ public final class VirtualDisplayConfig implements Parcelable { @Nullable String uniqueId, int displayIdToMirror, boolean windowManagerMirroring, @NonNull List<String> displayCategories) { @NonNull List<String> displayCategories, float requestedRefreshRate) { this.mName = name; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mName); Loading @@ -161,6 +169,7 @@ public final class VirtualDisplayConfig implements Parcelable { this.mDisplayCategories = displayCategories; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mDisplayCategories); this.mRequestedRefreshRate = requestedRefreshRate; // onConstructed(); // You can define this method to get a callback } Loading Loading @@ -256,6 +265,16 @@ public final class VirtualDisplayConfig implements Parcelable { return mDisplayCategories; } /** * The refresh rate of a virtual display in frames per second. * If this value is none zero, this is the requested refresh rate to set. * If this value is zero, the system chooses a default refresh rate. */ @DataClass.Generated.Member public float getRequestedRefreshRate() { return mRequestedRefreshRate; } @Override @DataClass.Generated.Member public void writeToParcel(@NonNull Parcel dest, int flags) { Loading @@ -276,6 +295,7 @@ public final class VirtualDisplayConfig implements Parcelable { if (mUniqueId != null) dest.writeString(mUniqueId); dest.writeInt(mDisplayIdToMirror); dest.writeStringList(mDisplayCategories); dest.writeFloat(mRequestedRefreshRate); } @Override Loading @@ -301,6 +321,7 @@ public final class VirtualDisplayConfig implements Parcelable { int displayIdToMirror = in.readInt(); List<String> displayCategories = new ArrayList<>(); in.readStringList(displayCategories); float requestedRefreshRate = in.readFloat(); this.mName = name; com.android.internal.util.AnnotationValidations.validate( Loading @@ -327,6 +348,7 @@ public final class VirtualDisplayConfig implements Parcelable { this.mDisplayCategories = displayCategories; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mDisplayCategories); this.mRequestedRefreshRate = requestedRefreshRate; // onConstructed(); // You can define this method to get a callback } Loading Loading @@ -362,6 +384,7 @@ public final class VirtualDisplayConfig implements Parcelable { private int mDisplayIdToMirror; private boolean mWindowManagerMirroring; private @NonNull List<String> mDisplayCategories; private float mRequestedRefreshRate; private long mBuilderFieldsSet = 0L; Loading Loading @@ -528,10 +551,23 @@ public final class VirtualDisplayConfig implements Parcelable { return this; } /** * The refresh rate of a virtual display in frames per second. * If this value is none zero, this is the requested refresh rate to set. * If this value is zero, the system chooses a default refresh rate. */ @DataClass.Generated.Member public @NonNull Builder setRequestedRefreshRate(float value) { checkNotUsed(); mBuilderFieldsSet |= 0x400; mRequestedRefreshRate = value; return this; } /** Builds the instance. This builder should not be touched after calling this! */ public @NonNull VirtualDisplayConfig build() { checkNotUsed(); mBuilderFieldsSet |= 0x400; // Mark builder used mBuilderFieldsSet |= 0x800; // Mark builder used if ((mBuilderFieldsSet & 0x10) == 0) { mFlags = 0; Loading @@ -551,6 +587,9 @@ public final class VirtualDisplayConfig implements Parcelable { if ((mBuilderFieldsSet & 0x200) == 0) { mDisplayCategories = new ArrayList<>(); } if ((mBuilderFieldsSet & 0x400) == 0) { mRequestedRefreshRate = 0.0f; } VirtualDisplayConfig o = new VirtualDisplayConfig( mName, mWidth, Loading @@ -561,12 +600,13 @@ public final class VirtualDisplayConfig implements Parcelable { mUniqueId, mDisplayIdToMirror, mWindowManagerMirroring, mDisplayCategories); mDisplayCategories, mRequestedRefreshRate); return o; } private void checkNotUsed() { if ((mBuilderFieldsSet & 0x400) != 0) { if ((mBuilderFieldsSet & 0x800) != 0) { throw new IllegalStateException( "This Builder should not be reused. Use a new Builder instance instead"); } Loading @@ -574,10 +614,10 @@ public final class VirtualDisplayConfig implements Parcelable { } @DataClass.Generated( time = 1668534501320L, time = 1671047069703L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java", inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nprivate boolean mWindowManagerMirroring\nprivate @com.android.internal.util.DataClass.PluralOf(\"displayCategory\") @android.annotation.NonNull java.util.List<java.lang.String> mDisplayCategories\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)") inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nprivate boolean mWindowManagerMirroring\nprivate @com.android.internal.util.DataClass.PluralOf(\"displayCategory\") @android.annotation.NonNull java.util.List<java.lang.String> mDisplayCategories\nprivate float mRequestedRefreshRate\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() {} Loading
services/core/java/com/android/server/display/DisplayControl.java +21 −2 Original line number Diff line number Diff line Loading @@ -28,7 +28,8 @@ import java.util.Objects; * Calls into SurfaceFlinger for Display creation and deletion. */ public class DisplayControl { private static native IBinder nativeCreateDisplay(String name, boolean secure); private static native IBinder nativeCreateDisplay(String name, boolean secure, float requestedRefreshRate); private static native void nativeDestroyDisplay(IBinder displayToken); private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes); private static native long[] nativeGetPhysicalDisplayIds(); Loading @@ -46,7 +47,25 @@ public class DisplayControl { */ public static IBinder createDisplay(String name, boolean secure) { Objects.requireNonNull(name, "name must not be null"); return nativeCreateDisplay(name, secure); return nativeCreateDisplay(name, secure, 0.0f); } /** * Create a display in SurfaceFlinger. * * @param name The name of the display * @param secure Whether this display is secure. * @param requestedRefreshRate The requested refresh rate in frames per second. * For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on * 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded * up or down to a divisor of the physical display. If 0 is specified, the virtual * display is refreshed at the physical display refresh rate. * @return The token reference for the display in SurfaceFlinger. */ public static IBinder createDisplay(String name, boolean secure, float requestedRefreshRate) { Objects.requireNonNull(name, "name must not be null"); return nativeCreateDisplay(name, secure, requestedRefreshRate); } /** Loading
services/core/java/com/android/server/display/VirtualDisplayAdapter.java +26 −6 Original line number Diff line number Diff line Loading @@ -106,7 +106,8 @@ public class VirtualDisplayAdapter extends DisplayAdapter { String name = virtualDisplayConfig.getName(); boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0; IBinder appToken = callback.asBinder(); IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure); IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure, virtualDisplayConfig.getRequestedRefreshRate()); final String baseUniqueId = UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ","; final int uniqueIndex = getNextUniqueIndex(baseUniqueId); Loading Loading @@ -247,6 +248,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { private int mWidth; private int mHeight; private int mDensityDpi; private float mRequestedRefreshRate; private Surface mSurface; private DisplayDeviceInfo mInfo; private int mDisplayState; Loading @@ -270,8 +272,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { mName = virtualDisplayConfig.getName(); mWidth = virtualDisplayConfig.getWidth(); mHeight = virtualDisplayConfig.getHeight(); mMode = createMode(mWidth, mHeight, REFRESH_RATE); mDensityDpi = virtualDisplayConfig.getDensityDpi(); mRequestedRefreshRate = virtualDisplayConfig.getRequestedRefreshRate(); mMode = createMode(mWidth, mHeight, getRefreshRate()); mSurface = surface; mFlags = flags; mCallback = callback; Loading Loading @@ -410,7 +413,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { sendTraversalRequestLocked(); mWidth = width; mHeight = height; mMode = createMode(width, height, REFRESH_RATE); mMode = createMode(width, height, getRefreshRate()); mDensityDpi = densityDpi; mInfo = null; mPendingChanges |= PENDING_RESIZE; Loading Loading @@ -438,9 +441,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { pw.println("mStopped=" + mStopped); pw.println("mDisplayIdToMirror=" + mDisplayIdToMirror); pw.println("mWindowManagerMirroring=" + mIsWindowManagerMirroring); pw.println("mRequestedRefreshRate=" + mRequestedRefreshRate); } @Override public DisplayDeviceInfo getDisplayDeviceInfoLocked() { if (mInfo == null) { Loading @@ -456,7 +459,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { mInfo.densityDpi = mDensityDpi; mInfo.xDpi = mDensityDpi; mInfo.yDpi = mDensityDpi; mInfo.presentationDeadlineNanos = 1000000000L / (int) REFRESH_RATE; // 1 frame mInfo.presentationDeadlineNanos = 1000000000L / (int) getRefreshRate(); // 1 frame mInfo.flags = 0; if ((mFlags & VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) { mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE Loading Loading @@ -554,6 +557,10 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } return mInfo; } private float getRefreshRate() { return (mRequestedRefreshRate != 0.0f) ? mRequestedRefreshRate : REFRESH_RATE; } } private static class Callback extends Handler { Loading Loading @@ -632,6 +639,19 @@ public class VirtualDisplayAdapter extends DisplayAdapter { @VisibleForTesting public interface SurfaceControlDisplayFactory { public IBinder createDisplay(String name, boolean secure); /** * Create a virtual display in SurfaceFlinger. * * @param name The name of the display * @param secure Whether this display is secure. * @param requestedRefreshRate * The refresh rate, frames per second, to request on the virtual display. * It should be a divisor of refresh rate of the leader physical display * that drives VSYNC, e.g. 30/60fps on 120fps display. If an arbitrary refresh * rate is specified, SurfaceFlinger rounds up or down to match a divisor of * the refresh rate of the leader physical display. * @return The token reference for the display in SurfaceFlinger. */ IBinder createDisplay(String name, boolean secure, float requestedRefreshRate); } }