Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9315989a authored by Huihong Luo's avatar Huihong Luo Committed by Android (Google) Code Review
Browse files

Merge "Variable refresh rate for virtual display"

parents 9af18e83 6c57176e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+89 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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>
@@ -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 */);
    }
+46 −6
Original line number Diff line number Diff line
@@ -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.
@@ -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);
@@ -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
    }
@@ -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) {
@@ -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
@@ -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(
@@ -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
    }
@@ -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;

@@ -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;
@@ -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,
@@ -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");
            }
@@ -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() {}

+21 −2
Original line number Diff line number Diff line
@@ -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();
@@ -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);
    }

    /**
+26 −6
Original line number Diff line number Diff line
@@ -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);
@@ -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;
@@ -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;
@@ -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;
@@ -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) {
@@ -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
@@ -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 {
@@ -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