summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java80
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java87
2 files changed, 160 insertions, 7 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 9c84c048003d..f85ef43f99fe 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -44,6 +44,8 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.provider.Settings;
import android.util.Log;
import android.util.MathUtils;
@@ -279,7 +281,8 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
return mTempPointerProperties;
}
- private void transitionTo(State state) {
+ @VisibleForTesting
+ void transitionTo(State state) {
if (DEBUG_STATE_TRANSITIONS) {
Slog.i(mLogTag,
(State.nameOf(mCurrentState) + " -> " + State.nameOf(state)
@@ -287,6 +290,9 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
.replace(getClass().getName(), ""));
}
mPreviousState = mCurrentState;
+ if (state == mPanningScalingState) {
+ mPanningScalingState.prepareForState();
+ }
mCurrentState = state;
}
@@ -317,18 +323,34 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
final class PanningScalingState extends SimpleOnGestureListener
implements OnScaleGestureListener, State {
+ private final Context mContext;
private final ScaleGestureDetector mScaleGestureDetector;
private final GestureDetector mScrollGestureDetector;
final float mScalingThreshold;
float mInitialScaleFactor = -1;
- boolean mScaling;
+ @VisibleForTesting boolean mScaling;
+
+ /**
+ * Whether it needs to detect the target scale passes
+ * {@link FullScreenMagnificationController#getPersistedScale} during panning scale.
+ */
+ @VisibleForTesting boolean mDetectingPassPersistedScale;
+
+ // The threshold for relative difference from given scale to persisted scale. If the
+ // difference >= threshold, we can start detecting if the scale passes the persisted
+ // scale during panning.
+ @VisibleForTesting static final float CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD = 0.2f;
+ // The threshold for relative difference from given scale to persisted scale. If the
+ // difference < threshold, we can decide that the scale passes the persisted scale.
+ @VisibleForTesting static final float PASSING_PERSISTED_SCALE_THRESHOLD = 0.01f;
PanningScalingState(Context context) {
final TypedValue scaleValue = new TypedValue();
context.getResources().getValue(
R.dimen.config_screen_magnification_scaling_threshold,
scaleValue, false);
+ mContext = context;
mScalingThreshold = scaleValue.getFloat();
mScaleGestureDetector = new ScaleGestureDetector(context, this, Handler.getMain());
mScaleGestureDetector.setQuickScaleEnabled(false);
@@ -351,12 +373,59 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
}
}
+
+ void prepareForState() {
+ checkShouldDetectPassPersistedScale();
+ }
+
+ private void checkShouldDetectPassPersistedScale() {
+ if (mDetectingPassPersistedScale) {
+ return;
+ }
+
+ final float currentScale =
+ mFullScreenMagnificationController.getScale(mDisplayId);
+ final float persistedScale =
+ mFullScreenMagnificationController.getPersistedScale(mDisplayId);
+
+ mDetectingPassPersistedScale =
+ (abs(currentScale - persistedScale) / persistedScale)
+ >= CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
+ }
+
public void persistScaleAndTransitionTo(State state) {
mFullScreenMagnificationController.persistScale(mDisplayId);
clear();
transitionTo(state);
}
+ @VisibleForTesting
+ void setScaleAndClearIfNeeded(float scale, float pivotX, float pivotY) {
+ if (mDetectingPassPersistedScale) {
+ final float persistedScale =
+ mFullScreenMagnificationController.getPersistedScale(mDisplayId);
+ // If the scale passes the persisted scale during panning, perform a vibration
+ // feedback to user. Also, call {@link clear} to create a buffer zone so that
+ // user needs to panning more than {@link mScalingThreshold} to change scale again.
+ if (abs(scale - persistedScale) / persistedScale
+ < PASSING_PERSISTED_SCALE_THRESHOLD) {
+ scale = persistedScale;
+ final Vibrator vibrator = mContext.getSystemService(Vibrator.class);
+ if (vibrator != null) {
+ vibrator.vibrate(
+ VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK));
+ }
+ clear();
+ }
+ }
+
+ if (DEBUG_PANNING_SCALING) Slog.i(mLogTag, "Scaled content to: " + scale + "x");
+ mFullScreenMagnificationController.setScale(mDisplayId, scale, pivotX, pivotY, false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+
+ checkShouldDetectPassPersistedScale();
+ }
+
@Override
public boolean onScroll(MotionEvent first, MotionEvent second,
float distanceX, float distanceY) {
@@ -402,11 +471,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
scale = targetScale;
}
- final float pivotX = detector.getFocusX();
- final float pivotY = detector.getFocusY();
- if (DEBUG_PANNING_SCALING) Slog.i(mLogTag, "Scaled content to: " + scale + "x");
- mFullScreenMagnificationController.setScale(mDisplayId, scale, pivotX, pivotY, false,
- AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ setScaleAndClearIfNeeded(scale, detector.getFocusX(), detector.getFocusY());
return /* handled: */ true;
}
@@ -424,6 +489,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
public void clear() {
mInitialScaleFactor = -1;
mScaling = false;
+ mDetectingPassPersistedScale = false;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 51d3bae7d32c..306ce4dbf707 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -44,6 +44,8 @@ import android.annotation.NonNull;
import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.testing.TestableContext;
import android.util.DebugUtils;
import android.view.InputDevice;
@@ -507,6 +509,91 @@ public class FullScreenMagnificationGestureHandlerTest {
verify(mWindowMagnificationPromptController).showNotificationIfNeeded();
}
+ @Test
+ public void testTransitToPanningState_scaleDifferenceOverThreshold_startDetecting() {
+ final float scale = 2.0f;
+ final float threshold = FullScreenMagnificationGestureHandler.PanningScalingState
+ .CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
+ final float persistedScale = (1.0f + threshold) * scale + 1.0f;
+ mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ mFullScreenMagnificationController.persistScale(DISPLAY_0);
+ mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+
+ mMgh.transitionTo(mMgh.mPanningScalingState);
+
+ assertTrue(mMgh.mPanningScalingState.mDetectingPassPersistedScale);
+
+ mMgh.clearAndTransitionToStateDetecting();
+ mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
+ }
+
+ @Test
+ public void testTransitToPanningState_scaleDifferenceLessThanThreshold_doNotDetect() {
+ final float scale = 2.0f;
+ final float threshold = FullScreenMagnificationGestureHandler.PanningScalingState
+ .CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
+ final float persistedScale = (1.0f + threshold) * scale - 0.1f;
+ mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ mFullScreenMagnificationController.persistScale(DISPLAY_0);
+ mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+
+ mMgh.transitionTo(mMgh.mPanningScalingState);
+
+ assertFalse(mMgh.mPanningScalingState.mDetectingPassPersistedScale);
+
+ mMgh.clearAndTransitionToStateDetecting();
+ mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
+ }
+
+ @Test
+ public void testPanningScaleToPersistedScale_detecting_vibrateAndClear() {
+ Vibrator vibrator = mock(Vibrator.class);
+ mContext.addMockSystemService(Vibrator.class, vibrator);
+
+ mMgh.mPanningScalingState.mDetectingPassPersistedScale = true;
+
+ final float persistedScale =
+ mFullScreenMagnificationController.getPersistedScale(DISPLAY_0);
+
+ mMgh.transitionTo(mMgh.mPanningScalingState);
+ mMgh.mPanningScalingState.setScaleAndClearIfNeeded(persistedScale, DEFAULT_X, DEFAULT_Y);
+
+ verify(vibrator).vibrate(any(VibrationEffect.class));
+ assertFalse(mMgh.mPanningScalingState.mScaling);
+
+ mMgh.clearAndTransitionToStateDetecting();
+ mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
+ }
+
+ @Test
+ public void testPanningScaleOverThreshold_notDetecting_startDetecting() {
+ final float persistedScale =
+ mFullScreenMagnificationController.getPersistedScale(DISPLAY_0);
+
+ mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ mMgh.transitionTo(mMgh.mPanningScalingState);
+
+ final float threshold = FullScreenMagnificationGestureHandler.PanningScalingState
+ .CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
+ final float scale = (1.0f + threshold) * persistedScale + 1.0f;
+ mMgh.mPanningScalingState.setScaleAndClearIfNeeded(scale, DEFAULT_X, DEFAULT_Y);
+
+ assertTrue(mMgh.mPanningScalingState.mDetectingPassPersistedScale);
+
+ mMgh.clearAndTransitionToStateDetecting();
+ mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
+ }
+
private void assertActionsInOrder(List<MotionEvent> actualEvents,
List<Integer> expectedActions) {
assertTrue(actualEvents.size() == expectedActions.size());