Loading core/java/android/view/DisplayEventReceiver.java +29 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading Loading @@ -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) { Loading core/jni/android_view_DisplayEventReceiver.cpp +46 −15 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ static struct { jmethodID dispatchHotplug; jmethodID dispatchHotplugConnectionError; jmethodID dispatchModeChanged; jmethodID dispatchModeChangedWithFrameRateOverrides; jmethodID dispatchModeRejected; jmethodID dispatchFrameRateOverrides; jmethodID dispatchHdcpLevelsChanged; Loading Loading @@ -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: Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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); Loading Loading @@ -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"); Loading services/core/java/com/android/server/display/LocalDisplayAdapter.java +26 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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) { Loading Loading @@ -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) { Loading services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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 { Loading Loading
core/java/android/view/DisplayEventReceiver.java +29 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading Loading @@ -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) { Loading
core/jni/android_view_DisplayEventReceiver.cpp +46 −15 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ static struct { jmethodID dispatchHotplug; jmethodID dispatchHotplugConnectionError; jmethodID dispatchModeChanged; jmethodID dispatchModeChangedWithFrameRateOverrides; jmethodID dispatchModeRejected; jmethodID dispatchFrameRateOverrides; jmethodID dispatchHdcpLevelsChanged; Loading Loading @@ -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: Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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); Loading Loading @@ -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"); Loading
services/core/java/com/android/server/display/LocalDisplayAdapter.java +26 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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) { Loading Loading @@ -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) { Loading
services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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 { Loading