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

Commit 4e4f8c2b authored by Ram Indani's avatar Ram Indani Committed by Android (Google) Code Review
Browse files

Merge "[DM] Unify onModeChanged and frameRateOverride callbacks." into main

parents 93e625b0 9ad1fb49
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -297,6 +297,26 @@ public abstract class DisplayEventReceiver {
            long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos) {
    }

    /**
     * Called when a display mode and frame rate overrides changed event is received.
     *
     * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
     * timebase.
     * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
     * @param modeId The new mode ID
     * @param renderPeriod The render frame period, which is a multiple of the mode's vsync period
     * @param appVsyncOffsetNanos The offset from the vsync of the display refresh rate.
     * @param presentationDeadlineNanos The time in nanoseconds by which the frame should be ready
     *                             from the target vsync, if target vsync is N then the frame
     *                             should be ready by N - presentationDeadlineNanos.
     * @param overrides The mappings from uid to frame rates
     */
    public void onModeAndFrameRateOverridesChanged(long timestampNanos,
            long physicalDisplayId,  int modeId,  long renderPeriod,
            long appVsyncOffsetNanos,
            long presentationDeadlineNanos, FrameRateOverride[] overrides) {
    }

    /**
     * Called when a display mode rejection event is received.
     *
@@ -398,6 +418,15 @@ public abstract class DisplayEventReceiver {
                appVsyncOffsetNanos, presentationDeadlineNanos);
    }

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchModeChangedWithFrameRateOverrides(long timestampNanos,
            long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos,
            long presentationDeadlineNanos, FrameRateOverride[] overrides) {
        onModeAndFrameRateOverridesChanged(timestampNanos, physicalDisplayId, modeId,
                renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides);
    }

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchModeRejected(long physicalDisplayId, int modeId) {
+46 −15
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ static struct {
    jmethodID dispatchHotplug;
    jmethodID dispatchHotplugConnectionError;
    jmethodID dispatchModeChanged;
    jmethodID dispatchModeChangedWithFrameRateOverrides;
    jmethodID dispatchModeRejected;
    jmethodID dispatchFrameRateOverrides;
    jmethodID dispatchHdcpLevelsChanged;
@@ -74,6 +75,22 @@ static struct {

} gDisplayEventReceiverClassInfo;

jobjectArray getFrameRateOverrides(std::vector<FrameRateOverride> overrides, JNIEnv* env) {
    const auto frameRateOverrideClass =
            gDisplayEventReceiverClassInfo.frameRateOverrideClassInfo.clazz;
    const auto frameRateOverrideInit =
            gDisplayEventReceiverClassInfo.frameRateOverrideClassInfo.init;
    auto frameRateOverrideInitObject =
            env->NewObject(frameRateOverrideClass, frameRateOverrideInit, 0, 0);
    auto frameRateOverrideArray = env->NewObjectArray(overrides.size(), frameRateOverrideClass,
                                                      frameRateOverrideInitObject);
    for (size_t i = 0; i < overrides.size(); i++) {
        auto FrameRateOverrideObject = env->NewObject(frameRateOverrideClass, frameRateOverrideInit,
                                                      overrides[i].uid, overrides[i].frameRateHz);
        env->SetObjectArrayElement(frameRateOverrideArray, i, FrameRateOverrideObject);
    }
    return frameRateOverrideArray;
}

class NativeDisplayEventReceiver : public DisplayEventDispatcher {
public:
@@ -95,6 +112,10 @@ private:
                       VsyncEventData vsyncEventData) override;
    void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
    void dispatchHotplugConnectionError(nsecs_t timestamp, int errorCode) override;
    void dispatchModeChangedWithFrameRateOverrides(
            nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t renderPeriod,
            nsecs_t appVsyncOffset, nsecs_t presentationDeadline,
            std::vector<FrameRateOverride> overrides) override;
    void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
                             nsecs_t renderPeriod, nsecs_t appVsyncOffset,
                             nsecs_t presentationDeadline) override;
@@ -278,6 +299,26 @@ void NativeDisplayEventReceiver::dispatchModeChanged(nsecs_t timestamp, Physical
    mMessageQueue->raiseAndClearException(env, "dispatchModeChanged");
}

void NativeDisplayEventReceiver::dispatchModeChangedWithFrameRateOverrides(
        nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t renderPeriod,
        nsecs_t appVsyncOffset, nsecs_t presentationDeadline,
        std::vector<FrameRateOverride> overrides) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
        ALOGV("receiver %p ~ Invoking modeWithFrameRateOverride changed handler.", this);
        auto frameRateOverrideArray = getFrameRateOverrides(overrides, env);
        env->CallVoidMethod(receiverObj.get(),
                            gDisplayEventReceiverClassInfo
                                    .dispatchModeChangedWithFrameRateOverrides,
                            timestamp, displayId.value, modeId, renderPeriod, appVsyncOffset,
                            presentationDeadline, frameRateOverrideArray);
        ALOGV("receiver %p ~ Returned from modeWithFrameRateOverride changed handler.", this);
    }

    mMessageQueue->raiseAndClearException(env, "dispatchModeChangedWithFrameRateOverrides");
}

void NativeDisplayEventReceiver::dispatchModeRejected(PhysicalDisplayId displayId, int32_t modeId) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();

@@ -299,21 +340,7 @@ void NativeDisplayEventReceiver::dispatchFrameRateOverrides(
    ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
        ALOGV("receiver %p ~ Invoking FrameRateOverride handler.", this);
        const auto frameRateOverrideClass =
                gDisplayEventReceiverClassInfo.frameRateOverrideClassInfo.clazz;
        const auto frameRateOverrideInit =
                gDisplayEventReceiverClassInfo.frameRateOverrideClassInfo.init;
        auto frameRateOverrideInitObject =
                env->NewObject(frameRateOverrideClass, frameRateOverrideInit, 0, 0);
        auto frameRateOverrideArray = env->NewObjectArray(overrides.size(), frameRateOverrideClass,
                                                          frameRateOverrideInitObject);
        for (size_t i = 0; i < overrides.size(); i++) {
            auto FrameRateOverrideObject =
                    env->NewObject(frameRateOverrideClass, frameRateOverrideInit, overrides[i].uid,
                                   overrides[i].frameRateHz);
            env->SetObjectArrayElement(frameRateOverrideArray, i, FrameRateOverrideObject);
        }

        auto frameRateOverrideArray = getFrameRateOverrides(overrides, env);
        env->CallVoidMethod(receiverObj.get(),
                            gDisplayEventReceiverClassInfo.dispatchFrameRateOverrides, timestamp,
                            displayId.value, frameRateOverrideArray);
@@ -426,6 +453,10 @@ int register_android_view_DisplayEventReceiver(JNIEnv* env) {
    gDisplayEventReceiverClassInfo.dispatchModeChanged =
            GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchModeChanged",
                             "(JJIJJJ)V");
    gDisplayEventReceiverClassInfo.dispatchModeChangedWithFrameRateOverrides =
            GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz,
                             "dispatchModeChangedWithFrameRateOverrides",
                             "(JJIJJJ[Landroid/view/DisplayEventReceiver$FrameRateOverride;)V");
    gDisplayEventReceiverClassInfo.dispatchModeRejected =
            GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchModeRejected",
                             "(JI)V");
+26 −0
Original line number Diff line number Diff line
@@ -1616,6 +1616,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos);
        void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
                DisplayEventReceiver.FrameRateOverride[] overrides);
        void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
                int modeId,  long renderPeriod, long appVsyncOffsetNanos,
                long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides);
        void onHdcpLevelsChanged(long physicalDisplayId, int connectedLevel, int maxLevel);

    }
@@ -1646,6 +1649,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                    renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos);
        }

        public void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
                int modeId,  long renderPeriod, long appVsyncOffsetNanos,
                long presentationDeadlineNanos,
                DisplayEventReceiver.FrameRateOverride[] overrides) {
            mListener.onModeAndFrameRateOverridesChanged(timestampNanos, physicalDisplayId, modeId,
                    renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides);
        }

        @Override
        public void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
                DisplayEventReceiver.FrameRateOverride[] overrides) {
@@ -1729,6 +1740,21 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            }
        }

        @Override
        public void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
                int modeId, long renderPeriod, long appVsyncOffsetNanos,
                long presentationDeadlineNanos,
                DisplayEventReceiver.FrameRateOverride[] overrides) {
            if (DEBUG) {
                Slog.d(TAG, "onModeAndFrameRateOverridesChanged");
            }
            //TODO(b/415850294) App should not get two callbacks when
            // onModeAndFrameRateOverridesChanged is executed.
            onModeChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod,
                    appVsyncOffsetNanos, presentationDeadlineNanos);
            onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides);
        }

        @Override
        public void onHdcpLevelsChanged(long physicalDisplayId, int connectedLevel, int maxLevel) {
            if (DEBUG) {
+62 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.display;

import static android.hardware.display.DeviceProductInfo.CONNECTION_TO_SINK_DIRECT;
import static android.view.DisplayEventReceiver.FrameRateOverride;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
@@ -939,6 +940,56 @@ public class LocalDisplayAdapterTest {
        assertThat(mListener.changedDisplays.size()).isEqualTo(1);
    }

    @Test
    public void testOnModeAndFrameRateOverridesChanged() throws Exception {
        doReturn(true).when(mFlags).isDispatchDisplayModeWithVsyncOffsetsEnabled();
        long appVsyncOffsetNanosMode1 = 100;
        long presentationDeadlineNanosMode1 = 200;
        long appVsyncOffsetNanosMode2 = 101;
        long presentationDeadlineNanosMode2 = 201;
        SurfaceControl.DisplayMode displayMode1 = createFakeDisplayMode(0, 1920, 1080, 60f,
                appVsyncOffsetNanosMode1, presentationDeadlineNanosMode1);
        SurfaceControl.DisplayMode displayMode2 = createFakeDisplayMode(1, 1920, 1080, 120f,
                appVsyncOffsetNanosMode2, presentationDeadlineNanosMode2);
        SurfaceControl.DisplayMode[] modes =
                new SurfaceControl.DisplayMode[]{displayMode1, displayMode2};
        FakeDisplay display = new FakeDisplay(PORT_A, modes, /*activeMode*/ 0,
                displayMode1.peakRefreshRate);
        setUpDisplay(display);
        updateAvailableDisplays();
        mAdapter.registerLocked();
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
        assertThat(mListener.changedDisplays).isEmpty();

        DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get(
                0).getDisplayDeviceInfoLocked();
        assertEquals(appVsyncOffsetNanosMode1, displayDeviceInfo.appVsyncOffsetNanos);
        assertEquals(presentationDeadlineNanosMode1, displayDeviceInfo.presentationDeadlineNanos);
        Display.Mode activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
        assertThat(activeMode.matches(1920, 1080, 60f)).isTrue();

        long newAppVsyncOffsetNanos = 400;
        long newPresentationDeadlineNanos = 500;

        FrameRateOverride[] frameRateOverrides = new FrameRateOverride[1];
        mInjector.getTransmitter().sendOnModeAndFrameRateOverridesChanged(display,
                /*modeId*/ 1, (long) displayMode2.peakRefreshRate, newAppVsyncOffsetNanos,
                newPresentationDeadlineNanos, frameRateOverrides);
        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        assertTrue(mListener.traversalRequested);

        DisplayDevice displayDevice = mListener.changedDisplays.get(0);
        displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
        displayDeviceInfo = mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked();
        // Returns the values captured from the OnModeAndFrameRateOverridesChanged event.
        assertEquals(newAppVsyncOffsetNanos, displayDeviceInfo.appVsyncOffsetNanos);
        assertEquals(newPresentationDeadlineNanos, displayDeviceInfo.presentationDeadlineNanos);
        assertThat(mListener.changedDisplays.size()).isEqualTo(2);
        activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
        assertThat(activeMode.matches(1920, 1080, 120f)).isTrue();
    }

    @Test
    public void testAfterDisplayChange_HdrCapabilitiesAreUpdated() throws Exception {
        FakeDisplay display = new FakeDisplay(PORT_A);
@@ -1928,6 +1979,17 @@ public class LocalDisplayAdapterTest {
                    appVsyncOffsetNanos, presentationDeadlineNanos));
            waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        }

        public void sendOnModeAndFrameRateOverridesChanged(FakeDisplay display, int modeId,
                long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos,
                FrameRateOverride[] frameRateOverrides) throws InterruptedException {

            mHandler.post(() -> mListener.onModeAndFrameRateOverridesChanged(
                    /* timestampNanos = */ 0, display.address.getPhysicalDisplayId(), modeId,
                    renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos,
                    frameRateOverrides));
            waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
        }
    }

    private class Injector extends LocalDisplayAdapter.Injector {