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

Commit 914944c8 authored by Roy Chou's avatar Roy Chou Committed by Android (Google) Code Review
Browse files

Merge "feat(onefingerpan): disable overscroll handelr on non-watch devices" into main

parents 8b1d33b5 618e191d
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -6969,9 +6969,17 @@
         Note that, indefinitely repeating vibrations are not allowed as shutdown vibrations. -->
    <string name="config_defaultShutdownVibrationFile" />

    <!-- Whether single finger panning is enabled when magnification is on -->
    <!-- Whether single finger panning is enabled by default when magnification is on -->
    <bool name="config_enable_a11y_magnification_single_panning">false</bool>

    <!-- Whether the overscroll handler is enabled when fullscreen magnification is on. When true,
         the magnification will change the scale if the user pans the magnifier horizontally past
         the edge of the screen, or delegate the touch events to the app if the user pans vertically
         past the edge. When false, the magnification will delegate the touch events to the app only
         when the users uses single finger to pan the magnifier past the edge of the screen,
         otherwise there are no extra actions. -->
    <bool name="config_enable_a11y_fullscreen_magnification_overscroll_handler">false</bool>

    <!-- The file path in which custom vibrations are provided for haptic feedbacks.
         If the device does not specify any such file path here, if the file path specified here
         does not exist, or if the contents of the file does not make up a valid customization
+3 −0
Original line number Diff line number Diff line
@@ -620,6 +620,9 @@
    <!-- width of the border of the magnification thumbnail -->
    <dimen name="accessibility_magnification_thumbnail_container_stroke_width">4dp</dimen>

    <!-- The distance from the edge within which the gesture is considered to be at the edge -->
    <dimen name="accessibility_fullscreen_magnification_gesture_edge_slop">12dp</dimen>

    <!-- The padding ratio of the Accessibility icon foreground drawable -->
    <item name="accessibility_icon_foreground_padding_ratio" type="dimen">21.88%</item>

+2 −0
Original line number Diff line number Diff line
@@ -5427,6 +5427,8 @@
  <java-symbol type="string" name="lockscreen_too_many_failed_attempts_countdown" />

  <java-symbol type="bool" name="config_enable_a11y_magnification_single_panning" />
  <java-symbol type="bool" name="config_enable_a11y_fullscreen_magnification_overscroll_handler" />
  <java-symbol type="dimen" name="accessibility_fullscreen_magnification_gesture_edge_slop" />

  <java-symbol type="string" name="config_hapticFeedbackCustomizationFile" />

+35 −26
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.accessibility.magnification;

import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL;
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
import static android.util.MathUtils.abs;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;

@@ -263,27 +264,27 @@ public class FullScreenMagnificationController implements

        @GuardedBy("mLock")
        boolean isAtEdge() {
            return isAtLeftEdge() || isAtRightEdge() || isAtTopEdge() || isAtBottomEdge();
            return isAtLeftEdge(0f) || isAtRightEdge(0f) || isAtTopEdge(0f) || isAtBottomEdge(0f);
        }

        @GuardedBy("mLock")
        boolean isAtLeftEdge() {
            return getOffsetX() == getMaxOffsetXLocked();
        boolean isAtLeftEdge(float slop) {
            return abs(getOffsetX() - getMaxOffsetXLocked()) <= slop;
        }

        @GuardedBy("mLock")
        boolean isAtRightEdge() {
            return getOffsetX() == getMinOffsetXLocked();
        boolean isAtRightEdge(float slop) {
            return abs(getOffsetX() - getMinOffsetXLocked()) <= slop;
        }

        @GuardedBy("mLock")
        boolean isAtTopEdge() {
            return getOffsetY() == getMaxOffsetYLocked();
        boolean isAtTopEdge(float slop) {
            return abs(getOffsetY() - getMaxOffsetYLocked()) <= slop;
        }

        @GuardedBy("mLock")
        boolean isAtBottomEdge() {
            return getOffsetY() == getMinOffsetYLocked();
        boolean isAtBottomEdge(float slop) {
            return abs(getOffsetY() - getMinOffsetYLocked()) <= slop;
        }

        @GuardedBy("mLock")
@@ -1298,7 +1299,7 @@ public class FullScreenMagnificationController implements
     * Returns whether the user is at one of the edges (left, right, top, bottom)
     * of the magnification viewport
     *
     * @param displayId
     * @param displayId The logical display id.
     * @return if user is at the edge of the view
     */
    public boolean isAtEdge(int displayId) {
@@ -1314,64 +1315,72 @@ public class FullScreenMagnificationController implements
    /**
     * Returns whether the user is at the left edge of the viewport
     *
     * @param displayId
     * @return if user is at left edge of view
     * @param displayId The logical display id.
     * @param slop The buffer distance in pixels from the left edge within that will be considered
     *             to be at the edge.
     * @return if user is considered at left edge of view
     */
    public boolean isAtLeftEdge(int displayId) {
    public boolean isAtLeftEdge(int displayId, float slop) {
        synchronized (mLock) {
            final DisplayMagnification display = mDisplays.get(displayId);
            if (display == null) {
                return false;
            }
            return display.isAtLeftEdge();
            return display.isAtLeftEdge(slop);
        }
    }

    /**
     * Returns whether the user is at the right edge of the viewport
     *
     * @param displayId
     * @return if user is at right edge of view
     * @param displayId The logical display id.
     * @param slop The buffer distance in pixels from the right edge within that will be considered
     *             to be at the edge.
     * @return if user is considered at right edge of view
     */
    public boolean isAtRightEdge(int displayId) {
    public boolean isAtRightEdge(int displayId, float slop) {
        synchronized (mLock) {
            final DisplayMagnification display = mDisplays.get(displayId);
            if (display == null) {
                return false;
            }
            return display.isAtRightEdge();
            return display.isAtRightEdge(slop);
        }
    }

    /**
     * Returns whether the user is at the top edge of the viewport
     *
     * @param displayId
     * @return if user is at top edge of view
     * @param displayId The logical display id.
     * @param slop The buffer distance in pixels from the top edge within that will be considered
     *             to be at the edge.
     * @return if user is considered at top edge of view
     */
    public boolean isAtTopEdge(int displayId) {
    public boolean isAtTopEdge(int displayId, float slop) {
        synchronized (mLock) {
            final DisplayMagnification display = mDisplays.get(displayId);
            if (display == null) {
                return false;
            }
            return display.isAtTopEdge();
            return display.isAtTopEdge(slop);
        }
    }

    /**
     * Returns whether the user is at the bottom edge of the viewport
     *
     * @param displayId
     * @return if user is at bottom edge of view
     * @param displayId The logical display id.
     * @param slop The buffer distance in pixels from the bottom edge within that will be considered
     *             to be at the edge.
     * @return if user is considered at bottom edge of view
     */
    public boolean isAtBottomEdge(int displayId) {
    public boolean isAtBottomEdge(int displayId, float slop) {
        synchronized (mLock) {
            final DisplayMagnification display = mDisplays.get(displayId);
            if (display == null) {
                return false;
            }
            return display.isAtBottomEdge();
            return display.isAtBottomEdge(slop);
        }
    }

+52 −34
Original line number Diff line number Diff line
@@ -171,7 +171,11 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH

    private final FullScreenMagnificationVibrationHelper mFullScreenMagnificationVibrationHelper;

    @VisibleForTesting final OverscrollHandler mOverscrollHandler;
    @VisibleForTesting
    @Nullable
    final OverscrollHandler mOverscrollHandler;

    private final float mOverscrollEdgeSlop;

    private final boolean mIsWatch;

@@ -308,7 +312,11 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
        mSinglePanningState = new SinglePanningState(context);
        mFullScreenMagnificationVibrationHelper = fullScreenMagnificationVibrationHelper;
        mOneFingerPanningSettingsProvider = oneFingerPanningSettingsProvider;
        mOverscrollHandler = new OverscrollHandler();
        boolean overscrollHandlerSupported = context.getResources().getBoolean(
                R.bool.config_enable_a11y_fullscreen_magnification_overscroll_handler);
        mOverscrollHandler = overscrollHandlerSupported ? new OverscrollHandler() : null;
        mOverscrollEdgeSlop = context.getResources().getDimensionPixelSize(
                R.dimen.accessibility_fullscreen_magnification_gesture_edge_slop);
        mIsWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);

        if (mDetectShortcutTrigger) {
@@ -523,16 +531,14 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
            if (action == ACTION_POINTER_UP
                    && event.getPointerCount() == 2 // includes the pointer currently being released
                    && mPreviousState == mViewportDraggingState) {
                // if feature flag is enabled, currently only true on watches
                if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()) {
                if (mOverscrollHandler != null) {
                    mOverscrollHandler.setScaleAndCenterToEdgeIfNeeded();
                    mOverscrollHandler.clearEdgeState();
                }
                persistScaleAndTransitionTo(mViewportDraggingState);
            } else if (action == ACTION_UP || action == ACTION_CANCEL) {
                onPanningFinished(event);
                // if feature flag is enabled, currently only true on watches
                if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()) {
                if (mOverscrollHandler != null) {
                    mOverscrollHandler.setScaleAndCenterToEdgeIfNeeded();
                    mOverscrollHandler.clearEdgeState();
                }
@@ -540,7 +546,6 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
            }
        }


        void prepareForState() {
            checkShouldDetectPassPersistedScale();
        }
@@ -611,7 +616,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
            onPan(second);
            mFullScreenMagnificationController.offsetMagnifiedRegion(mDisplayId, distanceX,
                    distanceY, AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
            if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()) {
            if (mOverscrollHandler != null) {
                mOverscrollHandler.onScrollStateChanged(first, second);
            }
            return /* event consumed: */ true;
@@ -1000,7 +1005,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
                                && event.getPointerCount() == 2) {
                            transitionToViewportDraggingStateAndClear(event);
                        } else if (isActivated() && event.getPointerCount() == 2) {
                            if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()
                            if (mOverscrollHandler != null
                                    && overscrollState(event, mFirstPointerDownLocation)
                                    == OVERSCROLL_VERTICAL_EDGE) {
                                transitionToDelegatingStateAndClear();
@@ -1011,9 +1016,13 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
                        } else if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()
                                && isActivated()
                                && event.getPointerCount() == 1) {
                            if (overscrollState(event, mFirstPointerDownLocation)
                            if (mOverscrollHandler != null
                                    && overscrollState(event, mFirstPointerDownLocation)
                                    == OVERSCROLL_VERTICAL_EDGE) {
                                transitionToDelegatingStateAndClear();
                            } else if (overscrollState(event, mFirstPointerDownLocation)
                                    != OVERSCROLL_NONE) {
                                transitionToDelegatingStateAndClear();
                            } else {
                                transitToSinglePanningStateAndClear();
                            }
@@ -1255,7 +1264,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
                        if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
                            transitionToViewportDraggingStateAndClear(event);
                        } else if (isActivated() && event.getPointerCount() == 2) {
                            if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()
                            if (mOverscrollHandler != null
                                    && overscrollState(event, mFirstPointerDownLocation)
                                    == OVERSCROLL_VERTICAL_EDGE) {
                                transitionToDelegatingStateAndClear();
@@ -1266,9 +1275,13 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
                        } else if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()
                                && isActivated()
                                && event.getPointerCount() == 1) {
                            if (overscrollState(event, mFirstPointerDownLocation)
                            if (mOverscrollHandler != null
                                    && overscrollState(event, mFirstPointerDownLocation)
                                    == OVERSCROLL_VERTICAL_EDGE) {
                                transitionToDelegatingStateAndClear();
                            } else if (overscrollState(event, mFirstPointerDownLocation)
                                    != OVERSCROLL_NONE) {
                                transitionToDelegatingStateAndClear();
                            } else {
                                transitToSinglePanningStateAndClear();
                            }
@@ -1645,22 +1658,36 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
        }
        float dX = event.getX() - firstPointerDownLocation.x;
        float dY = event.getY() - firstPointerDownLocation.y;
        if (mFullScreenMagnificationController.isAtLeftEdge(mDisplayId) && dX > 0) {
        if (isAtLeftEdge() && dX > 0) {
            return OVERSCROLL_LEFT_EDGE;
        } else if (mFullScreenMagnificationController.isAtRightEdge(mDisplayId) && dX < 0) {
        } else if (isAtRightEdge() && dX < 0) {
            return OVERSCROLL_RIGHT_EDGE;
        } else if (mFullScreenMagnificationController.isAtTopEdge(mDisplayId) && dY > 0
                || mFullScreenMagnificationController.isAtBottomEdge(mDisplayId) && dY < 0) {
        } else if ((isAtTopEdge() && dY > 0) || (isAtBottomEdge() && dY < 0)) {
            return OVERSCROLL_VERTICAL_EDGE;
        }
        return OVERSCROLL_NONE;
    }

    private boolean isAtLeftEdge() {
        return mFullScreenMagnificationController.isAtLeftEdge(mDisplayId, mOverscrollEdgeSlop);
    }

    private boolean isAtRightEdge() {
        return mFullScreenMagnificationController.isAtRightEdge(mDisplayId, mOverscrollEdgeSlop);
    }

    private boolean isAtTopEdge() {
        return mFullScreenMagnificationController.isAtTopEdge(mDisplayId, mOverscrollEdgeSlop);
    }

    private boolean isAtBottomEdge() {
        return mFullScreenMagnificationController.isAtBottomEdge(mDisplayId, mOverscrollEdgeSlop);
    }

    private boolean pointerValid(PointF pointerDownLocation) {
        return !(Float.isNaN(pointerDownLocation.x) && Float.isNaN(pointerDownLocation.y));
    }


    private static final class MotionEventInfo {

        private static final int MAX_POOL_SIZE = 10;
@@ -1845,7 +1872,6 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH

    final class SinglePanningState extends SimpleOnGestureListener implements State {


        private final GestureDetector mScrollGestureDetector;
        private MotionEventInfo mEvent;
        SinglePanningState(Context context) {
@@ -1860,8 +1886,10 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
                    onPanningFinished(event);
                    // fall-through!
                case ACTION_CANCEL:
                    if (mOverscrollHandler != null) {
                        mOverscrollHandler.setScaleAndCenterToEdgeIfNeeded();
                        mOverscrollHandler.clearEdgeState();
                    }
                    transitionTo(mDetectingState);
                    break;
            }
@@ -1889,26 +1917,18 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
                                + " isAtEdge: "
                                + mFullScreenMagnificationController.isAtEdge(mDisplayId));
            }
            if (mOverscrollHandler != null) {
                mOverscrollHandler.onScrollStateChanged(first, second);
            return /* event consumed: */ true;
        }

        private void vibrateIfNeeded() {
            if ((mFullScreenMagnificationController.isAtLeftEdge(mDisplayId)
                    || mFullScreenMagnificationController.isAtRightEdge(mDisplayId))) {
                mFullScreenMagnificationVibrationHelper.vibrateIfSettingEnabled();
            }
            return /* event consumed: */ true;
        }



        @Override
        public String toString() {
            return "SinglePanningState{"
                    + "isEdgeOfView="
                    + mFullScreenMagnificationController.isAtEdge(mDisplayId);
        }

    }

    /** Overscroll Handler handles the logic when user is at the edge and scrolls past an edge */
@@ -2007,9 +2027,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
            if (mOverscrollState != OVERSCROLL_NONE) {
                return;
            }
            if ((mFullScreenMagnificationController.isAtLeftEdge(mDisplayId)
                            || mFullScreenMagnificationController.isAtRightEdge(mDisplayId))
                    && !mEdgeCooldown) {
            if ((isAtLeftEdge() || isAtRightEdge()) && !mEdgeCooldown) {
                mFullScreenMagnificationVibrationHelper.vibrateIfSettingEnabled();
            }
        }
Loading