Gesture detection for window magnification (1/n)

To change the gesturehandler easily for different magnification mode,
we rename MagnificationGestureHandler to FullScreenMagnificationGestureHandler
and add a common class MagnificationGestureHandler. We will create
different MagnificationGestureHandler based on magnification mode.

Bug: 146400227
Test:FullScreenMagnificationGestureHandlerTest
Test: AccessibilityInputFilterTest.java
Change-Id: Ib7a45300a1f1323e1005b89694bb66932b22ab1b
This commit is contained in:
ryanlwlin
2019-12-24 11:19:20 +08:00
parent 2cc1d117a8
commit 6259298cd8
5 changed files with 93 additions and 57 deletions

View File

@@ -31,6 +31,7 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.server.LocalServices;
import com.android.server.accessibility.gestures.TouchExplorer;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;
import com.android.server.policy.WindowManagerPolicy;
import java.util.ArrayList;
@@ -402,7 +403,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
final boolean triggerable = (mEnabledFeatures
& FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0;
MagnificationGestureHandler magnificationGestureHandler =
new MagnificationGestureHandler(displayContext,
new FullScreenMagnificationGestureHandler(displayContext,
mAms.getMagnificationController(),
detectControlGestures, triggerable, displayId);
addFirstEventHandler(displayId, magnificationGestureHandler);

View File

@@ -53,14 +53,16 @@ import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.ViewConfiguration;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.accessibility.gestures.GestureUtils;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;
import java.util.ArrayDeque;
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:
*
@@ -108,14 +110,14 @@ import java.util.Queue;
* 7. The magnification scale will be persisted in settings and in the cloud.
*/
@SuppressWarnings("WeakerAccess")
class MagnificationGestureHandler extends BaseEventStreamTransformation {
private static final String LOG_TAG = "MagnificationGestureHandler";
class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler {
private static final String LOG_TAG = "FullScreenMagnificationGestureHandler";
private static final boolean DEBUG_ALL = false;
private static final boolean DEBUG_STATE_TRANSITIONS = 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_EVENT_STREAM = 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_PANNING_SCALING = false | DEBUG_ALL;
private static final boolean DEBUG_EVENT_STREAM = false | DEBUG_ALL;
// The MIN_SCALE is different from MagnificationController.MIN_SCALE due
// to AccessibilityService.MagnificationController#setScale() has
@@ -167,14 +169,14 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
* {@code false} if it should ignore such triggers.
* @param displayId The logical display id.
*/
public MagnificationGestureHandler(Context context,
FullScreenMagnificationGestureHandler(Context context,
MagnificationController magnificationController,
boolean detectTripleTap,
boolean detectShortcutTrigger,
int displayId) {
if (DEBUG_ALL) {
Log.i(LOG_TAG,
"MagnificationGestureHandler(detectTripleTap = " + detectTripleTap
"FullScreenMagnificationGestureHandler(detectTripleTap = " + detectTripleTap
+ ", detectShortcutTrigger = " + detectShortcutTrigger + ")");
}
@@ -263,7 +265,8 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
clearAndTransitionToStateDetecting();
}
void notifyShortcutTriggered() {
@Override
public void notifyShortcutTriggered() {
if (mDetectShortcutTrigger) {
boolean wasMagnifying = mMagnificationController.resetIfNeeded(mDisplayId,
/* animate */ true);
@@ -383,10 +386,10 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
float mInitialScaleFactor = -1;
boolean mScaling;
public PanningScalingState(Context context) {
PanningScalingState(Context context) {
final TypedValue scaleValue = new TypedValue();
context.getResources().getValue(
com.android.internal.R.dimen.config_screen_magnification_scaling_threshold,
R.dimen.config_screen_magnification_scaling_threshold,
scaleValue, false);
mScalingThreshold = scaleValue.getFloat();
mScaleGestureDetector = new ScaleGestureDetector(context, this, Handler.getMain());
@@ -407,7 +410,6 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
} else if (action == ACTION_UP || action == ACTION_CANCEL) {
persistScaleAndTransitionTo(mDetectingState);
}
}
@@ -489,10 +491,9 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
public String toString() {
return "PanningScalingState{" +
"mInitialScaleFactor=" + mInitialScaleFactor +
", mScaling=" + mScaling +
'}';
return "PanningScalingState{" + "mInitialScaleFactor=" + mInitialScaleFactor
+ ", mScaling=" + mScaling
+ '}';
}
}
@@ -544,7 +545,7 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
clear();
transitionTo(mDetectingState);
}
break;
break;
case ACTION_DOWN:
case ACTION_POINTER_UP: {
@@ -561,10 +562,10 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
public String toString() {
return "ViewportDraggingState{" +
"mZoomedInBeforeDrag=" + mZoomedInBeforeDrag +
", mLastMoveOutsideMagnifiedRegion=" + mLastMoveOutsideMagnifiedRegion +
'}';
return "ViewportDraggingState{"
+ "mZoomedInBeforeDrag=" + mZoomedInBeforeDrag
+ ", mLastMoveOutsideMagnifiedRegion=" + mLastMoveOutsideMagnifiedRegion
+ '}';
}
}
@@ -577,16 +578,17 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
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
switch (event.getActionMasked()) {
case ACTION_UP:
case ACTION_CANCEL: {
transitionTo(mDetectingState);
} break;
}
break;
case ACTION_DOWN: {
transitionTo(mDelegatingState);
transitionTo(mDelegatingState);
mLastDelegatedDownEventTime = event.getDownTime();
} break;
}
@@ -630,11 +632,11 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@VisibleForTesting Handler mHandler = new Handler(Looper.getMainLooper(), this);
public DetectingState(Context context) {
DetectingState(Context context) {
mLongTapMinDelay = ViewConfiguration.getLongPressTimeout();
mMultiTapMaxDelay = ViewConfiguration.getDoubleTapTimeout()
+ 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();
mMultiTapMaxDistance = ViewConfiguration.get(context).getScaledDoubleTapSlop();
}
@@ -913,11 +915,11 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
public String toString() {
return "DetectingState{" +
"tapCount()=" + tapCount() +
", mShortcutTriggered=" + mShortcutTriggered +
", mDelayedEventQueue=" + MotionEventInfo.toString(mDelayedEventQueue) +
'}';
return "DetectingState{"
+ "tapCount()=" + tapCount()
+ ", mShortcutTriggered=" + mShortcutTriggered
+ ", mDelayedEventQueue=" + MotionEventInfo.toString(mDelayedEventQueue)
+ '}';
}
void toggleShortcutTriggered() {
@@ -986,18 +988,18 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
public String toString() {
return "MagnificationGesture{" +
"mDetectingState=" + mDetectingState +
", mDelegatingState=" + mDelegatingState +
", mMagnifiedInteractionState=" + mPanningScalingState +
", mViewportDraggingState=" + mViewportDraggingState +
", mDetectTripleTap=" + mDetectTripleTap +
", mDetectShortcutTrigger=" + mDetectShortcutTrigger +
", mCurrentState=" + State.nameOf(mCurrentState) +
", mPreviousState=" + State.nameOf(mPreviousState) +
", mMagnificationController=" + mMagnificationController +
", mDisplayId=" + mDisplayId +
'}';
return "MagnificationGesture{"
+ "mDetectingState=" + mDetectingState
+ ", mDelegatingState=" + mDelegatingState
+ ", mMagnifiedInteractionState=" + mPanningScalingState
+ ", mViewportDraggingState=" + mViewportDraggingState
+ ", mDetectTripleTap=" + mDetectTripleTap
+ ", mDetectShortcutTrigger=" + mDetectShortcutTrigger
+ ", mCurrentState=" + State.nameOf(mCurrentState)
+ ", mPreviousState=" + State.nameOf(mPreviousState)
+ ", mMagnificationController=" + mMagnificationController
+ ", mDisplayId=" + mDisplayId
+ '}';
}
private static final class MotionEventInfo {
@@ -1085,9 +1087,10 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
*/
private static class ScreenStateReceiver extends BroadcastReceiver {
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;
mGestureHandler = gestureHandler;
}

View File

@@ -0,0 +1,30 @@
/*
* 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();
}

View File

@@ -80,7 +80,7 @@ public class AccessibilityInputFilterTest {
// The expected order of EventStreamTransformations.
private final Class[] mExpectedEventHandlerTypes =
{KeyboardInterceptor.class, MotionEventInjector.class,
MagnificationGestureHandler.class, TouchExplorer.class,
FullScreenMagnificationGestureHandler.class, TouchExplorer.class,
AutoclickController.class, AccessibilityInputFilter.class};
private MagnificationController mMockMagnificationController;

View File

@@ -59,7 +59,7 @@ import org.junit.runner.RunWith;
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:
* {@code
@@ -87,7 +87,7 @@ import java.util.function.IntConsumer;
* }
*/
@RunWith(AndroidJUnit4.class)
public class MagnificationGestureHandlerTest {
public class FullScreenMagnificationGestureHandlerTest {
public static final int STATE_IDLE = 1;
public static final int STATE_ZOOMED = 2;
@@ -113,7 +113,7 @@ public class MagnificationGestureHandlerTest {
MagnificationController mMagnificationController;
private OffsettableClock mClock;
private MagnificationGestureHandler mMgh;
private FullScreenMagnificationGestureHandler mMgh;
private TestHandler mHandler;
private long mLastDownTime = Integer.MIN_VALUE;
@@ -154,16 +154,17 @@ public class MagnificationGestureHandlerTest {
}
@NonNull
private MagnificationGestureHandler newInstance(boolean detectTripleTap,
private FullScreenMagnificationGestureHandler newInstance(boolean detectTripleTap,
boolean detectShortcutTrigger) {
MagnificationGestureHandler h = new MagnificationGestureHandler(
FullScreenMagnificationGestureHandler h = new FullScreenMagnificationGestureHandler(
mContext, mMagnificationController,
detectTripleTap, detectShortcutTrigger, DISPLAY_0);
mHandler = new TestHandler(h.mDetectingState, mClock) {
@Override
protected String messageToString(Message m) {
return DebugUtils.valueToString(
MagnificationGestureHandler.DetectingState.class, "MESSAGE_", m.what);
FullScreenMagnificationGestureHandler.DetectingState.class, "MESSAGE_",
m.what);
}
};
h.mDetectingState.mHandler = mHandler;
@@ -541,7 +542,8 @@ public class MagnificationGestureHandlerTest {
}
private static String stateToString(int state) {
return DebugUtils.valueToString(MagnificationGestureHandlerTest.class, "STATE_", state);
return DebugUtils.valueToString(FullScreenMagnificationGestureHandlerTest.class, "STATE_",
state);
}
private void tap() {
@@ -591,7 +593,7 @@ public class MagnificationGestureHandlerTest {
private MotionEvent moveEvent(float x, float y) {
return fromTouchscreen(
MotionEvent.obtain(mLastDownTime, mClock.now(), ACTION_MOVE, x, y, 0));
MotionEvent.obtain(mLastDownTime, mClock.now(), ACTION_MOVE, x, y, 0));
}
private MotionEvent downEvent() {
@@ -638,7 +640,7 @@ public class MagnificationGestureHandlerTest {
/* action */ action,
/* pointerCount */ 2,
/* pointerProperties */ new MotionEvent.PointerProperties[] {
defPointerProperties, pointerProperties },
defPointerProperties, pointerProperties},
/* pointerCoords */ new MotionEvent.PointerCoords[] { defPointerCoords, pointerCoords },
/* metaState */ 0,
/* buttonState */ 0,