Merge "API: add smooth switch in setFrameRateCategory" into main
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 658341c..2f3d73a 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -263,7 +263,7 @@
private static native void nativeSetDefaultFrameRateCompatibility(long transactionObj,
long nativeObject, int compatibility);
private static native void nativeSetFrameRateCategory(
- long transactionObj, long nativeObject, int category);
+ long transactionObj, long nativeObject, int category, boolean smoothSwitchOnly);
private static native void nativeSetFrameRateSelectionStrategy(
long transactionObj, long nativeObject, int strategy);
private static native long nativeGetHandle(long nativeObject);
@@ -3709,6 +3709,10 @@
* @param sc The SurfaceControl to specify the frame rate category of.
* @param category The frame rate category of this surface. The category value may influence
* the system's choice of display frame rate.
+ * @param smoothSwitchOnly Set to {@code true} to indicate the display frame rate should not
+ * change if changing it would cause jank. Else {@code false}.
+ * This parameter is ignored when {@code category} is
+ * {@link Surface#FRAME_RATE_CATEGORY_DEFAULT}.
*
* @return This transaction object.
*
@@ -3717,10 +3721,10 @@
* @hide
*/
@NonNull
- public Transaction setFrameRateCategory(
- @NonNull SurfaceControl sc, @Surface.FrameRateCategory int category) {
+ public Transaction setFrameRateCategory(@NonNull SurfaceControl sc,
+ @Surface.FrameRateCategory int category, boolean smoothSwitchOnly) {
checkPreconditions(sc);
- nativeSetFrameRateCategory(mNativeObject, sc.mNativeObject, category);
+ nativeSetFrameRateCategory(mNativeObject, sc.mNativeObject, category, smoothSwitchOnly);
return this;
}
diff --git a/core/java/android/window/SystemPerformanceHinter.java b/core/java/android/window/SystemPerformanceHinter.java
index 07ac292..2736b68 100644
--- a/core/java/android/window/SystemPerformanceHinter.java
+++ b/core/java/android/window/SystemPerformanceHinter.java
@@ -211,7 +211,11 @@
session.displayId);
mTransaction.setFrameRateSelectionStrategy(displaySurfaceControl,
FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
- mTransaction.setFrameRateCategory(displaySurfaceControl, FRAME_RATE_CATEGORY_HIGH);
+ // smoothSwitchOnly is false to request a higher framerate, even if it means switching
+ // the display mode will cause would jank on non-VRR devices because keeping a lower
+ // refresh rate would mean a poorer user experience.
+ mTransaction.setFrameRateCategory(
+ displaySurfaceControl, FRAME_RATE_CATEGORY_HIGH, /* smoothSwitchOnly= */ false);
transactionChanged = true;
Trace.beginAsyncSection("PerfHint-framerate-" + session.displayId + "-"
+ session.reason, session.traceCookie);
@@ -251,7 +255,11 @@
session.displayId);
mTransaction.setFrameRateSelectionStrategy(displaySurfaceControl,
FRAME_RATE_SELECTION_STRATEGY_SELF);
- mTransaction.setFrameRateCategory(displaySurfaceControl, FRAME_RATE_CATEGORY_DEFAULT);
+ // smoothSwitchOnly is false to request a higher framerate, even if it means switching
+ // the display mode will cause would jank on non-VRR devices because keeping a lower
+ // refresh rate would mean a poorer user experience.
+ mTransaction.setFrameRateCategory(displaySurfaceControl, FRAME_RATE_CATEGORY_DEFAULT,
+ /* smoothSwitchOnly= */ false);
transactionChanged = true;
Trace.endAsyncSection("PerfHint-framerate-" + session.displayId + "-" + session.reason,
session.traceCookie);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index ba644eb..178c0d0 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -963,10 +963,11 @@
}
static void nativeSetFrameRateCategory(JNIEnv* env, jclass clazz, jlong transactionObj,
- jlong nativeObject, jint category) {
+ jlong nativeObject, jint category,
+ jboolean smoothSwitchOnly) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
const auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
- transaction->setFrameRateCategory(ctrl, static_cast<int8_t>(category));
+ transaction->setFrameRateCategory(ctrl, static_cast<int8_t>(category), smoothSwitchOnly);
}
static void nativeSetFrameRateSelectionStrategy(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -2181,7 +2182,7 @@
(void*)nativeSetFrameRate },
{"nativeSetDefaultFrameRateCompatibility", "(JJI)V",
(void*)nativeSetDefaultFrameRateCompatibility},
- {"nativeSetFrameRateCategory", "(JJI)V",
+ {"nativeSetFrameRateCategory", "(JJIZ)V",
(void*)nativeSetFrameRateCategory},
{"nativeSetFrameRateSelectionStrategy", "(JJI)V",
(void*)nativeSetFrameRateSelectionStrategy},
diff --git a/core/tests/coretests/src/android/window/SystemPerformanceHinterTests.java b/core/tests/coretests/src/android/window/SystemPerformanceHinterTests.java
index 263e563..6229530 100644
--- a/core/tests/coretests/src/android/window/SystemPerformanceHinterTests.java
+++ b/core/tests/coretests/src/android/window/SystemPerformanceHinterTests.java
@@ -31,6 +31,7 @@
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -154,7 +155,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN));
verify(mTransaction).setFrameRateCategory(
eq(mDefaultDisplayRoot),
- eq(FRAME_RATE_CATEGORY_HIGH));
+ eq(FRAME_RATE_CATEGORY_HIGH),
+ eq(false));
verify(mTransaction).applyAsyncUnsafe();
}
@@ -171,7 +173,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_SELF));
verify(mTransaction).setFrameRateCategory(
eq(mDefaultDisplayRoot),
- eq(FRAME_RATE_CATEGORY_DEFAULT));
+ eq(FRAME_RATE_CATEGORY_DEFAULT),
+ eq(false));
verify(mTransaction).applyAsyncUnsafe();
}
@@ -241,7 +244,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN));
verify(mTransaction).setFrameRateCategory(
eq(mDefaultDisplayRoot),
- eq(FRAME_RATE_CATEGORY_HIGH));
+ eq(FRAME_RATE_CATEGORY_HIGH),
+ eq(false));
verify(mTransaction).setEarlyWakeupStart();
verify(mTransaction).applyAsyncUnsafe();
verify(mAdpfSession).sendHint(eq(CPU_LOAD_UP));
@@ -261,7 +265,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_SELF));
verify(mTransaction).setFrameRateCategory(
eq(mDefaultDisplayRoot),
- eq(FRAME_RATE_CATEGORY_DEFAULT));
+ eq(FRAME_RATE_CATEGORY_DEFAULT),
+ eq(false));
verify(mTransaction).setEarlyWakeupEnd();
verify(mTransaction).applyAsyncUnsafe();
verify(mAdpfSession).sendHint(eq(CPU_LOAD_RESET));
@@ -281,7 +286,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_SELF));
verify(mTransaction).setFrameRateCategory(
eq(mDefaultDisplayRoot),
- eq(FRAME_RATE_CATEGORY_DEFAULT));
+ eq(FRAME_RATE_CATEGORY_DEFAULT),
+ eq(false));
verify(mTransaction).setEarlyWakeupEnd();
verify(mTransaction).applyAsyncUnsafe();
verify(mAdpfSession).sendHint(eq(CPU_LOAD_RESET));
@@ -299,7 +305,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN));
verify(mTransaction).setFrameRateCategory(
eq(mDefaultDisplayRoot),
- eq(FRAME_RATE_CATEGORY_HIGH));
+ eq(FRAME_RATE_CATEGORY_HIGH),
+ eq(false));
verify(mTransaction).setEarlyWakeupStart();
verify(mTransaction).applyAsyncUnsafe();
verify(mAdpfSession).sendHint(eq(CPU_LOAD_UP));
@@ -310,7 +317,7 @@
mHinter.startSession(HINT_ALL, DEFAULT_DISPLAY_ID, TEST_OTHER_REASON);
// Verify we never call SF and perf manager since session1 is already running
verify(mTransaction, never()).setFrameRateSelectionStrategy(any(), anyInt());
- verify(mTransaction, never()).setFrameRateCategory(any(), anyInt());
+ verify(mTransaction, never()).setFrameRateCategory(any(), anyInt(), anyBoolean());
verify(mTransaction, never()).setEarlyWakeupEnd();
verify(mTransaction, never()).applyAsyncUnsafe();
verify(mAdpfSession, never()).sendHint(anyInt());
@@ -318,7 +325,7 @@
session2.close();
// Verify we have not cleaned up because session1 is still running
verify(mTransaction, never()).setFrameRateSelectionStrategy(any(), anyInt());
- verify(mTransaction, never()).setFrameRateCategory(any(), anyInt());
+ verify(mTransaction, never()).setFrameRateCategory(any(), anyInt(), anyBoolean());
verify(mTransaction, never()).setEarlyWakeupEnd();
verify(mTransaction, never()).applyAsyncUnsafe();
verify(mAdpfSession, never()).sendHint(anyInt());
@@ -330,7 +337,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_SELF));
verify(mTransaction).setFrameRateCategory(
eq(mDefaultDisplayRoot),
- eq(FRAME_RATE_CATEGORY_DEFAULT));
+ eq(FRAME_RATE_CATEGORY_DEFAULT),
+ eq(false));
verify(mTransaction).setEarlyWakeupEnd();
verify(mTransaction).applyAsyncUnsafe();
verify(mAdpfSession).sendHint(eq(CPU_LOAD_RESET));
@@ -348,7 +356,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN));
verify(mTransaction).setFrameRateCategory(
eq(mDefaultDisplayRoot),
- eq(FRAME_RATE_CATEGORY_HIGH));
+ eq(FRAME_RATE_CATEGORY_HIGH),
+ eq(false));
verify(mTransaction).setEarlyWakeupStart();
verify(mTransaction).applyAsyncUnsafe();
verify(mAdpfSession).sendHint(eq(CPU_LOAD_UP));
@@ -363,7 +372,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN));
verify(mTransaction).setFrameRateCategory(
eq(mSecondaryDisplayRoot),
- eq(FRAME_RATE_CATEGORY_HIGH));
+ eq(FRAME_RATE_CATEGORY_HIGH),
+ eq(false));
verify(mTransaction, never()).setEarlyWakeupStart();
verify(mTransaction).applyAsyncUnsafe();
verify(mAdpfSession, never()).sendHint(anyInt());
@@ -378,13 +388,15 @@
eq(FRAME_RATE_SELECTION_STRATEGY_SELF));
verify(mTransaction).setFrameRateCategory(
eq(mDefaultDisplayRoot),
- eq(FRAME_RATE_CATEGORY_DEFAULT));
+ eq(FRAME_RATE_CATEGORY_DEFAULT),
+ eq(false));
verify(mTransaction, never()).setFrameRateSelectionStrategy(
eq(mSecondaryDisplayRoot),
anyInt());
verify(mTransaction, never()).setFrameRateCategory(
eq(mSecondaryDisplayRoot),
- anyInt());
+ anyInt(),
+ eq(false));
verify(mTransaction, never()).setEarlyWakeupEnd();
verify(mTransaction).applyAsyncUnsafe();
verify(mAdpfSession, never()).sendHint(anyInt());
@@ -401,7 +413,8 @@
eq(FRAME_RATE_SELECTION_STRATEGY_SELF));
verify(mTransaction).setFrameRateCategory(
eq(mSecondaryDisplayRoot),
- eq(FRAME_RATE_CATEGORY_DEFAULT));
+ eq(FRAME_RATE_CATEGORY_DEFAULT),
+ eq(false));
verify(mTransaction).setEarlyWakeupEnd();
verify(mTransaction).applyAsyncUnsafe();
verify(mAdpfSession).sendHint(eq(CPU_LOAD_RESET));
diff --git a/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java b/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java
index 79348d1..ae7c2a9 100644
--- a/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java
+++ b/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java
@@ -247,7 +247,7 @@
int rc = 0;
try (SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()) {
- transaction.setFrameRateCategory(mSurfaceControl, category);
+ transaction.setFrameRateCategory(mSurfaceControl, category, false);
transaction.apply();
}
return rc;