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

Commit 793b0f4b authored by Robert Berry's avatar Robert Berry
Browse files

Sync granularity of gestures with vsync

Gesture dispatch should match the refresh rate of the Display, in order
to create smooth animations. The previous behavior was to split gestures
up into 100ms steps. Retain that behavior for AccessibilityService
instances that are targeting pre-R. For R, split gestures up into enough
steps to closely track refresh rate.

Test: manual
Bug: 150190594
Change-Id: I80b24227f86916945abf7ff8bfb60a91fc12f50e
parent 76c2a127
Loading
Loading
Loading
Loading
+27 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.graphics.ColorSpace;
import android.graphics.ParcelableColorSpace;
import android.graphics.Region;
import android.hardware.HardwareBuffer;
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -1014,8 +1015,9 @@ public abstract class AccessibilityService extends Service {
        if (connection == null) {
            return false;
        }
        int sampleTimeMs = calculateGestureSampleTimeMs(gesture.getDisplayId());
        List<GestureDescription.GestureStep> steps =
                MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, 16);
                MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, sampleTimeMs);
        try {
            synchronized (mLock) {
                mGestureStatusCallbackSequence++;
@@ -1036,6 +1038,30 @@ public abstract class AccessibilityService extends Service {
        return true;
    }

    /**
     * Returns the sample time in millis of gesture steps for the current display.
     *
     * <p>For gestures to be smooth they should line up with the refresh rate of the display.
     * On versions of Android before R, the sample time was fixed to 100ms.
     */
    private int calculateGestureSampleTimeMs(int displayId) {
        if (getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.Q) {
            return 100;
        }
        Display display = getSystemService(DisplayManager.class).getDisplay(
                displayId);
        if (display == null) {
            return 100;
        }
        int msPerSecond = 1000;
        int sampleTimeMs = (int) (msPerSecond / display.getRefreshRate());
        if (sampleTimeMs < 1) {
            // Should be impossible, but do not return 0.
            return 100;
        }
        return sampleTimeMs;
    }

    void onPerformGestureResult(int sequence, final boolean completedSuccessfully) {
        if (mGestureStatusCallbackInfos == null) {
            return;