/**
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.accessibilityservice.cts;

import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityOnSpecifiedDisplayAndWaitForItToBeOnscreen;
import static android.accessibilityservice.cts.utils.DisplayUtils.VirtualDisplaySession;
import static android.accessibilityservice.cts.utils.GestureUtils.add;
import static android.accessibilityservice.cts.utils.GestureUtils.click;
import static android.accessibilityservice.cts.utils.GestureUtils.diff;
import static android.accessibilityservice.cts.utils.GestureUtils.endTimeOf;
import static android.accessibilityservice.cts.utils.GestureUtils.getGestureBuilder;
import static android.accessibilityservice.cts.utils.GestureUtils.longClick;
import static android.accessibilityservice.cts.utils.GestureUtils.startingAt;
import static android.app.UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES;

import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;

import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.accessibilityservice.GestureDescription.StrokeDescription;
import android.accessibilityservice.cts.activities.AccessibilityWindowQueryActivity;
import android.accessibilityservice.cts.utils.GestureUtils;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.platform.test.annotations.AppModeFull;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;

import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/** Verify that motion events are recognized as accessibility gestures. */
@RunWith(AndroidJUnit4.class)
public class AccessibilityGestureDetectorTest {

    // Constants
    private static final float GESTURE_LENGTH_INCHES = 1.0f;
    // The movement should exceed the threshold 1 cm in 150 ms defined in Swipe.java. It means the
    // swipe velocity in testing should be greater than 2.54 cm / 381 ms. Therefore the
    // duration should be smaller than 381.
    private static final long STROKE_MS = 380;
    private static final long GESTURE_DISPATCH_TIMEOUT_MS = 3000;
    private static final long EVENT_DISPATCH_TIMEOUT_MS = 3000;
    private static final PointF FINGER_OFFSET_PX = new PointF(100f, -50f);

    private static Instrumentation sInstrumentation;
    private static UiAutomation sUiAutomation;

    private InstrumentedAccessibilityServiceTestRule<GestureDetectionStubAccessibilityService>
            mServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
                    GestureDetectionStubAccessibilityService.class, false);

    private AccessibilityDumpOnFailureRule mDumpOnFailureRule =
            new AccessibilityDumpOnFailureRule();

    @Rule
    public final RuleChain mRuleChain = RuleChain
            .outerRule(mServiceRule)
            .around(mDumpOnFailureRule);

    // Test AccessibilityService that collects gestures.
    GestureDetectionStubAccessibilityService mService; 
    boolean mHasTouchScreen;
    boolean mScreenBigEnough;
    int mStrokeLenPxX; // Gesture stroke size, in pixels
    int mStrokeLenPxY;
    Point mCenter; // Center of screen. Gestures all start from this point.
    PointF mTapLocation;
    int mScaledTouchSlop;
    int mMaxAdjustedStrokeLenPxX;
    int mMaxAdjustedStrokeLenPxY;
    @Mock AccessibilityService.GestureResultCallback mGestureDispatchCallback;

    @BeforeClass
    public static void oneTimeSetup() {
        sInstrumentation = InstrumentationRegistry.getInstrumentation();
        sUiAutomation = sInstrumentation.getUiAutomation(FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
    }

    @AfterClass
    public static void finalTearDown() {
        sUiAutomation.destroy();
    }

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        // Check that device has a touch screen.
        PackageManager pm = sInstrumentation.getContext().getPackageManager();
        mHasTouchScreen = pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
                || pm.hasSystemFeature(PackageManager.FEATURE_FAKETOUCH);
        if (!mHasTouchScreen) {
            return;
        }

        // Find screen size, check that it is big enough for gestures.
        // Gestures will start in the center of the screen, so we need enough horiz/vert space.
        WindowManager windowManager = (WindowManager) sInstrumentation.getContext()
                .getSystemService(Context.WINDOW_SERVICE);
        final DisplayMetrics metrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getRealMetrics(metrics);
        mCenter = new Point((int) metrics.widthPixels / 2, (int) metrics.heightPixels / 2);
        mTapLocation = new PointF(mCenter);
        mScaledTouchSlop =
                ViewConfiguration.get(sInstrumentation.getContext()).getScaledTouchSlop();
        mStrokeLenPxX = (int) (GESTURE_LENGTH_INCHES * metrics.xdpi);
        // The threshold is determined by xdpi.
        mStrokeLenPxY = mStrokeLenPxX;
        mMaxAdjustedStrokeLenPxX = metrics.widthPixels / 2;
        mMaxAdjustedStrokeLenPxY = metrics.heightPixels / 2;
        final boolean screenWideEnough = metrics.widthPixels / 2 > mStrokeLenPxX;
        final boolean screenHighEnough =  metrics.heightPixels / 2 > mStrokeLenPxY;
        mScreenBigEnough = screenWideEnough && screenHighEnough;
        if (!mScreenBigEnough) {
            return;
        }
        // Start stub accessibility service.
        mService = mServiceRule.enableService();
    }

    @Test
    @AppModeFull
    public void testRecognizeGesturePath() {
        if (!mHasTouchScreen || !mScreenBigEnough) {
            return;
        }

        runGestureDetectionTestOnDisplay(Display.DEFAULT_DISPLAY);
        runMultiFingerGestureDetectionTestOnDisplay(Display.DEFAULT_DISPLAY);
    }

    @Test
    @AppModeFull
    public void testRecognizeGesturePathOnVirtualDisplay() throws Exception {
        assumeTrue(sInstrumentation.getContext().getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS));

        if (!mHasTouchScreen || !mScreenBigEnough) {
            return;
        }

        try (final VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
            final int displayId = displaySession.createDisplayWithDefaultDisplayMetricsAndWait(
                    sInstrumentation.getTargetContext(), false).getDisplayId();
            // Launches an activity on virtual display to meet a real situation.
            final Activity activity = launchActivityOnSpecifiedDisplayAndWaitForItToBeOnscreen(
                    sInstrumentation, sUiAutomation, AccessibilityWindowQueryActivity.class,
                    displayId);

            try {
                runGestureDetectionTestOnDisplay(displayId);
                runMultiFingerGestureDetectionTestOnDisplay(displayId);
            } finally {
                sInstrumentation.runOnMainSync(() -> {
                    activity.finish();
                });
                sInstrumentation.waitForIdleSync();
            }
        }
    }

    private void runGestureDetectionTestOnDisplay(int displayId) {
        // Compute gesture stroke lengths, in pixels.
        final int dx = mStrokeLenPxX;
        final int dy = mStrokeLenPxY;

        // Test recognizing various gestures.
        testGesture(
                doubleTap(displayId),
                AccessibilityService.GESTURE_DOUBLE_TAP,
                displayId);
        testGesture(
                doubleTapAndHold(displayId),
                AccessibilityService.GESTURE_DOUBLE_TAP_AND_HOLD,
                displayId);
        testPath(p(-dx, +0), AccessibilityService.GESTURE_SWIPE_LEFT, displayId);
        testPath(p(+dx, +0), AccessibilityService.GESTURE_SWIPE_RIGHT, displayId);
        testPath(p(+0, -dy), AccessibilityService.GESTURE_SWIPE_UP, displayId);
        testPath(p(+0, +dy), AccessibilityService.GESTURE_SWIPE_DOWN, displayId);

        testPath(p(-dx, +0), p(+0, +0), AccessibilityService.GESTURE_SWIPE_LEFT_AND_RIGHT,
                displayId);
        testPath(p(-dx, +0), p(-dx, -dy), AccessibilityService.GESTURE_SWIPE_LEFT_AND_UP,
                displayId);
        testPath(p(-dx, +0), p(-dx, +dy), AccessibilityService.GESTURE_SWIPE_LEFT_AND_DOWN,
                displayId);

        testPath(p(+dx, +0), p(+0, +0), AccessibilityService.GESTURE_SWIPE_RIGHT_AND_LEFT,
                displayId);
        testPath(p(+dx, +0), p(+dx, -dy), AccessibilityService.GESTURE_SWIPE_RIGHT_AND_UP,
                displayId);
        testPath(p(+dx, +0), p(+dx, +dy), AccessibilityService.GESTURE_SWIPE_RIGHT_AND_DOWN,
                displayId);

        testPath(p(+0, -dy), p(-dx, -dy), AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT,
                displayId);
        testPath(p(+0, -dy), p(+dx, -dy), AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT,
                displayId);
        testPath(p(+0, -dy), p(+0, +0), AccessibilityService.GESTURE_SWIPE_UP_AND_DOWN,
                displayId);

        testPath(p(+0, +dy), p(-dx, +dy), AccessibilityService.GESTURE_SWIPE_DOWN_AND_LEFT,
                displayId);
        testPath(p(+0, +dy), p(+dx, +dy), AccessibilityService.GESTURE_SWIPE_DOWN_AND_RIGHT,
                displayId);
        testPath(p(+0, +dy), p(+0, +0), AccessibilityService.GESTURE_SWIPE_DOWN_AND_UP,
                displayId);
    }

    private void runMultiFingerGestureDetectionTestOnDisplay(int displayId) {
        // Compute gesture stroke lengths, in pixels.
        final int dx = mStrokeLenPxX;
        final int dy = mStrokeLenPxY;
        testGesture(
                twoFingerSingleTap(displayId),
                AccessibilityService.GESTURE_2_FINGER_SINGLE_TAP,
                displayId);
                testGesture(
                        twoFingerTripleTapAndHold(displayId),
                        AccessibilityService.GESTURE_2_FINGER_TRIPLE_TAP_AND_HOLD,
                        displayId);
                testGesture(
                twoFingerDoubleTap(displayId),
                AccessibilityService.GESTURE_2_FINGER_DOUBLE_TAP,
                displayId);
                testGesture(
                twoFingerDoubleTapAndHold(displayId),
                AccessibilityService.GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD,
                displayId);
        testGesture(
                twoFingerTripleTap(displayId),
                AccessibilityService.GESTURE_2_FINGER_TRIPLE_TAP,
                displayId);

        testGesture(
                threeFingerSingleTap(displayId),
                AccessibilityService.GESTURE_3_FINGER_SINGLE_TAP,
                displayId);
                testGesture(
                        threeFingerSingleTapAndHold(displayId),
                        AccessibilityService.GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD,
                        displayId);
                testGesture(
                threeFingerDoubleTap(displayId),
                AccessibilityService.GESTURE_3_FINGER_DOUBLE_TAP,
                displayId);
                testGesture(
                threeFingerDoubleTapAndHold(displayId),
                AccessibilityService.GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD,
                displayId);
        testGesture(
                threeFingerTripleTap(displayId),
                AccessibilityService.GESTURE_3_FINGER_TRIPLE_TAP,
                displayId);
                testGesture(
                        threeFingerTripleTapAndHold(displayId),
                        AccessibilityService.GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD,
                        displayId);

        testGesture(
                fourFingerSingleTap(displayId),
                AccessibilityService.GESTURE_4_FINGER_SINGLE_TAP,
                displayId);
        testGesture(
                fourFingerDoubleTap(displayId),
                AccessibilityService.GESTURE_4_FINGER_DOUBLE_TAP,
                displayId);
                testGesture(
                fourFingerDoubleTapAndHold(displayId),
                AccessibilityService.GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD,
                displayId);
        testGesture(
                fourFingerTripleTap(displayId),
                AccessibilityService.GESTURE_4_FINGER_TRIPLE_TAP,
                displayId);

        testGesture(
                MultiFingerSwipe(displayId, 3, 0, dy),
                AccessibilityService.GESTURE_3_FINGER_SWIPE_DOWN,
                displayId);
        testGesture(
                MultiFingerSwipe(displayId, 3, -dx, 0),
                AccessibilityService.GESTURE_3_FINGER_SWIPE_LEFT,
                displayId);
        testGesture(
                MultiFingerSwipe(displayId, 3, dx, 0),
                AccessibilityService.GESTURE_3_FINGER_SWIPE_RIGHT,
                displayId);
        testGesture(
                MultiFingerSwipe(displayId, 3, 0, -dy),
                AccessibilityService.GESTURE_3_FINGER_SWIPE_UP,
                displayId);
        testGesture(
                MultiFingerSwipe(displayId, 4, 0, dy),
                AccessibilityService.GESTURE_4_FINGER_SWIPE_DOWN,
                displayId);
        testGesture(
                MultiFingerSwipe(displayId, 4, -dx, 0),
                AccessibilityService.GESTURE_4_FINGER_SWIPE_LEFT,
                displayId);
        testGesture(
                MultiFingerSwipe(displayId, 4, dx, 0),
                AccessibilityService.GESTURE_4_FINGER_SWIPE_RIGHT,
                displayId);
        testGesture(
                MultiFingerSwipe(displayId, 4, 0, -dy),
                AccessibilityService.GESTURE_4_FINGER_SWIPE_UP,
                displayId);
    }

    /** Convenient short alias to make a Point. */
    private static Point p(int x, int y) {
        return new Point(x, y);
    }

    /** Test recognizing path from PATH_START to PATH_START+delta on default display. */
    private void testPath(Point delta, int gestureId) {
        testPath(delta, null, gestureId, Display.DEFAULT_DISPLAY);
    }

    /** Test recognizing path from PATH_START to PATH_START+delta on specified display. */
    private void testPath(Point delta, int gestureId, int displayId) {
        testPath(delta, null, gestureId, displayId);
    }
    /** Test recognizing path from PATH_START to PATH_START+delta on default display. */
    private void testPath(Point delta1, Point delta2, int gestureId) {
        testPath(delta1, delta2, gestureId, Display.DEFAULT_DISPLAY);
    }

    /**
     * Test recognizing path from PATH_START to PATH_START+delta1 to PATH_START+delta2. on specified
     * display.
     */
    private void testPath(Point delta1, Point delta2, int gestureId, int displayId) {
        // Create gesture motions.
        int numPathSegments = (delta2 == null) ? 1 : 2;
        long pathDurationMs = numPathSegments * STROKE_MS;
        GestureDescription gesture = new GestureDescription.Builder()
                .addStroke(new StrokeDescription(
                linePath(mCenter, delta1, delta2), 0, pathDurationMs, false))
                .setDisplayId(displayId)
                .build();

        testGesture(gesture, gestureId, displayId);
    }

    /** Dispatch a gesture and make sure it is detected as the specified gesture id. */
    private void testGesture(GestureDescription gesture, int gestureId, int displayId) {
        // Dispatch gesture motions to specified  display with GestureDescription..
        // Use AccessibilityService.dispatchGesture() instead of Instrumentation.sendPointerSync()
        // because accessibility services read gesture events upstream from the point where
        // sendPointerSync() injects events.
        mService.runOnServiceSync(() ->
        mService.dispatchGesture(gesture, mGestureDispatchCallback, null));
        verify(mGestureDispatchCallback, timeout(GESTURE_DISPATCH_TIMEOUT_MS).atLeastOnce())
                .onCompleted(any());

        // Wait for gesture recognizer, and check recognized gesture.
        mService.assertGestureReceived(gestureId, displayId);
    }
    /** Create a path from startPoint, moving by delta1, then delta2. (delta2 may be null.) */
    Path linePath(Point startPoint, Point delta1, Point delta2) {
        Path path = new Path();
        path.moveTo(startPoint.x, startPoint.y);
        path.lineTo(startPoint.x + delta1.x, startPoint.y + delta1.y);
        if (delta2 != null) {
            path.lineTo(startPoint.x + delta2.x, startPoint.y + delta2.y);
        }
        return path;
    }

    @Test
    @AppModeFull
    public void testVerifyGestureTouchEvent() {
        if (!mHasTouchScreen || !mScreenBigEnough) {
            return;
        }

        verifyGestureTouchEventOnDisplay(Display.DEFAULT_DISPLAY);
        verifyMultiFingerGestureTouchEventOnDisplay(Display.DEFAULT_DISPLAY);
    }

    @Test
    @AppModeFull
    public void testVerifyGestureTouchEventOnVirtualDisplay() throws Exception {
        assumeTrue(sInstrumentation.getContext().getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS));
        if (!mHasTouchScreen || !mScreenBigEnough) {
            return;
        }

        try (final VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
            final int displayId = displaySession.createDisplayWithDefaultDisplayMetricsAndWait(
                    sInstrumentation.getTargetContext(),
                    false).getDisplayId();

            // Launches an activity on virtual display to meet a real situation.
            final Activity activity = launchActivityOnSpecifiedDisplayAndWaitForItToBeOnscreen(
                    sInstrumentation, sUiAutomation, AccessibilityWindowQueryActivity.class,
                    displayId);
            try {
                verifyGestureTouchEventOnDisplay(displayId);
                verifyMultiFingerGestureTouchEventOnDisplay(displayId);
            } finally {
                sInstrumentation.runOnMainSync(() -> {
                    activity.finish();
                });
                sInstrumentation.waitForIdleSync();
            }
        }
    }

    private void verifyGestureTouchEventOnDisplay(int displayId) {
        assertEventAfterGesture(swipe(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);

        assertEventAfterGesture(tap(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START,
                AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);

        assertEventAfterGesture(doubleTap(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);

        assertEventAfterGesture(doubleTapAndHold(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
    }

    private void verifyMultiFingerGestureTouchEventOnDisplay(int displayId) {
        assertEventAfterGesture(twoFingerSingleTap(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
        assertEventAfterGesture(twoFingerDoubleTap(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
        assertEventAfterGesture(twoFingerTripleTap(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);

        assertEventAfterGesture(threeFingerSingleTap(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
        assertEventAfterGesture(threeFingerDoubleTap(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
        assertEventAfterGesture(threeFingerTripleTap(displayId),
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
    }

    @Test
    @AppModeFull
    public void testDispatchGesture_privateDisplay_gestureCancelled() throws Exception{
        assumeTrue(sInstrumentation.getContext().getPackageManager()
            .hasSystemFeature(PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS));
        if (!mHasTouchScreen || !mScreenBigEnough) {
            return;
        }

        try (final VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
            final int displayId = displaySession.createDisplayWithDefaultDisplayMetricsAndWait
                    (sInstrumentation.getTargetContext(),
                            true).getDisplayId();
            GestureDescription gesture = swipe(displayId);
            mService.clearGestures();
            mService.runOnServiceSync(() ->
                    mService.dispatchGesture(gesture, mGestureDispatchCallback, null));
            verify(mGestureDispatchCallback, timeout(GESTURE_DISPATCH_TIMEOUT_MS).atLeastOnce())
                    .onCancelled(any());
        }
    }

    /** Test touch for accessibility events */
    private void assertEventAfterGesture(GestureDescription gesture, int... events) {
        mService.clearEvents();
        mService.runOnServiceSync(
                () -> mService.dispatchGesture(gesture, mGestureDispatchCallback, null));
        verify(mGestureDispatchCallback, timeout(EVENT_DISPATCH_TIMEOUT_MS).atLeastOnce())
                .onCompleted(any());

        mService.assertPropagated(events);
    }

    private GestureDescription swipe(int displayId) {
        StrokeDescription swipe = new StrokeDescription(
                linePath(mCenter, p(0, mStrokeLenPxY), null), 0, STROKE_MS, false);
        return getGestureBuilder(displayId, swipe).build();
    }

    private GestureDescription tap(int displayId) {
        StrokeDescription tap = click(mTapLocation);
        return getGestureBuilder(displayId, tap).build();
    }

    private GestureDescription doubleTap(int displayId) {
        StrokeDescription tap1 = click(mTapLocation);
        StrokeDescription tap2 = startingAt(endTimeOf(tap1) + 20, click(mTapLocation));
        return getGestureBuilder(displayId, tap1, tap2).build();
    }

    private GestureDescription doubleTapAndHold(int displayId) {
        StrokeDescription tap1 = click(mTapLocation);
        StrokeDescription tap2 = startingAt(endTimeOf(tap1) + 20, longClick(mTapLocation));
        return getGestureBuilder(displayId, tap1, tap2).build();
    }

    private GestureDescription twoFingerSingleTap(int displayId) {
        return multiFingerMultiTap(2, 1, displayId);
    }

    private GestureDescription twoFingerTripleTapAndHold(int displayId) {
        return multiFingerMultiTapAndHold(2, 3, displayId);
    }

    private GestureDescription twoFingerDoubleTap(int displayId) {
        return multiFingerMultiTap(2, 2, displayId);
    }

    private GestureDescription twoFingerDoubleTapAndHold(int displayId) {
        return multiFingerMultiTapAndHold(2, 2, displayId);
    }
 
    private GestureDescription twoFingerTripleTap(int displayId) {
        return multiFingerMultiTap(2, 3, displayId);
    }

    private GestureDescription threeFingerSingleTap(int displayId) {
        return multiFingerMultiTap(3, 1, displayId);
    }

    private GestureDescription threeFingerSingleTapAndHold(int displayId) {
        return multiFingerMultiTapAndHold(3, 1, displayId);
    }

    private GestureDescription threeFingerDoubleTap(int displayId) {
        return multiFingerMultiTap(3, 2, displayId);
    }

    private GestureDescription threeFingerDoubleTapAndHold(int displayId) {
        return multiFingerMultiTapAndHold(3, 2, displayId);
    }

    private GestureDescription threeFingerTripleTap(int displayId) {
        return multiFingerMultiTap(3, 3, displayId);
    }

    private GestureDescription threeFingerTripleTapAndHold(int displayId) {
        return multiFingerMultiTapAndHold(3, 3, displayId);
    }

    private GestureDescription fourFingerSingleTap(int displayId) {
        return multiFingerMultiTap(4, 1, displayId);
    }

    private GestureDescription fourFingerDoubleTap(int displayId) {
        return multiFingerMultiTap(4, 2, displayId);
    }

    private GestureDescription fourFingerDoubleTapAndHold(int displayId) {
        return multiFingerMultiTapAndHold(4, 2, displayId);
    }

    private GestureDescription fourFingerTripleTap(int displayId) {
        return multiFingerMultiTap(4, 3, displayId);
    }

    private GestureDescription multiFingerMultiTap(int fingerCount, int tapCount, int displayId) {
        // We dispatch the first finger, base, placed at left down side by an offset
        // from the center of the display and the rest ones at right up side by delta
        // from the base.
        final PointF base = diff(mTapLocation, FINGER_OFFSET_PX);
        return GestureUtils.multiFingerMultiTap(
                base, FINGER_OFFSET_PX, fingerCount, tapCount, /* slop= */ 0, displayId);
    }

    private GestureDescription multiFingerMultiTapAndHold(
            int fingerCount, int tapCount, int displayId) {
        // We dispatch the first finger, base, placed at left down side by an offset
        // from the center of the display and the rest ones at right up side by delta
        // from the base.
        final PointF base = diff(mTapLocation, FINGER_OFFSET_PX);
        return GestureUtils.multiFingerMultiTapAndHold(
                base, FINGER_OFFSET_PX, fingerCount, tapCount, /* slop= */ 0, displayId);
    }

    private GestureDescription MultiFingerSwipe(
            int displayId, int fingerCount, float dx, float dy) {
        float fingerOffset = 10f;
        GestureDescription.Builder builder = new GestureDescription.Builder();
        builder.setDisplayId(displayId);

        // MultiFingerSwipe.java scales delta thresholds for multifinger gestures by multiplying
        // the touch slop with the amount of fingers used in the gesture.
        // With higher touch slops than default (8dp), the swipe lengths and duration needs to be
        // adjusted in order for the a11y-service to interpret it as a swipe gesture.
        float slopAdjustedDx = adjustStrokeDeltaForSlop(fingerCount, dx);
        float slopAdjustedDy = adjustStrokeDeltaForSlop(fingerCount, dy);
        long slopAdjustedStrokeDuration = Math.min(
                adjustStrokeDurationForSlop(STROKE_MS, dx, slopAdjustedDx),
                adjustStrokeDurationForSlop(STROKE_MS, dy, slopAdjustedDy));

        final PointF tapLocation = new PointF(mTapLocation);
        final float locationOffsetX = (fingerCount - 1) * fingerOffset;
        tapLocation.offset(dx > 0 ? -locationOffsetX : locationOffsetX , 0);
        for (int currentFinger = 0; currentFinger < fingerCount; ++currentFinger) {
            // Make sure adjustments don't take us outside of screen boundaries.
            assertTrue(slopAdjustedDx + (fingerOffset * currentFinger) < (mMaxAdjustedStrokeLenPxX
                    + locationOffsetX));
            assertTrue(slopAdjustedDy < mMaxAdjustedStrokeLenPxY);
            builder.addStroke(
                    GestureUtils.swipe(
                            add(tapLocation, fingerOffset * currentFinger, 0),
                            add(tapLocation, slopAdjustedDx + (fingerOffset * currentFinger),
                                    slopAdjustedDy),
                            slopAdjustedStrokeDuration));
        }
        return builder.build();
    }

    private float adjustStrokeDeltaForSlop(int fingerCount, float strokeDelta) {
        if (strokeDelta > 0.0f) {
            return Math.max(strokeDelta, fingerCount * mScaledTouchSlop + 10);
        } else if (strokeDelta < 0.0f) {
            return Math.min(strokeDelta, -(fingerCount * mScaledTouchSlop + 10));
        }
        return strokeDelta;
    }

    private long adjustStrokeDurationForSlop(
            long strokeDuration, float unadjustedDelta, float adjustedDelta) {
        if (unadjustedDelta == 0.0f || adjustedDelta == 0.0f) {
            return strokeDuration;
        }
        float absUnadjustedDelta = Math.abs(unadjustedDelta);
        float absAdjustedDelta = Math.abs(adjustedDelta);
        // Adjusted delta in this case, has additional delta added due to touch slop.
        return Math.round((float) strokeDuration * absUnadjustedDelta / absAdjustedDelta);
    }
}
