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

Commit 364580d2 authored by Phil Weaver's avatar Phil Weaver Committed by Android (Google) Code Review
Browse files

Merge "Limit capabilities of a11y gesture dispatch." into nyc-mr1-dev

parents aefa8920 a8918f23
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -628,8 +628,8 @@ public abstract class AccessibilityService extends Service {
        if (connection == null) {
            return false;
        }
        List<MotionEvent> events = MotionEventGenerator.getMotionEventsFromGestureDescription(
                gesture, 100);
        List<GestureDescription.GestureStep> steps =
                MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, 100);
        try {
            synchronized (mLock) {
                mGestureStatusCallbackSequence++;
@@ -641,8 +641,8 @@ public abstract class AccessibilityService extends Service {
                            callback, handler);
                    mGestureStatusCallbackInfos.put(mGestureStatusCallbackSequence, callbackInfo);
                }
                connection.sendMotionEvents(mGestureStatusCallbackSequence,
                        new ParceledListSlice<>(events));
                connection.sendGesture(mGestureStatusCallbackSequence,
                        new ParceledListSlice<>(steps));
            }
        } catch (RemoteException re) {
            throw new RuntimeException(re);
+141 −19
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.annotation.NonNull;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
@@ -303,13 +305,37 @@ public final class GestureDescription {
        }
    }

    private static class TouchPoint {
    /**
     * The location of a finger for gesture dispatch
     *
     * @hide
     */
    public static class TouchPoint implements Parcelable {
        private static final int FLAG_IS_START_OF_PATH = 0x01;
        private static final int FLAG_IS_END_OF_PATH = 0x02;

        int mPathIndex;
        boolean mIsStartOfPath;
        boolean mIsEndOfPath;
        float mX;
        float mY;

        public TouchPoint() {
        }

        public TouchPoint(TouchPoint pointToCopy) {
            copyFrom(pointToCopy);
        }

        public TouchPoint(Parcel parcel) {
            mPathIndex = parcel.readInt();
            int startEnd = parcel.readInt();
            mIsStartOfPath = (startEnd & FLAG_IS_START_OF_PATH) != 0;
            mIsEndOfPath = (startEnd & FLAG_IS_END_OF_PATH) != 0;
            mX = parcel.readFloat();
            mY = parcel.readFloat();
        }

        void copyFrom(TouchPoint other) {
            mPathIndex = other.mPathIndex;
            mIsStartOfPath = other.mIsStartOfPath;
@@ -317,12 +343,94 @@ public final class GestureDescription {
            mX = other.mX;
            mY = other.mY;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(mPathIndex);
            int startEnd = mIsStartOfPath ? FLAG_IS_START_OF_PATH : 0;
            startEnd |= mIsEndOfPath ? FLAG_IS_END_OF_PATH : 0;
            dest.writeInt(startEnd);
            dest.writeFloat(mX);
            dest.writeFloat(mY);
        }

        public static final Parcelable.Creator<TouchPoint> CREATOR
                = new Parcelable.Creator<TouchPoint>() {
            public TouchPoint createFromParcel(Parcel in) {
                return new TouchPoint(in);
            }

            public TouchPoint[] newArray(int size) {
                return new TouchPoint[size];
            }
        };
    }

    /**
     * A step along a gesture. Contains all of the touch points at a particular time
     *
     * @hide
     */
    public static class GestureStep implements Parcelable {
        public long timeSinceGestureStart;
        public int numTouchPoints;
        public TouchPoint[] touchPoints;

        public GestureStep(long timeSinceGestureStart, int numTouchPoints,
                TouchPoint[] touchPointsToCopy) {
            this.timeSinceGestureStart = timeSinceGestureStart;
            this.numTouchPoints = numTouchPoints;
            this.touchPoints = new TouchPoint[numTouchPoints];
            for (int i = 0; i < numTouchPoints; i++) {
                this.touchPoints[i] = new TouchPoint(touchPointsToCopy[i]);
            }
        }

        public GestureStep(Parcel parcel) {
            timeSinceGestureStart = parcel.readLong();
            Parcelable[] parcelables =
                    parcel.readParcelableArray(TouchPoint.class.getClassLoader());
            numTouchPoints = (parcelables == null) ? 0 : parcelables.length;
            touchPoints = new TouchPoint[numTouchPoints];
            for (int i = 0; i < numTouchPoints; i++) {
                touchPoints[i] = (TouchPoint) parcelables[i];
            }
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeLong(timeSinceGestureStart);
            dest.writeParcelableArray(touchPoints, flags);
        }

        public static final Parcelable.Creator<GestureStep> CREATOR
                = new Parcelable.Creator<GestureStep>() {
            public GestureStep createFromParcel(Parcel in) {
                return new GestureStep(in);
            }

            public GestureStep[] newArray(int size) {
                return new GestureStep[size];
            }
        };
    }

    /**
     * Class to convert a GestureDescription to a series of MotionEvents.
     *
     * @hide
     */
    static class MotionEventGenerator {
    public static class MotionEventGenerator {
        /**
         * Constants used to initialize all MotionEvents
         */
@@ -341,38 +449,52 @@ public final class GestureDescription {
        private static PointerCoords[] sPointerCoords;
        private static PointerProperties[] sPointerProps;

        static List<MotionEvent> getMotionEventsFromGestureDescription(
        static List<GestureStep> getGestureStepsFromGestureDescription(
                GestureDescription description, int sampleTimeMs) {
            final List<MotionEvent> motionEvents = new ArrayList<>();
            final List<GestureStep> gestureSteps = new ArrayList<>();

            // Point data at each time we generate an event for
            final TouchPoint[] currentTouchPoints =
                    getCurrentTouchPoints(description.getStrokeCount());
            // Point data sent in last touch event
            int lastTouchPointSize = 0;
            final TouchPoint[] lastTouchPoints =
                    getLastTouchPoints(description.getStrokeCount());

            int currentTouchPointSize = 0;
            /* Loop through each time slice where there are touch points */
            long timeSinceGestureStart = 0;
            long nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart);
            while (nextKeyPointTime >= 0) {
                timeSinceGestureStart = (lastTouchPointSize == 0) ? nextKeyPointTime
                timeSinceGestureStart = (currentTouchPointSize == 0) ? nextKeyPointTime
                        : Math.min(nextKeyPointTime, timeSinceGestureStart + sampleTimeMs);
                int currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart,
                currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart,
                        currentTouchPoints);
                gestureSteps.add(new GestureStep(timeSinceGestureStart, currentTouchPointSize,
                        currentTouchPoints));

                /* Move to next time slice */
                nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart + 1);
            }
            return gestureSteps;
        }

        public static List<MotionEvent> getMotionEventsFromGestureSteps(List<GestureStep> steps) {
            final List<MotionEvent> motionEvents = new ArrayList<>();

            // Number of points in last touch event
            int lastTouchPointSize = 0;
            TouchPoint[] lastTouchPoints;

            for (int i = 0; i < steps.size(); i++) {
                GestureStep step = steps.get(i);
                int currentTouchPointSize = step.numTouchPoints;
                lastTouchPoints = getLastTouchPoints(
                        Math.max(lastTouchPointSize, currentTouchPointSize));

                appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize,
                        currentTouchPoints, currentTouchPointSize, timeSinceGestureStart);
                        step.touchPoints, currentTouchPointSize, step.timeSinceGestureStart);
                lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints,
                        lastTouchPointSize, currentTouchPoints, currentTouchPointSize,
                        timeSinceGestureStart);
                        lastTouchPointSize, step.touchPoints, currentTouchPointSize,
                        step.timeSinceGestureStart);
                lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints,
                        lastTouchPointSize, currentTouchPoints, currentTouchPointSize,
                        timeSinceGestureStart);

                /* Move to next time slice */
                nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart + 1);
                        lastTouchPointSize, step.touchPoints, currentTouchPointSize,
                        step.timeSinceGestureStart);
            }
            return motionEvents;
        }
+1 −1
Original line number Diff line number Diff line
@@ -88,5 +88,5 @@ interface IAccessibilityServiceConnection {

    void setSoftKeyboardCallbackEnabled(boolean enabled);

    void sendMotionEvents(int sequence, in ParceledListSlice events);
    void sendGesture(int sequence, in ParceledListSlice gestureSteps);
}
+12 −4
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
import android.Manifest;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.GestureDescription;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
@@ -2752,7 +2753,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
        }

        @Override
        public void sendMotionEvents(int sequence, ParceledListSlice events) {
        public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
            synchronized (mLock) {
                if (mSecurityPolicy.canPerformGestures(this)) {
                    final long endMillis =
@@ -2766,9 +2767,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
                        }
                    }
                    if (mMotionEventInjector != null) {
                        mMotionEventInjector.injectEvents((List<MotionEvent>) events.getList(),
                                mServiceInterface, sequence);
                        List<GestureDescription.GestureStep> steps = gestureSteps.getList();
                        List<MotionEvent> events = GestureDescription.MotionEventGenerator
                                .getMotionEventsFromGestureSteps(steps);
                        // Confirm that the motion events end with an UP event.
                        if (events.get(events.size() - 1).getAction() == MotionEvent.ACTION_UP) {
                            mMotionEventInjector.injectEvents(events, mServiceInterface, sequence);
                            return;
                        } else {
                            Slog.e(LOG_TAG, "Gesture is not well-formed");
                        }
                    } else {
                        Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
                    }