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

Commit e21d279b authored by Ryan Lin's avatar Ryan Lin Committed by Android (Google) Code Review
Browse files

Merge "Gesture detection for window magnification (1/n)"

parents 541baf0c 6259298c
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -31,6 +31,7 @@ import android.view.accessibility.AccessibilityEvent;


import com.android.server.LocalServices;
import com.android.server.LocalServices;
import com.android.server.accessibility.gestures.TouchExplorer;
import com.android.server.accessibility.gestures.TouchExplorer;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.policy.WindowManagerPolicy;


import java.util.ArrayList;
import java.util.ArrayList;
@@ -402,7 +403,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
                final boolean triggerable = (mEnabledFeatures
                final boolean triggerable = (mEnabledFeatures
                        & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0;
                        & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0;
                MagnificationGestureHandler magnificationGestureHandler =
                MagnificationGestureHandler magnificationGestureHandler =
                        new MagnificationGestureHandler(displayContext,
                        new FullScreenMagnificationGestureHandler(displayContext,
                                mAms.getMagnificationController(),
                                mAms.getMagnificationController(),
                                detectControlGestures, triggerable, displayId);
                                detectControlGestures, triggerable, displayId);
                addFirstEventHandler(displayId, magnificationGestureHandler);
                addFirstEventHandler(displayId, magnificationGestureHandler);
+49 −46
Original line number Original line Diff line number Diff line
@@ -53,14 +53,16 @@ import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.ViewConfiguration;
import android.view.ViewConfiguration;


import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.accessibility.gestures.GestureUtils;
import com.android.server.accessibility.gestures.GestureUtils;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;


import java.util.ArrayDeque;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Queue;


/**
/**
 * This class handles magnification in response to touch events.
 * This class handles full screen magnification in response to touch events.
 *
 *
 * The behavior is as follows:
 * The behavior is as follows:
 *
 *
@@ -108,14 +110,14 @@ import java.util.Queue;
 * 7. The magnification scale will be persisted in settings and in the cloud.
 * 7. The magnification scale will be persisted in settings and in the cloud.
 */
 */
@SuppressWarnings("WeakerAccess")
@SuppressWarnings("WeakerAccess")
class MagnificationGestureHandler extends BaseEventStreamTransformation {
class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler {
    private static final String LOG_TAG = "MagnificationGestureHandler";
    private static final String LOG_TAG = "FullScreenMagnificationGestureHandler";


    private static final boolean DEBUG_ALL = false;
    private static final boolean DEBUG_ALL = false;
    private static final boolean DEBUG_STATE_TRANSITIONS = false || DEBUG_ALL;
    private static final boolean DEBUG_STATE_TRANSITIONS = false | DEBUG_ALL;
    private static final boolean DEBUG_DETECTING = false || DEBUG_ALL;
    private static final boolean DEBUG_DETECTING = false | DEBUG_ALL;
    private static final boolean DEBUG_PANNING_SCALING = false || DEBUG_ALL;
    private static final boolean DEBUG_PANNING_SCALING = false | DEBUG_ALL;
    private static final boolean DEBUG_EVENT_STREAM = false || DEBUG_ALL;
    private static final boolean DEBUG_EVENT_STREAM = false | DEBUG_ALL;


    // The MIN_SCALE is different from MagnificationController.MIN_SCALE due
    // The MIN_SCALE is different from MagnificationController.MIN_SCALE due
    // to AccessibilityService.MagnificationController#setScale() has
    // to AccessibilityService.MagnificationController#setScale() has
@@ -167,14 +169,14 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
     *                           {@code false} if it should ignore such triggers.
     *                           {@code false} if it should ignore such triggers.
     * @param displayId The logical display id.
     * @param displayId The logical display id.
     */
     */
    public MagnificationGestureHandler(Context context,
    FullScreenMagnificationGestureHandler(Context context,
            MagnificationController magnificationController,
            MagnificationController magnificationController,
            boolean detectTripleTap,
            boolean detectTripleTap,
            boolean detectShortcutTrigger,
            boolean detectShortcutTrigger,
            int displayId) {
            int displayId) {
        if (DEBUG_ALL) {
        if (DEBUG_ALL) {
            Log.i(LOG_TAG,
            Log.i(LOG_TAG,
                    "MagnificationGestureHandler(detectTripleTap = " + detectTripleTap
                    "FullScreenMagnificationGestureHandler(detectTripleTap = " + detectTripleTap
                            + ", detectShortcutTrigger = " + detectShortcutTrigger + ")");
                            + ", detectShortcutTrigger = " + detectShortcutTrigger + ")");
        }
        }


@@ -263,7 +265,8 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
        clearAndTransitionToStateDetecting();
        clearAndTransitionToStateDetecting();
    }
    }


    void notifyShortcutTriggered() {
    @Override
    public void notifyShortcutTriggered() {
        if (mDetectShortcutTrigger) {
        if (mDetectShortcutTrigger) {
            boolean wasMagnifying = mMagnificationController.resetIfNeeded(mDisplayId,
            boolean wasMagnifying = mMagnificationController.resetIfNeeded(mDisplayId,
                    /* animate */ true);
                    /* animate */ true);
@@ -383,10 +386,10 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
        float mInitialScaleFactor = -1;
        float mInitialScaleFactor = -1;
        boolean mScaling;
        boolean mScaling;


        public PanningScalingState(Context context) {
        PanningScalingState(Context context) {
            final TypedValue scaleValue = new TypedValue();
            final TypedValue scaleValue = new TypedValue();
            context.getResources().getValue(
            context.getResources().getValue(
                    com.android.internal.R.dimen.config_screen_magnification_scaling_threshold,
                    R.dimen.config_screen_magnification_scaling_threshold,
                    scaleValue, false);
                    scaleValue, false);
            mScalingThreshold = scaleValue.getFloat();
            mScalingThreshold = scaleValue.getFloat();
            mScaleGestureDetector = new ScaleGestureDetector(context, this, Handler.getMain());
            mScaleGestureDetector = new ScaleGestureDetector(context, this, Handler.getMain());
@@ -407,7 +410,6 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
            } else if (action == ACTION_UP || action == ACTION_CANCEL) {
            } else if (action == ACTION_UP || action == ACTION_CANCEL) {


                persistScaleAndTransitionTo(mDetectingState);
                persistScaleAndTransitionTo(mDetectingState);

            }
            }
        }
        }


@@ -489,10 +491,9 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {


        @Override
        @Override
        public String toString() {
        public String toString() {
            return "PanningScalingState{" +
            return "PanningScalingState{" + "mInitialScaleFactor=" + mInitialScaleFactor
                    "mInitialScaleFactor=" + mInitialScaleFactor +
                    + ", mScaling=" + mScaling
                    ", mScaling=" + mScaling +
                    + '}';
                    '}';
        }
        }
    }
    }


@@ -561,10 +562,10 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {


        @Override
        @Override
        public String toString() {
        public String toString() {
            return "ViewportDraggingState{" +
            return "ViewportDraggingState{"
                    "mZoomedInBeforeDrag=" + mZoomedInBeforeDrag +
                    + "mZoomedInBeforeDrag=" + mZoomedInBeforeDrag
                    ", mLastMoveOutsideMagnifiedRegion=" + mLastMoveOutsideMagnifiedRegion +
                    + ", mLastMoveOutsideMagnifiedRegion=" + mLastMoveOutsideMagnifiedRegion
                    '}';
                    + '}';
        }
        }
    }
    }


@@ -577,13 +578,14 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
        @Override
        @Override
        public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
        public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {


        	// Ensure that the state at the end of delegation is consistent with the last delegated
            // Ensures that the state at the end of delegation is consistent with the last delegated
            // UP/DOWN event in queue: still delegating if pointer is down, detecting otherwise
            // UP/DOWN event in queue: still delegating if pointer is down, detecting otherwise
            switch (event.getActionMasked()) {
            switch (event.getActionMasked()) {
                case ACTION_UP:
                case ACTION_UP:
                case ACTION_CANCEL: {
                case ACTION_CANCEL: {
                    transitionTo(mDetectingState);
                    transitionTo(mDetectingState);
                } break;
                }
                    break;


                case ACTION_DOWN: {
                case ACTION_DOWN: {
                    transitionTo(mDelegatingState);
                    transitionTo(mDelegatingState);
@@ -630,11 +632,11 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {


        @VisibleForTesting Handler mHandler = new Handler(Looper.getMainLooper(), this);
        @VisibleForTesting Handler mHandler = new Handler(Looper.getMainLooper(), this);


        public DetectingState(Context context) {
        DetectingState(Context context) {
            mLongTapMinDelay = ViewConfiguration.getLongPressTimeout();
            mLongTapMinDelay = ViewConfiguration.getLongPressTimeout();
            mMultiTapMaxDelay = ViewConfiguration.getDoubleTapTimeout()
            mMultiTapMaxDelay = ViewConfiguration.getDoubleTapTimeout()
                    + context.getResources().getInteger(
                    + context.getResources().getInteger(
                    com.android.internal.R.integer.config_screen_magnification_multi_tap_adjustment);
                    R.integer.config_screen_magnification_multi_tap_adjustment);
            mSwipeMinDistance = ViewConfiguration.get(context).getScaledTouchSlop();
            mSwipeMinDistance = ViewConfiguration.get(context).getScaledTouchSlop();
            mMultiTapMaxDistance = ViewConfiguration.get(context).getScaledDoubleTapSlop();
            mMultiTapMaxDistance = ViewConfiguration.get(context).getScaledDoubleTapSlop();
        }
        }
@@ -913,11 +915,11 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {


        @Override
        @Override
        public String toString() {
        public String toString() {
            return "DetectingState{" +
            return "DetectingState{"
                    "tapCount()=" + tapCount() +
                    + "tapCount()=" + tapCount()
                    ", mShortcutTriggered=" + mShortcutTriggered +
                    + ", mShortcutTriggered=" + mShortcutTriggered
                    ", mDelayedEventQueue=" + MotionEventInfo.toString(mDelayedEventQueue) +
                    + ", mDelayedEventQueue=" + MotionEventInfo.toString(mDelayedEventQueue)
                    '}';
                    + '}';
        }
        }


        void toggleShortcutTriggered() {
        void toggleShortcutTriggered() {
@@ -986,18 +988,18 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {


    @Override
    @Override
    public String toString() {
    public String toString() {
        return "MagnificationGesture{" +
        return "MagnificationGesture{"
                "mDetectingState=" + mDetectingState +
                + "mDetectingState=" + mDetectingState
                ", mDelegatingState=" + mDelegatingState +
                + ", mDelegatingState=" + mDelegatingState
                ", mMagnifiedInteractionState=" + mPanningScalingState +
                + ", mMagnifiedInteractionState=" + mPanningScalingState
                ", mViewportDraggingState=" + mViewportDraggingState +
                + ", mViewportDraggingState=" + mViewportDraggingState
                ", mDetectTripleTap=" + mDetectTripleTap +
                + ", mDetectTripleTap=" + mDetectTripleTap
                ", mDetectShortcutTrigger=" + mDetectShortcutTrigger +
                + ", mDetectShortcutTrigger=" + mDetectShortcutTrigger
                ", mCurrentState=" + State.nameOf(mCurrentState) +
                + ", mCurrentState=" + State.nameOf(mCurrentState)
                ", mPreviousState=" + State.nameOf(mPreviousState) +
                + ", mPreviousState=" + State.nameOf(mPreviousState)
                ", mMagnificationController=" + mMagnificationController +
                + ", mMagnificationController=" + mMagnificationController
                ", mDisplayId=" + mDisplayId +
                + ", mDisplayId=" + mDisplayId
                '}';
                + '}';
    }
    }


    private static final class MotionEventInfo {
    private static final class MotionEventInfo {
@@ -1085,9 +1087,10 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
     */
     */
    private static class ScreenStateReceiver extends BroadcastReceiver {
    private static class ScreenStateReceiver extends BroadcastReceiver {
        private final Context mContext;
        private final Context mContext;
        private final MagnificationGestureHandler mGestureHandler;
        private final FullScreenMagnificationGestureHandler mGestureHandler;


        public ScreenStateReceiver(Context context, MagnificationGestureHandler gestureHandler) {
        ScreenStateReceiver(Context context,
                FullScreenMagnificationGestureHandler gestureHandler) {
            mContext = context;
            mContext = context;
            mGestureHandler = gestureHandler;
            mGestureHandler = gestureHandler;
        }
        }
+30 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2019 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 com.android.server.accessibility.magnification;

import com.android.server.accessibility.BaseEventStreamTransformation;

/**
 * A base class that detects gestures and defines common methods for magnification.
 */
public abstract class MagnificationGestureHandler extends BaseEventStreamTransformation {

    /**
     * Called when the shortcut target is magnification.
     */
    public abstract void notifyShortcutTriggered();
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -80,7 +80,7 @@ public class AccessibilityInputFilterTest {
    // The expected order of EventStreamTransformations.
    // The expected order of EventStreamTransformations.
    private final Class[] mExpectedEventHandlerTypes =
    private final Class[] mExpectedEventHandlerTypes =
            {KeyboardInterceptor.class, MotionEventInjector.class,
            {KeyboardInterceptor.class, MotionEventInjector.class,
                    MagnificationGestureHandler.class, TouchExplorer.class,
                    FullScreenMagnificationGestureHandler.class, TouchExplorer.class,
                    AutoclickController.class, AccessibilityInputFilter.class};
                    AutoclickController.class, AccessibilityInputFilter.class};


    private MagnificationController mMockMagnificationController;
    private MagnificationController mMockMagnificationController;
+11 −9
Original line number Original line Diff line number Diff line
@@ -59,7 +59,7 @@ import org.junit.runner.RunWith;
import java.util.function.IntConsumer;
import java.util.function.IntConsumer;


/**
/**
 * Tests the state transitions of {@link MagnificationGestureHandler}
 * Tests the state transitions of {@link FullScreenMagnificationGestureHandler}
 *
 *
 * Here's a dot graph describing the transitions being tested:
 * Here's a dot graph describing the transitions being tested:
 * {@code
 * {@code
@@ -87,7 +87,7 @@ import java.util.function.IntConsumer;
 * }
 * }
 */
 */
@RunWith(AndroidJUnit4.class)
@RunWith(AndroidJUnit4.class)
public class MagnificationGestureHandlerTest {
public class FullScreenMagnificationGestureHandlerTest {


    public static final int STATE_IDLE = 1;
    public static final int STATE_IDLE = 1;
    public static final int STATE_ZOOMED = 2;
    public static final int STATE_ZOOMED = 2;
@@ -113,7 +113,7 @@ public class MagnificationGestureHandlerTest {
    MagnificationController mMagnificationController;
    MagnificationController mMagnificationController;


    private OffsettableClock mClock;
    private OffsettableClock mClock;
    private MagnificationGestureHandler mMgh;
    private FullScreenMagnificationGestureHandler mMgh;
    private TestHandler mHandler;
    private TestHandler mHandler;


    private long mLastDownTime = Integer.MIN_VALUE;
    private long mLastDownTime = Integer.MIN_VALUE;
@@ -154,16 +154,17 @@ public class MagnificationGestureHandlerTest {
    }
    }


    @NonNull
    @NonNull
    private MagnificationGestureHandler newInstance(boolean detectTripleTap,
    private FullScreenMagnificationGestureHandler newInstance(boolean detectTripleTap,
            boolean detectShortcutTrigger) {
            boolean detectShortcutTrigger) {
        MagnificationGestureHandler h = new MagnificationGestureHandler(
        FullScreenMagnificationGestureHandler h = new FullScreenMagnificationGestureHandler(
                mContext, mMagnificationController,
                mContext, mMagnificationController,
                detectTripleTap, detectShortcutTrigger, DISPLAY_0);
                detectTripleTap, detectShortcutTrigger, DISPLAY_0);
        mHandler = new TestHandler(h.mDetectingState, mClock) {
        mHandler = new TestHandler(h.mDetectingState, mClock) {
            @Override
            @Override
            protected String messageToString(Message m) {
            protected String messageToString(Message m) {
                return DebugUtils.valueToString(
                return DebugUtils.valueToString(
                        MagnificationGestureHandler.DetectingState.class, "MESSAGE_", m.what);
                        FullScreenMagnificationGestureHandler.DetectingState.class, "MESSAGE_",
                        m.what);
            }
            }
        };
        };
        h.mDetectingState.mHandler = mHandler;
        h.mDetectingState.mHandler = mHandler;
@@ -541,7 +542,8 @@ public class MagnificationGestureHandlerTest {
    }
    }


    private static String stateToString(int state) {
    private static String stateToString(int state) {
        return DebugUtils.valueToString(MagnificationGestureHandlerTest.class, "STATE_", state);
        return DebugUtils.valueToString(FullScreenMagnificationGestureHandlerTest.class, "STATE_",
                state);
    }
    }


    private void tap() {
    private void tap() {