Loading core/java/android/view/DisplayEventReceiver.java +7 −3 Original line number Diff line number Diff line Loading @@ -321,11 +321,13 @@ public abstract class DisplayEventReceiver { * 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 * @param supportedRefreshRates The list of refresh rates supported on the display */ public void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, FrameRateOverride[] overrides) { long presentationDeadlineNanos, FrameRateOverride[] overrides, float[] supportedRefreshRates) { } /** Loading Loading @@ -433,9 +435,11 @@ public abstract class DisplayEventReceiver { @SuppressWarnings("unused") private void dispatchModeChangedWithFrameRateOverrides(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, FrameRateOverride[] overrides) { long presentationDeadlineNanos, FrameRateOverride[] overrides, float[] supportedRefreshRates) { onModeAndFrameRateOverridesChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides); renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides, supportedRefreshRates); } // Called from native code. Loading core/jni/android_view_DisplayEventReceiver.cpp +19 −4 Original line number Diff line number Diff line Loading @@ -92,6 +92,18 @@ jobjectArray getFrameRateOverrides(std::vector<FrameRateOverride> overrides, JNI return frameRateOverrideArray; } jfloatArray getSupportedRefreshRates(std::vector<SupportedRefreshRate> supportedRefreshRates, JNIEnv* env) { jfloatArray floatArray = env->NewFloatArray(supportedRefreshRates.size()); std::vector<jfloat> refreshRates(supportedRefreshRates.size()); for (size_t i = 0; i < supportedRefreshRates.size(); i++) { refreshRates[i] = supportedRefreshRates[i].refreshRate; } env->SetFloatArrayRegion(floatArray, 0, supportedRefreshRates.size(), refreshRates.data()); return floatArray; } class NativeDisplayEventReceiver : public DisplayEventDispatcher { public: NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak, jobject vsyncEventDataWeak, Loading @@ -115,7 +127,8 @@ private: void dispatchModeChangedWithFrameRateOverrides( nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t renderPeriod, nsecs_t appVsyncOffset, nsecs_t presentationDeadline, std::vector<FrameRateOverride> overrides) override; std::vector<FrameRateOverride> overrides, std::vector<SupportedRefreshRate> supportedRefreshRates) override; void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t renderPeriod, nsecs_t appVsyncOffset, nsecs_t presentationDeadline) override; Loading Loading @@ -302,17 +315,19 @@ void NativeDisplayEventReceiver::dispatchModeChanged(nsecs_t timestamp, Physical void NativeDisplayEventReceiver::dispatchModeChangedWithFrameRateOverrides( nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t renderPeriod, nsecs_t appVsyncOffset, nsecs_t presentationDeadline, std::vector<FrameRateOverride> overrides) { std::vector<FrameRateOverride> overrides, std::vector<SupportedRefreshRate> refreshRates) { 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); auto supportedRefreshRateArray = getSupportedRefreshRates(refreshRates, env); env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo .dispatchModeChangedWithFrameRateOverrides, timestamp, displayId.value, modeId, renderPeriod, appVsyncOffset, presentationDeadline, frameRateOverrideArray); presentationDeadline, frameRateOverrideArray, supportedRefreshRateArray); ALOGV("receiver %p ~ Returned from modeWithFrameRateOverride changed handler.", this); } Loading Loading @@ -456,7 +471,7 @@ int register_android_view_DisplayEventReceiver(JNIEnv* env) { gDisplayEventReceiverClassInfo.dispatchModeChangedWithFrameRateOverrides = GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchModeChangedWithFrameRateOverrides", "(JJIJJJ[Landroid/view/DisplayEventReceiver$FrameRateOverride;)V"); "(JJIJJJ[Landroid/view/DisplayEventReceiver$FrameRateOverride;[F)V"); gDisplayEventReceiverClassInfo.dispatchModeRejected = GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchModeRejected", "(JI)V"); Loading services/core/java/com/android/server/display/LocalDisplayAdapter.java +61 −26 Original line number Diff line number Diff line Loading @@ -1242,18 +1242,26 @@ final class LocalDisplayAdapter extends DisplayAdapter { } private void onActiveDisplayModeChangedLocked(int sfModeId, float renderFrameRate, long appVsyncOffsetNanos, long presentationDeadlineNanos) { long appVsyncOffsetNanos, long presentationDeadlineNanos, @Nullable float[] supportedRefreshRates) { if (updateActiveModeAndFrameOverrideChangedLocked(sfModeId, renderFrameRate, appVsyncOffsetNanos, presentationDeadlineNanos, mFrameRateOverrides)) { appVsyncOffsetNanos, presentationDeadlineNanos, mFrameRateOverrides, supportedRefreshRates == null ? mSupportedRefreshRates : supportedRefreshRates)) { updateDeviceInfoLocked(); } } private void onFrameRateOverridesChangedLocked( DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, @Nullable float[] supportedRefreshRates) { if (updateActiveModeAndFrameOverrideChangedLocked(mActiveSfDisplayMode.id, mActiveRenderFrameRate, mAppVsyncOffsetNanos, mPresentationDeadlineNanos, overrides)) { overrides, supportedRefreshRates == null ? mSupportedRefreshRates : supportedRefreshRates)) { updateDeviceInfoLocked(); } } Loading @@ -1261,10 +1269,11 @@ final class LocalDisplayAdapter extends DisplayAdapter { private void onModeAndFrameRateOverridesChangedLocked( int sfModeId, float renderFrameRate, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates) { if (updateActiveModeAndFrameOverrideChangedLocked(sfModeId, renderFrameRate, appVsyncOffsetNanos, presentationDeadlineNanos, overrides)) { presentationDeadlineNanos, overrides, supportedRefreshRates)) { updateDeviceInfoLocked(); } } Loading @@ -1278,13 +1287,16 @@ final class LocalDisplayAdapter extends DisplayAdapter { private boolean updateActiveModeAndFrameOverrideChangedLocked(int activeSfModeId, float renderFrameRate, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates) { if (mActiveSfDisplayMode.id == activeSfModeId && mActiveRenderFrameRate == renderFrameRate && mAppVsyncOffsetNanos == appVsyncOffsetNanos && mPresentationDeadlineNanos == presentationDeadlineNanos && Arrays.equals(overrides, mFrameRateOverrides) ) { && (!com.android.graphics.surfaceflinger.flags.Flags.supportedRefreshRateUpdate() || Arrays.equals(supportedRefreshRates, mSupportedRefreshRates))) { return false; } mActiveSfDisplayMode = getModeById(mSfDisplayModes, activeSfModeId); Loading @@ -1297,6 +1309,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { mAppVsyncOffsetNanos = appVsyncOffsetNanos; mPresentationDeadlineNanos = presentationDeadlineNanos; mFrameRateOverrides = overrides; if (com.android.graphics.surfaceflinger.flags.Flags.supportedRefreshRateUpdate()) { mSupportedRefreshRates = supportedRefreshRates; } return true; } Loading Loading @@ -1626,12 +1641,15 @@ final class LocalDisplayAdapter extends DisplayAdapter { void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected); void onHotplugConnectionError(long timestampNanos, int connectionError); void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos); long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, @Nullable float[] supportedRefreshRates); void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, DisplayEventReceiver.FrameRateOverride[] overrides); DisplayEventReceiver.FrameRateOverride[] overrides, @Nullable float[] supportedRefreshRates); void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides); long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates); void onHdcpLevelsChanged(long physicalDisplayId, int connectedLevel, int maxLevel); } Loading Loading @@ -1660,21 +1678,25 @@ final class LocalDisplayAdapter extends DisplayAdapter { public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos) { mListener.onModeChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos); renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, /*supportedRefreshRates*/ null); } public void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates) { mListener.onModeAndFrameRateOverridesChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides); renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides, supportedRefreshRates); } @Override public void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, DisplayEventReceiver.FrameRateOverride[] overrides) { mListener.onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides); mListener.onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides, /*supportedRefreshRates*/ null); } @Override Loading Loading @@ -1708,7 +1730,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { @Override public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDealineNanos) { long renderPeriod, long appVsyncOffsetNanos, long presentationDealineNanos, @Nullable float[] supportedRefreshRates) { if (DEBUG) { Slog.d(TAG, "onModeChanged(" + "timestampNanos=" + timestampNanos Loading @@ -1716,7 +1739,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { + ", modeId=" + modeId + ", renderPeriod=" + renderPeriod + ", appVsyncOffsetNanos=" + appVsyncOffsetNanos + ", presentationDealineNanos=" + presentationDealineNanos + ")"); + ", presentationDealineNanos=" + presentationDealineNanos + ", supportedRefreshRates=" + Arrays.toString(supportedRefreshRates) + ")"); } synchronized (getSyncRoot()) { LocalDisplayDevice device = mDevices.get(physicalDisplayId); Loading @@ -1729,17 +1754,21 @@ final class LocalDisplayAdapter extends DisplayAdapter { } float renderFrameRate = 1e9f / renderPeriod; device.onActiveDisplayModeChangedLocked(modeId, renderFrameRate, appVsyncOffsetNanos, presentationDealineNanos); appVsyncOffsetNanos, presentationDealineNanos, supportedRefreshRates); } } @Override public void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, @Nullable float[] supportedRefreshRates) { if (DEBUG) { Slog.d(TAG, "onFrameRateOverrideChanged(timestampNanos=" + timestampNanos + ", physicalDisplayId=" + physicalDisplayId + " overrides=" + Arrays.toString(overrides) + ")"); + Arrays.toString(overrides) + ", supportedRefreshRates=" + Arrays.toString(supportedRefreshRates) + ")"); } synchronized (getSyncRoot()) { LocalDisplayDevice device = mDevices.get(physicalDisplayId); Loading @@ -1750,7 +1779,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { } return; } device.onFrameRateOverridesChangedLocked(overrides); device.onFrameRateOverridesChangedLocked(overrides, supportedRefreshRates); } } Loading @@ -1758,7 +1787,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { public void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates) { if (getFeatureFlags().isSingleAppEventForModeAndFrameRateOverrideEnabled()) { if (DEBUG) { Slog.d(TAG, "onModeAndFrameRateOverridesChanged(" Loading @@ -1768,7 +1798,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { + ", renderPeriod=" + renderPeriod + ", appVsyncOffsetNanos=" + appVsyncOffsetNanos + ", presentationDeadlineNanos=" + presentationDeadlineNanos + ", overrides=" + Arrays.toString(overrides) + ")"); + ", overrides=" + Arrays.toString(overrides) + ", supportedRefreshRates=" + Arrays.toString(supportedRefreshRates) + ")"); } synchronized (getSyncRoot()) { LocalDisplayDevice device = mDevices.get(physicalDisplayId); Loading @@ -1782,15 +1814,18 @@ final class LocalDisplayAdapter extends DisplayAdapter { } float renderFrameRate = 1e9f / renderPeriod; device.onModeAndFrameRateOverridesChangedLocked(modeId, renderFrameRate, appVsyncOffsetNanos, presentationDeadlineNanos, overrides); appVsyncOffsetNanos, presentationDeadlineNanos, overrides, supportedRefreshRates); } } else { if (DEBUG) { Slog.d(TAG, "onModeAndFrameRateOverridesChanged"); } onModeChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos); onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides); appVsyncOffsetNanos, presentationDeadlineNanos, supportedRefreshRates); onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides, supportedRefreshRates); } } Loading services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java +14 −4 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Spline; import android.view.Display; import android.view.DisplayAddress; Loading Loading @@ -78,6 +80,7 @@ import com.google.common.truth.Truth; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading Loading @@ -155,6 +158,9 @@ public class LocalDisplayAdapterTest { private static final List<Integer> mDisplayOffloadSupportedStates = new ArrayList<>(List.of(Display.STATE_DOZE_SUSPEND)); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Before public void setUp() throws Exception { mMockitoSession = mockitoSession() Loading Loading @@ -941,6 +947,7 @@ public class LocalDisplayAdapterTest { } @Test @EnableFlags(com.android.graphics.surfaceflinger.flags.Flags.FLAG_SUPPORTED_REFRESH_RATE_UPDATE) public void testOnModeAndFrameRateOverridesChanged() throws Exception { doReturn(true).when(mFlags).isDispatchDisplayModeWithVsyncOffsetsEnabled(); doReturn(true).when(mFlags).isSingleAppEventForModeAndFrameRateOverrideEnabled(); Loading Loading @@ -974,9 +981,10 @@ public class LocalDisplayAdapterTest { long newPresentationDeadlineNanos = 500; FrameRateOverride[] frameRateOverrides = new FrameRateOverride[1]; float[] supportedRefreshRates = {120.f, 60.f, 40.f, 30.f, 24.f, 20.f}; mInjector.getTransmitter().sendOnModeAndFrameRateOverridesChanged(display, /*modeId*/ 1, (long) displayMode2.peakRefreshRate, newAppVsyncOffsetNanos, newPresentationDeadlineNanos, frameRateOverrides); newPresentationDeadlineNanos, frameRateOverrides, supportedRefreshRates); waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); assertTrue(mListener.traversalRequested); Loading @@ -989,6 +997,7 @@ public class LocalDisplayAdapterTest { assertThat(mListener.changedDisplays.size()).isEqualTo(1); activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId); assertThat(activeMode.matches(1920, 1080, 120f)).isTrue(); assertEquals(supportedRefreshRates.length, displayDeviceInfo.supportedRefreshRates.length); } @Test Loading Loading @@ -1977,18 +1986,19 @@ public class LocalDisplayAdapterTest { throws InterruptedException { mHandler.post(() -> mListener.onModeChanged(/* timestampNanos = */ 0, display.address.getPhysicalDisplayId(), modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos)); appVsyncOffsetNanos, presentationDeadlineNanos, /*supportedRefreshRate*/ null)); waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); } public void sendOnModeAndFrameRateOverridesChanged(FakeDisplay display, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, FrameRateOverride[] frameRateOverrides) throws InterruptedException { FrameRateOverride[] frameRateOverrides, float[] supportedRefreshRates) throws InterruptedException { mHandler.post(() -> mListener.onModeAndFrameRateOverridesChanged( /* timestampNanos = */ 0, display.address.getPhysicalDisplayId(), modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, frameRateOverrides)); frameRateOverrides, supportedRefreshRates)); waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); } } Loading Loading
core/java/android/view/DisplayEventReceiver.java +7 −3 Original line number Diff line number Diff line Loading @@ -321,11 +321,13 @@ public abstract class DisplayEventReceiver { * 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 * @param supportedRefreshRates The list of refresh rates supported on the display */ public void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, FrameRateOverride[] overrides) { long presentationDeadlineNanos, FrameRateOverride[] overrides, float[] supportedRefreshRates) { } /** Loading Loading @@ -433,9 +435,11 @@ public abstract class DisplayEventReceiver { @SuppressWarnings("unused") private void dispatchModeChangedWithFrameRateOverrides(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, FrameRateOverride[] overrides) { long presentationDeadlineNanos, FrameRateOverride[] overrides, float[] supportedRefreshRates) { onModeAndFrameRateOverridesChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides); renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides, supportedRefreshRates); } // Called from native code. Loading
core/jni/android_view_DisplayEventReceiver.cpp +19 −4 Original line number Diff line number Diff line Loading @@ -92,6 +92,18 @@ jobjectArray getFrameRateOverrides(std::vector<FrameRateOverride> overrides, JNI return frameRateOverrideArray; } jfloatArray getSupportedRefreshRates(std::vector<SupportedRefreshRate> supportedRefreshRates, JNIEnv* env) { jfloatArray floatArray = env->NewFloatArray(supportedRefreshRates.size()); std::vector<jfloat> refreshRates(supportedRefreshRates.size()); for (size_t i = 0; i < supportedRefreshRates.size(); i++) { refreshRates[i] = supportedRefreshRates[i].refreshRate; } env->SetFloatArrayRegion(floatArray, 0, supportedRefreshRates.size(), refreshRates.data()); return floatArray; } class NativeDisplayEventReceiver : public DisplayEventDispatcher { public: NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak, jobject vsyncEventDataWeak, Loading @@ -115,7 +127,8 @@ private: void dispatchModeChangedWithFrameRateOverrides( nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t renderPeriod, nsecs_t appVsyncOffset, nsecs_t presentationDeadline, std::vector<FrameRateOverride> overrides) override; std::vector<FrameRateOverride> overrides, std::vector<SupportedRefreshRate> supportedRefreshRates) override; void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t renderPeriod, nsecs_t appVsyncOffset, nsecs_t presentationDeadline) override; Loading Loading @@ -302,17 +315,19 @@ void NativeDisplayEventReceiver::dispatchModeChanged(nsecs_t timestamp, Physical void NativeDisplayEventReceiver::dispatchModeChangedWithFrameRateOverrides( nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t renderPeriod, nsecs_t appVsyncOffset, nsecs_t presentationDeadline, std::vector<FrameRateOverride> overrides) { std::vector<FrameRateOverride> overrides, std::vector<SupportedRefreshRate> refreshRates) { 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); auto supportedRefreshRateArray = getSupportedRefreshRates(refreshRates, env); env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo .dispatchModeChangedWithFrameRateOverrides, timestamp, displayId.value, modeId, renderPeriod, appVsyncOffset, presentationDeadline, frameRateOverrideArray); presentationDeadline, frameRateOverrideArray, supportedRefreshRateArray); ALOGV("receiver %p ~ Returned from modeWithFrameRateOverride changed handler.", this); } Loading Loading @@ -456,7 +471,7 @@ int register_android_view_DisplayEventReceiver(JNIEnv* env) { gDisplayEventReceiverClassInfo.dispatchModeChangedWithFrameRateOverrides = GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchModeChangedWithFrameRateOverrides", "(JJIJJJ[Landroid/view/DisplayEventReceiver$FrameRateOverride;)V"); "(JJIJJJ[Landroid/view/DisplayEventReceiver$FrameRateOverride;[F)V"); gDisplayEventReceiverClassInfo.dispatchModeRejected = GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchModeRejected", "(JI)V"); Loading
services/core/java/com/android/server/display/LocalDisplayAdapter.java +61 −26 Original line number Diff line number Diff line Loading @@ -1242,18 +1242,26 @@ final class LocalDisplayAdapter extends DisplayAdapter { } private void onActiveDisplayModeChangedLocked(int sfModeId, float renderFrameRate, long appVsyncOffsetNanos, long presentationDeadlineNanos) { long appVsyncOffsetNanos, long presentationDeadlineNanos, @Nullable float[] supportedRefreshRates) { if (updateActiveModeAndFrameOverrideChangedLocked(sfModeId, renderFrameRate, appVsyncOffsetNanos, presentationDeadlineNanos, mFrameRateOverrides)) { appVsyncOffsetNanos, presentationDeadlineNanos, mFrameRateOverrides, supportedRefreshRates == null ? mSupportedRefreshRates : supportedRefreshRates)) { updateDeviceInfoLocked(); } } private void onFrameRateOverridesChangedLocked( DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, @Nullable float[] supportedRefreshRates) { if (updateActiveModeAndFrameOverrideChangedLocked(mActiveSfDisplayMode.id, mActiveRenderFrameRate, mAppVsyncOffsetNanos, mPresentationDeadlineNanos, overrides)) { overrides, supportedRefreshRates == null ? mSupportedRefreshRates : supportedRefreshRates)) { updateDeviceInfoLocked(); } } Loading @@ -1261,10 +1269,11 @@ final class LocalDisplayAdapter extends DisplayAdapter { private void onModeAndFrameRateOverridesChangedLocked( int sfModeId, float renderFrameRate, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates) { if (updateActiveModeAndFrameOverrideChangedLocked(sfModeId, renderFrameRate, appVsyncOffsetNanos, presentationDeadlineNanos, overrides)) { presentationDeadlineNanos, overrides, supportedRefreshRates)) { updateDeviceInfoLocked(); } } Loading @@ -1278,13 +1287,16 @@ final class LocalDisplayAdapter extends DisplayAdapter { private boolean updateActiveModeAndFrameOverrideChangedLocked(int activeSfModeId, float renderFrameRate, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates) { if (mActiveSfDisplayMode.id == activeSfModeId && mActiveRenderFrameRate == renderFrameRate && mAppVsyncOffsetNanos == appVsyncOffsetNanos && mPresentationDeadlineNanos == presentationDeadlineNanos && Arrays.equals(overrides, mFrameRateOverrides) ) { && (!com.android.graphics.surfaceflinger.flags.Flags.supportedRefreshRateUpdate() || Arrays.equals(supportedRefreshRates, mSupportedRefreshRates))) { return false; } mActiveSfDisplayMode = getModeById(mSfDisplayModes, activeSfModeId); Loading @@ -1297,6 +1309,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { mAppVsyncOffsetNanos = appVsyncOffsetNanos; mPresentationDeadlineNanos = presentationDeadlineNanos; mFrameRateOverrides = overrides; if (com.android.graphics.surfaceflinger.flags.Flags.supportedRefreshRateUpdate()) { mSupportedRefreshRates = supportedRefreshRates; } return true; } Loading Loading @@ -1626,12 +1641,15 @@ final class LocalDisplayAdapter extends DisplayAdapter { void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected); void onHotplugConnectionError(long timestampNanos, int connectionError); void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos); long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, @Nullable float[] supportedRefreshRates); void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, DisplayEventReceiver.FrameRateOverride[] overrides); DisplayEventReceiver.FrameRateOverride[] overrides, @Nullable float[] supportedRefreshRates); void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides); long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates); void onHdcpLevelsChanged(long physicalDisplayId, int connectedLevel, int maxLevel); } Loading Loading @@ -1660,21 +1678,25 @@ final class LocalDisplayAdapter extends DisplayAdapter { public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos) { mListener.onModeChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos); renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, /*supportedRefreshRates*/ null); } public void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates) { mListener.onModeAndFrameRateOverridesChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides); renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, overrides, supportedRefreshRates); } @Override public void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, DisplayEventReceiver.FrameRateOverride[] overrides) { mListener.onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides); mListener.onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides, /*supportedRefreshRates*/ null); } @Override Loading Loading @@ -1708,7 +1730,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { @Override public void onModeChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDealineNanos) { long renderPeriod, long appVsyncOffsetNanos, long presentationDealineNanos, @Nullable float[] supportedRefreshRates) { if (DEBUG) { Slog.d(TAG, "onModeChanged(" + "timestampNanos=" + timestampNanos Loading @@ -1716,7 +1739,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { + ", modeId=" + modeId + ", renderPeriod=" + renderPeriod + ", appVsyncOffsetNanos=" + appVsyncOffsetNanos + ", presentationDealineNanos=" + presentationDealineNanos + ")"); + ", presentationDealineNanos=" + presentationDealineNanos + ", supportedRefreshRates=" + Arrays.toString(supportedRefreshRates) + ")"); } synchronized (getSyncRoot()) { LocalDisplayDevice device = mDevices.get(physicalDisplayId); Loading @@ -1729,17 +1754,21 @@ final class LocalDisplayAdapter extends DisplayAdapter { } float renderFrameRate = 1e9f / renderPeriod; device.onActiveDisplayModeChangedLocked(modeId, renderFrameRate, appVsyncOffsetNanos, presentationDealineNanos); appVsyncOffsetNanos, presentationDealineNanos, supportedRefreshRates); } } @Override public void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, @Nullable float[] supportedRefreshRates) { if (DEBUG) { Slog.d(TAG, "onFrameRateOverrideChanged(timestampNanos=" + timestampNanos + ", physicalDisplayId=" + physicalDisplayId + " overrides=" + Arrays.toString(overrides) + ")"); + Arrays.toString(overrides) + ", supportedRefreshRates=" + Arrays.toString(supportedRefreshRates) + ")"); } synchronized (getSyncRoot()) { LocalDisplayDevice device = mDevices.get(physicalDisplayId); Loading @@ -1750,7 +1779,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { } return; } device.onFrameRateOverridesChangedLocked(overrides); device.onFrameRateOverridesChangedLocked(overrides, supportedRefreshRates); } } Loading @@ -1758,7 +1787,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { public void onModeAndFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, DisplayEventReceiver.FrameRateOverride[] overrides) { DisplayEventReceiver.FrameRateOverride[] overrides, float[] supportedRefreshRates) { if (getFeatureFlags().isSingleAppEventForModeAndFrameRateOverrideEnabled()) { if (DEBUG) { Slog.d(TAG, "onModeAndFrameRateOverridesChanged(" Loading @@ -1768,7 +1798,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { + ", renderPeriod=" + renderPeriod + ", appVsyncOffsetNanos=" + appVsyncOffsetNanos + ", presentationDeadlineNanos=" + presentationDeadlineNanos + ", overrides=" + Arrays.toString(overrides) + ")"); + ", overrides=" + Arrays.toString(overrides) + ", supportedRefreshRates=" + Arrays.toString(supportedRefreshRates) + ")"); } synchronized (getSyncRoot()) { LocalDisplayDevice device = mDevices.get(physicalDisplayId); Loading @@ -1782,15 +1814,18 @@ final class LocalDisplayAdapter extends DisplayAdapter { } float renderFrameRate = 1e9f / renderPeriod; device.onModeAndFrameRateOverridesChangedLocked(modeId, renderFrameRate, appVsyncOffsetNanos, presentationDeadlineNanos, overrides); appVsyncOffsetNanos, presentationDeadlineNanos, overrides, supportedRefreshRates); } } else { if (DEBUG) { Slog.d(TAG, "onModeAndFrameRateOverridesChanged"); } onModeChanged(timestampNanos, physicalDisplayId, modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos); onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides); appVsyncOffsetNanos, presentationDeadlineNanos, supportedRefreshRates); onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides, supportedRefreshRates); } } Loading
services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java +14 −4 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Spline; import android.view.Display; import android.view.DisplayAddress; Loading Loading @@ -78,6 +80,7 @@ import com.google.common.truth.Truth; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading Loading @@ -155,6 +158,9 @@ public class LocalDisplayAdapterTest { private static final List<Integer> mDisplayOffloadSupportedStates = new ArrayList<>(List.of(Display.STATE_DOZE_SUSPEND)); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Before public void setUp() throws Exception { mMockitoSession = mockitoSession() Loading Loading @@ -941,6 +947,7 @@ public class LocalDisplayAdapterTest { } @Test @EnableFlags(com.android.graphics.surfaceflinger.flags.Flags.FLAG_SUPPORTED_REFRESH_RATE_UPDATE) public void testOnModeAndFrameRateOverridesChanged() throws Exception { doReturn(true).when(mFlags).isDispatchDisplayModeWithVsyncOffsetsEnabled(); doReturn(true).when(mFlags).isSingleAppEventForModeAndFrameRateOverrideEnabled(); Loading Loading @@ -974,9 +981,10 @@ public class LocalDisplayAdapterTest { long newPresentationDeadlineNanos = 500; FrameRateOverride[] frameRateOverrides = new FrameRateOverride[1]; float[] supportedRefreshRates = {120.f, 60.f, 40.f, 30.f, 24.f, 20.f}; mInjector.getTransmitter().sendOnModeAndFrameRateOverridesChanged(display, /*modeId*/ 1, (long) displayMode2.peakRefreshRate, newAppVsyncOffsetNanos, newPresentationDeadlineNanos, frameRateOverrides); newPresentationDeadlineNanos, frameRateOverrides, supportedRefreshRates); waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); assertTrue(mListener.traversalRequested); Loading @@ -989,6 +997,7 @@ public class LocalDisplayAdapterTest { assertThat(mListener.changedDisplays.size()).isEqualTo(1); activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId); assertThat(activeMode.matches(1920, 1080, 120f)).isTrue(); assertEquals(supportedRefreshRates.length, displayDeviceInfo.supportedRefreshRates.length); } @Test Loading Loading @@ -1977,18 +1986,19 @@ public class LocalDisplayAdapterTest { throws InterruptedException { mHandler.post(() -> mListener.onModeChanged(/* timestampNanos = */ 0, display.address.getPhysicalDisplayId(), modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos)); appVsyncOffsetNanos, presentationDeadlineNanos, /*supportedRefreshRate*/ null)); waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); } public void sendOnModeAndFrameRateOverridesChanged(FakeDisplay display, int modeId, long renderPeriod, long appVsyncOffsetNanos, long presentationDeadlineNanos, FrameRateOverride[] frameRateOverrides) throws InterruptedException { FrameRateOverride[] frameRateOverrides, float[] supportedRefreshRates) throws InterruptedException { mHandler.post(() -> mListener.onModeAndFrameRateOverridesChanged( /* timestampNanos = */ 0, display.address.getPhysicalDisplayId(), modeId, renderPeriod, appVsyncOffsetNanos, presentationDeadlineNanos, frameRateOverrides)); frameRateOverrides, supportedRefreshRates)); waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); } } Loading