summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/ViewRootImpl.java37
-rw-r--r--core/java/android/view/flags/refresh_rate_flags.aconfig7
-rw-r--r--core/tests/coretests/src/android/view/ViewFrameRateTest.java71
3 files changed, 112 insertions, 3 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 23c43f56f2bc..350906818cb4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -123,6 +123,7 @@ import static android.view.flags.Flags.toolkitFrameRateTouchBoost25q1;
import static android.view.flags.Flags.toolkitFrameRateTypingReadOnly;
import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;
import static android.view.flags.Flags.toolkitFrameRateViewEnablingReadOnly;
+import static android.view.flags.Flags.toolkitInitialTouchBoost;
import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision;
import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER;
@@ -1113,9 +1114,13 @@ public final class ViewRootImpl implements ViewParent,
private boolean mIsFrameRateConflicted = false;
// Used to check whether SurfaceControl has been replaced.
private boolean mSurfaceReplaced = false;
+ // Indicates whether a draw operation occurred during this frame while a touch event was active.
+ private boolean mTouchAndDrawn = false;
// Used to set frame rate compatibility.
@Surface.FrameRateCompatibility int mFrameRateCompatibility =
FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
+ // time for initial touch boost period.
+ private static final int FRAME_RATE_INITIAL_TOUCH_BOOST_TIME = 30;
// time for touch boost period.
private static final int FRAME_RATE_TOUCH_BOOST_TIME = 3000;
// Timeout for the other frame rate boosts other than touch boost.
@@ -1213,6 +1218,7 @@ public final class ViewRootImpl implements ViewParent,
private static boolean sSurfaceFlingerBugfixFlagValue =
com.android.graphics.surfaceflinger.flags.Flags.vrrBugfix24q4();
private static final boolean sEnableVrr = ViewProperties.vrr_enabled().orElse(true);
+ private static final boolean sToolkitInitialTouchBoostFlagValue = toolkitInitialTouchBoost();
static {
sToolkitSetFrameRateReadOnlyFlagValue = toolkitSetFrameRateReadOnly();
@@ -4435,6 +4441,10 @@ public final class ViewRootImpl implements ViewParent,
// We set the preferred frame rate and frame rate category at the end of performTraversals
// when the values are applicable.
if (mDrawnThisFrame) {
+ if (sToolkitInitialTouchBoostFlagValue && mIsTouchBoosting) {
+ mTouchAndDrawn = true;
+ }
+
mDrawnThisFrame = false;
if (!mInvalidationIdleMessagePosted && sSurfaceFlingerBugfixFlagValue) {
mInvalidationIdleMessagePosted = true;
@@ -6718,6 +6728,7 @@ public final class ViewRootImpl implements ViewParent,
private static final int MSG_REFRESH_POINTER_ICON = 41;
private static final int MSG_FRAME_RATE_SETTING = 42;
private static final int MSG_SURFACE_REPLACED_TIMEOUT = 43;
+ private static final int MSG_INITIAL_TOUCH_BOOST_TIMEOUT = 44;
final class ViewRootHandler extends Handler {
@Override
@@ -6791,6 +6802,8 @@ public final class ViewRootImpl implements ViewParent,
return "MSG_FRAME_RATE_SETTING";
case MSG_SURFACE_REPLACED_TIMEOUT:
return "MSG_SURFACE_REPLACED_TIMEOUT";
+ case MSG_INITIAL_TOUCH_BOOST_TIMEOUT:
+ return "MSG_INITIAL_TOUCH_BOOST_TIMEOUT";
}
return super.getMessageName(message);
}
@@ -7066,6 +7079,17 @@ public final class ViewRootImpl implements ViewParent,
setPreferredFrameRateCategory(FRAME_RATE_CATEGORY_NO_PREFERENCE);
}
break;
+ case MSG_INITIAL_TOUCH_BOOST_TIMEOUT:
+ if (mTouchAndDrawn) {
+ mHandler.removeMessages(MSG_TOUCH_BOOST_TIMEOUT);
+ mHandler.sendEmptyMessageDelayed(MSG_TOUCH_BOOST_TIMEOUT,
+ FRAME_RATE_TOUCH_BOOST_TIME);
+ } else {
+ mIsTouchBoosting = false;
+ setPreferredFrameRateCategory(FRAME_RATE_CATEGORY_NO_PREFERENCE);
+ }
+ mTouchAndDrawn = false;
+ break;
case MSG_REFRESH_POINTER_ICON:
if (mPointerIconEvent == null) {
break;
@@ -8130,9 +8154,16 @@ public final class ViewRootImpl implements ViewParent,
*/
if (mIsTouchBoosting && (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL)) {
- mHandler.removeMessages(MSG_TOUCH_BOOST_TIMEOUT);
- mHandler.sendEmptyMessageDelayed(MSG_TOUCH_BOOST_TIMEOUT,
- FRAME_RATE_TOUCH_BOOST_TIME);
+
+ if (sToolkitInitialTouchBoostFlagValue) {
+ mHandler.removeMessages(MSG_INITIAL_TOUCH_BOOST_TIMEOUT);
+ mHandler.sendEmptyMessageDelayed(MSG_INITIAL_TOUCH_BOOST_TIMEOUT,
+ FRAME_RATE_INITIAL_TOUCH_BOOST_TIME);
+ } else {
+ mHandler.removeMessages(MSG_TOUCH_BOOST_TIMEOUT);
+ mHandler.sendEmptyMessageDelayed(MSG_TOUCH_BOOST_TIMEOUT,
+ FRAME_RATE_TOUCH_BOOST_TIME);
+ }
}
return handled ? FINISH_HANDLED : FORWARD;
}
diff --git a/core/java/android/view/flags/refresh_rate_flags.aconfig b/core/java/android/view/flags/refresh_rate_flags.aconfig
index 675e5a1b4804..3bc2205f8e1c 100644
--- a/core/java/android/view/flags/refresh_rate_flags.aconfig
+++ b/core/java/android/view/flags/refresh_rate_flags.aconfig
@@ -136,4 +136,11 @@ flag {
description: "Feature flag to not suppress touch boost for specific windowTypes in VRR V QPR2"
bug: "335874198"
is_exported: true
+}
+
+flag {
+ name: "toolkit_initial_touch_boost"
+ namespace: "toolkit"
+ description: "Feature flag to update initial touch boost logic"
+ bug: "393004744"
} \ No newline at end of file
diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
index 8b4f714fbf65..45f1a096aa85 100644
--- a/core/tests/coretests/src/android/view/ViewFrameRateTest.java
+++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
@@ -26,6 +26,7 @@ import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_ANIMATION_BUGFIX_
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_TOUCH_BOOST_25Q1;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY;
+import static android.view.flags.Flags.FLAG_TOOLKIT_INITIAL_TOUCH_BOOST;
import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
@@ -34,6 +35,7 @@ import static android.view.flags.Flags.toolkitFrameRateSmallUsesPercentReadOnly;
import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.annotation.NonNull;
@@ -180,6 +182,75 @@ public class ViewFrameRateTest {
}
@Test
+ @RequiresFlagsEnabled(FLAG_TOOLKIT_INITIAL_TOUCH_BOOST)
+ public void initialTouchBoost() throws Throwable {
+ if (!ViewProperties.vrr_enabled().orElse(true)) {
+ return;
+ }
+
+ mActivityRule.runOnUiThread(() -> {
+ ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
+ layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ mMovingView.setLayoutParams(layoutParams);
+ mMovingView.setOnClickListener((v) -> {});
+ });
+ waitForFrameRateCategoryToSettle();
+
+ int[] position = new int[2];
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.getLocationOnScreen(position);
+ position[0] += mMovingView.getWidth() / 2;
+ position[1] += mMovingView.getHeight() / 2;
+ });
+ final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+
+ assertFalse(mViewRoot.getIsTouchBoosting());
+
+ long now = SystemClock.uptimeMillis();
+ MotionEvent down = MotionEvent.obtain(
+ now, // downTime
+ now, // eventTime
+ MotionEvent.ACTION_DOWN, // action
+ position[0], // x
+ position[1], // y
+ 0 // metaState
+ );
+
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.getViewRootImpl().dispatchAppVisibility(false);
+ });
+
+ down.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ instrumentation.sendPointerSync(down);
+ down.recycle();
+
+ Thread.sleep(100);
+ // should have touch boost
+ assertTrue(mViewRoot.getIsTouchBoosting());
+
+ MotionEvent up = MotionEvent.obtain(
+ now, // downTime
+ now, // eventTime
+ MotionEvent.ACTION_UP, // action
+ position[0], // x
+ position[1], // y
+ 0 // metaState
+ );
+ up.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ instrumentation.sendPointerSync(up);
+ up.recycle();
+
+ // Should not be boosted if nothing is drawn
+ Thread.sleep(30);
+ assertFalse(mViewRoot.getIsTouchBoosting());
+
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.getViewRootImpl().dispatchAppVisibility(true);
+ });
+ }
+
+ @Test
@RequiresFlagsEnabled(FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY)
public void inputMethodWithContentMoves() throws Throwable {
if (!ViewProperties.vrr_enabled().orElse(true)) {