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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
Reference in New Issue
Block a user