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

Commit 92c974c6 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Pass never-blank state from VirtualDisplayAdapter to SurfaceFlinger." into main

parents b078f585 b989023e
Loading
Loading
Loading
Loading
+9 −4
Original line number Original line Diff line number Diff line
@@ -29,7 +29,7 @@ import java.util.Objects;
 */
 */
public class DisplayControl {
public class DisplayControl {
    private static native IBinder nativeCreateVirtualDisplay(String name, boolean secure,
    private static native IBinder nativeCreateVirtualDisplay(String name, boolean secure,
            String uniqueId, float requestedRefreshRate);
            boolean optimizeForPower, String uniqueId, float requestedRefreshRate);
    private static native void nativeDestroyVirtualDisplay(IBinder displayToken);
    private static native void nativeDestroyVirtualDisplay(IBinder displayToken);
    private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes);
    private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes);
    private static native long[] nativeGetPhysicalDisplayIds();
    private static native long[] nativeGetPhysicalDisplayIds();
@@ -49,7 +49,7 @@ public class DisplayControl {
     */
     */
    public static IBinder createVirtualDisplay(String name, boolean secure) {
    public static IBinder createVirtualDisplay(String name, boolean secure) {
        Objects.requireNonNull(name, "name must not be null");
        Objects.requireNonNull(name, "name must not be null");
        return nativeCreateVirtualDisplay(name, secure, "", 0.0f);
        return nativeCreateVirtualDisplay(name, secure, true, "", 0.0f);
    }
    }


    /**
    /**
@@ -57,6 +57,10 @@ public class DisplayControl {
     *
     *
     * @param name The name of the virtual display.
     * @param name The name of the virtual display.
     * @param secure Whether this display is secure.
     * @param secure Whether this display is secure.
     * @param optimizeForPower Whether SurfaceFlinger should optimize for power (instead of
     *                         performance). Such displays will depend on another display for it to
     *                         be shown and rendered, and that display will optimize for
     *                         performance when it is on.
     * @param uniqueId The unique ID for the display.
     * @param uniqueId The unique ID for the display.
     * @param requestedRefreshRate The requested refresh rate in frames per second.
     * @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
     * For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on
@@ -66,10 +70,11 @@ public class DisplayControl {
     * @return The token reference for the display in SurfaceFlinger.
     * @return The token reference for the display in SurfaceFlinger.
     */
     */
    public static IBinder createVirtualDisplay(String name, boolean secure,
    public static IBinder createVirtualDisplay(String name, boolean secure,
            String uniqueId, float requestedRefreshRate) {
            boolean optimizeForPower, String uniqueId, float requestedRefreshRate) {
        Objects.requireNonNull(name, "name must not be null");
        Objects.requireNonNull(name, "name must not be null");
        Objects.requireNonNull(uniqueId, "uniqueId must not be null");
        Objects.requireNonNull(uniqueId, "uniqueId must not be null");
        return nativeCreateVirtualDisplay(name, secure, uniqueId, requestedRefreshRate);
        return nativeCreateVirtualDisplay(name, secure, optimizeForPower, uniqueId,
                requestedRefreshRate);
    }
    }


    /**
    /**
+23 −11
Original line number Original line Diff line number Diff line
@@ -103,9 +103,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
            Context context, Handler handler, Listener listener, DisplayManagerFlags featureFlags) {
            Context context, Handler handler, Listener listener, DisplayManagerFlags featureFlags) {
        this(syncRoot, context, handler, listener, new SurfaceControlDisplayFactory() {
        this(syncRoot, context, handler, listener, new SurfaceControlDisplayFactory() {
            @Override
            @Override
            public IBinder createDisplay(String name, boolean secure, String uniqueId,
            public IBinder createDisplay(String name, boolean secure, boolean optimizeForPower,
                                         float requestedRefreshRate) {
                    String uniqueId, float requestedRefreshRate) {
                return DisplayControl.createVirtualDisplay(name, secure, uniqueId,
                return DisplayControl.createVirtualDisplay(name, secure, optimizeForPower, uniqueId,
                        requestedRefreshRate);
                        requestedRefreshRate);
            }
            }


@@ -182,9 +182,13 @@ public class VirtualDisplayAdapter extends DisplayAdapter {


        String name = virtualDisplayConfig.getName();
        String name = virtualDisplayConfig.getName();
        boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
        boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
        boolean neverBlank = isNeverBlank(flags);


        IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure, uniqueId,
        // Never-blank displays are considered to be dependent on another display to be rendered.
                virtualDisplayConfig.getRequestedRefreshRate());
        // As a result, such displays should optimize for power instead of performance when it is
        // powered on.
        IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure, neverBlank,
                uniqueId, virtualDisplayConfig.getRequestedRefreshRate());
        MediaProjectionCallback mediaProjectionCallback =  null;
        MediaProjectionCallback mediaProjectionCallback =  null;
        if (projection != null) {
        if (projection != null) {
            mediaProjectionCallback = new MediaProjectionCallback(appToken);
            mediaProjectionCallback = new MediaProjectionCallback(appToken);
@@ -318,6 +322,12 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
        return mVirtualDisplayDevices.remove(appToken);
        return mVirtualDisplayDevices.remove(appToken);
    }
    }


    private static boolean isNeverBlank(int flags) {
        // Private non-mirror displays are never blank and always on.
        return (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) == 0
                && (flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0;
    }

    private final class VirtualDisplayDevice extends DisplayDevice implements DeathRecipient {
    private final class VirtualDisplayDevice extends DisplayDevice implements DeathRecipient {
        private static final int PENDING_SURFACE_CHANGE = 0x01;
        private static final int PENDING_SURFACE_CHANGE = 0x01;
        private static final int PENDING_RESIZE = 0x02;
        private static final int PENDING_RESIZE = 0x02;
@@ -377,9 +387,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
            mCallback = callback;
            mCallback = callback;
            mProjection = projection;
            mProjection = projection;
            mMediaProjectionCallback = mediaProjectionCallback;
            mMediaProjectionCallback = mediaProjectionCallback;
            // Private non-mirror displays are never blank and always on.
            mNeverBlank = isNeverBlank(flags);
            mNeverBlank = (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) == 0
                    && (flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0;
            if (android.companion.virtualdevice.flags.Flags.correctVirtualDisplayPowerState()
            if (android.companion.virtualdevice.flags.Flags.correctVirtualDisplayPowerState()
                    && !mNeverBlank) {
                    && !mNeverBlank) {
                // The display's power state depends on the power state of the state of its
                // The display's power state depends on the power state of the state of its
@@ -782,6 +790,10 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
         *
         *
         * @param name The name of the display.
         * @param name The name of the display.
         * @param secure Whether this display is secure.
         * @param secure Whether this display is secure.
         * @param optimizeForPower Whether SurfaceFlinger should optimize for power (instead of
         *                         performance). Such displays will depend on another display for
         *                         it to be shown and rendered, and that display will optimize for
         *                         performance when it is on.
         * @param uniqueId The unique ID for the display.
         * @param uniqueId The unique ID for the display.
         * @param requestedRefreshRate
         * @param requestedRefreshRate
         *     The refresh rate, frames per second, to request on the virtual display.
         *     The refresh rate, frames per second, to request on the virtual display.
@@ -791,8 +803,8 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
         *     the refresh rate of the leader physical display.
         *     the refresh rate of the leader physical display.
         * @return The token reference for the display in SurfaceFlinger.
         * @return The token reference for the display in SurfaceFlinger.
         */
         */
        IBinder createDisplay(String name, boolean secure, String uniqueId,
        IBinder createDisplay(String name, boolean secure, boolean optimizeForPower,
                              float requestedRefreshRate);
                String uniqueId, float requestedRefreshRate);


        /**
        /**
         * Destroy a display in SurfaceFlinger.
         * Destroy a display in SurfaceFlinger.
+4 −3
Original line number Original line Diff line number Diff line
@@ -24,12 +24,13 @@
namespace android {
namespace android {


static jobject nativeCreateVirtualDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
static jobject nativeCreateVirtualDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
                                          jboolean secure, jstring uniqueIdStr,
                                          jboolean secure, jboolean optimizeForPower,
                                          jfloat requestedRefreshRate) {
                                          jstring uniqueIdStr, jfloat requestedRefreshRate) {
    const ScopedUtfChars name(env, nameObj);
    const ScopedUtfChars name(env, nameObj);
    const ScopedUtfChars uniqueId(env, uniqueIdStr);
    const ScopedUtfChars uniqueId(env, uniqueIdStr);
    sp<IBinder> token(SurfaceComposerClient::createVirtualDisplay(std::string(name.c_str()),
    sp<IBinder> token(SurfaceComposerClient::createVirtualDisplay(std::string(name.c_str()),
                                                                  bool(secure),
                                                                  bool(secure),
                                                                  bool(optimizeForPower),
                                                                  std::string(uniqueId.c_str()),
                                                                  std::string(uniqueId.c_str()),
                                                                  requestedRefreshRate));
                                                                  requestedRefreshRate));
    return javaObjectForIBinder(env, token);
    return javaObjectForIBinder(env, token);
@@ -182,7 +183,7 @@ static jobject nativeGetPhysicalDisplayToken(JNIEnv* env, jclass clazz, jlong ph


static const JNINativeMethod sDisplayMethods[] = {
static const JNINativeMethod sDisplayMethods[] = {
        // clang-format off
        // clang-format off
    {"nativeCreateVirtualDisplay", "(Ljava/lang/String;ZLjava/lang/String;F)Landroid/os/IBinder;",
    {"nativeCreateVirtualDisplay", "(Ljava/lang/String;ZZLjava/lang/String;F)Landroid/os/IBinder;",
            (void*)nativeCreateVirtualDisplay },
            (void*)nativeCreateVirtualDisplay },
    {"nativeDestroyVirtualDisplay", "(Landroid/os/IBinder;)V",
    {"nativeDestroyVirtualDisplay", "(Landroid/os/IBinder;)V",
            (void*)nativeDestroyVirtualDisplay },
            (void*)nativeDestroyVirtualDisplay },
+2 −1
Original line number Original line Diff line number Diff line
@@ -324,7 +324,8 @@ public class DisplayManagerServiceTest {
            return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
            return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
                    new VirtualDisplayAdapter.SurfaceControlDisplayFactory() {
                    new VirtualDisplayAdapter.SurfaceControlDisplayFactory() {
                        @Override
                        @Override
                        public IBinder createDisplay(String name, boolean secure, String uniqueId,
                        public IBinder createDisplay(String name, boolean secure,
                                boolean optimizeForPower, String uniqueId,
                                float requestedRefreshRate) {
                                float requestedRefreshRate) {
                            return mMockDisplayToken;
                            return mMockDisplayToken;
                        }
                        }
+44 −1
Original line number Original line Diff line number Diff line
@@ -416,7 +416,7 @@ public class VirtualDisplayAdapterTest {
        final String uniqueId = "uniqueId";
        final String uniqueId = "uniqueId";
        final IBinder displayToken = new Binder();
        final IBinder displayToken = new Binder();
        when(mMockSufaceControlDisplayFactory.createDisplay(
        when(mMockSufaceControlDisplayFactory.createDisplay(
                any(), anyBoolean(), eq(uniqueId), anyFloat()))
                any(), anyBoolean(), anyBoolean(), eq(uniqueId), anyFloat()))
                .thenReturn(displayToken);
                .thenReturn(displayToken);


        // The display needs to be public, otherwise it will be considered never blank.
        // The display needs to be public, otherwise it will be considered never blank.
@@ -456,6 +456,49 @@ public class VirtualDisplayAdapterTest {
        verify(mMockCallback).onPaused();
        verify(mMockCallback).onPaused();
    }
    }


    @EnableFlags(
            android.companion.virtualdevice.flags.Flags.FLAG_CORRECT_VIRTUAL_DISPLAY_POWER_STATE)
    @Test
    public void createVirtualDisplayLocked_neverBlank_optimizesForPower() {
        final String uniqueId = "uniqueId";
        final IBinder displayToken = new Binder();
        final String name = "name";
        when(mVirtualDisplayConfigMock.getName()).thenReturn(name);
        when(mMockSufaceControlDisplayFactory.createDisplay(
                any(), anyBoolean(), anyBoolean(), eq(uniqueId), anyFloat()))
                .thenReturn(displayToken);

        // Use a private display to cause the display to be never blank.
        mAdapter.createVirtualDisplayLocked(mMockCallback,
                /* projection= */ null, /* ownerUid= */ 10, /* packageName= */ "testpackage",
                uniqueId, /* surface= */ mSurfaceMock, 0, mVirtualDisplayConfigMock);

        verify(mMockSufaceControlDisplayFactory).createDisplay(eq(name), eq(false), eq(true),
                eq(uniqueId), anyFloat());
    }

    @EnableFlags(
            android.companion.virtualdevice.flags.Flags.FLAG_CORRECT_VIRTUAL_DISPLAY_POWER_STATE)
    @Test
    public void createVirtualDisplayLocked_blankable_optimizesForPerformance() {
        final String uniqueId = "uniqueId";
        final IBinder displayToken = new Binder();
        final String name = "name";
        when(mVirtualDisplayConfigMock.getName()).thenReturn(name);
        when(mMockSufaceControlDisplayFactory.createDisplay(
                any(), anyBoolean(), anyBoolean(), eq(uniqueId), anyFloat()))
                .thenReturn(displayToken);

        // Use a public display to cause the display to be blankable
        mAdapter.createVirtualDisplayLocked(mMockCallback,
                /* projection= */ null, /* ownerUid= */ 10, /* packageName= */ "testpackage",
                uniqueId, /* surface= */ mSurfaceMock, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
                mVirtualDisplayConfigMock);

        verify(mMockSufaceControlDisplayFactory).createDisplay(eq(name), eq(false), eq(false),
                eq(uniqueId), anyFloat());
    }

    private IVirtualDisplayCallback createCallback() {
    private IVirtualDisplayCallback createCallback() {
        return new IVirtualDisplayCallback.Stub() {
        return new IVirtualDisplayCallback.Stub() {