summaryrefslogtreecommitdiff
path: root/services/accessibility
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2025-03-03 16:55:24 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-03-03 16:55:24 -0800
commitcf191b8ca9cab234e0cf88496d60494e2cde99bf (patch)
tree8c3c917d08d0f61d1ecaaa02664bfffe2c68391a /services/accessibility
parent1eeb9667feb274722980ce1b750188dfb3981d89 (diff)
parent872880ee3f2f1c95acf42e4a81cf6f4f79eb6de2 (diff)
Merge "Re-implement full screen magnification continuous cursor following" into main
Diffstat (limited to 'services/accessibility')
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java3
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java56
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java9
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationPointerMotionEventFilter.java66
4 files changed, 128 insertions, 6 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 42834ce20783..c49151dd5e30 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -287,7 +287,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
public static final int INVALID_SERVICE_ID = -1;
- // Each service has an ID. Also provide one for magnification gesture handling
+ // Each service has an ID. Also provide one for magnification gesture handling.
+ // This ID is also used for mouse event handling.
public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0;
private static int sIdCounter = MAGNIFICATION_GESTURE_HANDLER_ID + 1;
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index 11b8ccb70dfb..004b3ffcb02b 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -121,6 +121,8 @@ public class FullScreenMagnificationController implements
@NonNull private final Supplier<MagnificationThumbnail> mThumbnailSupplier;
@NonNull private final Supplier<Boolean> mMagnificationConnectionStateSupplier;
+ private boolean mIsPointerMotionFilterInstalled = false;
+
/**
* This class implements {@link WindowManagerInternal.MagnificationCallbacks} and holds
* magnification information per display.
@@ -830,9 +832,17 @@ public class FullScreenMagnificationController implements
return;
}
- final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
- final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
- if (updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY)) {
+ setOffset(mCurrentMagnificationSpec.offsetX - offsetX,
+ mCurrentMagnificationSpec.offsetY - offsetY, id);
+ }
+
+ @GuardedBy("mLock")
+ void setOffset(float offsetX, float offsetY, int id) {
+ if (!mRegistered) {
+ return;
+ }
+
+ if (updateCurrentSpecWithOffsetsLocked(offsetX, offsetY)) {
onMagnificationChangedLocked(/* isScaleTransient= */ false);
}
if (id != INVALID_SERVICE_ID) {
@@ -1065,6 +1075,7 @@ public class FullScreenMagnificationController implements
if (display.register()) {
mDisplays.put(displayId, display);
mScreenStateObserver.registerIfNecessary();
+ configurePointerMotionFilter(true);
}
}
}
@@ -1613,6 +1624,28 @@ public class FullScreenMagnificationController implements
}
/**
+ * Sets the offset of the magnified region.
+ *
+ * @param displayId The logical display id.
+ * @param offsetX the offset of the magnified region in the X coordinate, in current
+ * screen pixels.
+ * @param offsetY the offset of the magnified region in the Y coordinate, in current
+ * screen pixels.
+ * @param id the ID of the service requesting the change
+ */
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
+ public void setOffset(int displayId, float offsetX, float offsetY, int id) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return;
+ }
+ display.setOffset(offsetX, offsetY, id);
+ }
+ }
+
+ /**
* Offsets the magnified region. Note that the offsetX and offsetY values actually move in the
* opposite direction as the offsets passed in here.
*
@@ -1885,6 +1918,7 @@ public class FullScreenMagnificationController implements
}
if (!hasRegister) {
mScreenStateObserver.unregister();
+ configurePointerMotionFilter(false);
}
}
@@ -1900,6 +1934,22 @@ public class FullScreenMagnificationController implements
}
}
+ private void configurePointerMotionFilter(boolean enabled) {
+ if (!Flags.enableMagnificationFollowsMouseWithPointerMotionFilter()) {
+ return;
+ }
+ if (enabled == mIsPointerMotionFilterInstalled) {
+ return;
+ }
+ if (!enabled) {
+ mControllerCtx.getInputManager().registerAccessibilityPointerMotionFilter(null);
+ } else {
+ mControllerCtx.getInputManager().registerAccessibilityPointerMotionFilter(
+ new FullScreenMagnificationPointerMotionEventFilter(this));
+ }
+ mIsPointerMotionFilterInstalled = enabled;
+ }
+
private boolean traceEnabled() {
return mControllerCtx.getTraceManager().isA11yTracingEnabledForTypes(
FLAGS_WINDOW_MANAGER_INTERNAL);
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 e0dd8b601a3d..59b4a1613e08 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -182,6 +182,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
private final int mMinimumVelocity;
private final int mMaximumVelocity;
+ @Nullable
private final MouseEventHandler mMouseEventHandler;
public FullScreenMagnificationGestureHandler(
@@ -313,7 +314,9 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
mOverscrollEdgeSlop = context.getResources().getDimensionPixelSize(
R.dimen.accessibility_fullscreen_magnification_gesture_edge_slop);
mIsWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
- mMouseEventHandler = new MouseEventHandler(mFullScreenMagnificationController);
+ mMouseEventHandler =
+ Flags.enableMagnificationFollowsMouseWithPointerMotionFilter()
+ ? null : new MouseEventHandler(mFullScreenMagnificationController);
if (mDetectShortcutTrigger) {
mScreenStateReceiver = new ScreenStateReceiver(context, this);
@@ -337,9 +340,11 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
@Override
void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- if (!mFullScreenMagnificationController.isActivated(mDisplayId)) {
+ if (mMouseEventHandler == null
+ || !mFullScreenMagnificationController.isActivated(mDisplayId)) {
return;
}
+
// TODO(b/354696546): Allow mouse/stylus to activate whichever display they are
// over, rather than only interacting with the current display.
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationPointerMotionEventFilter.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationPointerMotionEventFilter.java
new file mode 100644
index 000000000000..f1ba83e80d54
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationPointerMotionEventFilter.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2025 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 static com.android.server.accessibility.AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID;
+
+import android.annotation.NonNull;
+
+import com.android.server.input.InputManagerInternal;
+
+/**
+ * Handles pointer motion event for full screen magnification.
+ * Responsible for controlling magnification's cursor following feature.
+ */
+public class FullScreenMagnificationPointerMotionEventFilter implements
+ InputManagerInternal.AccessibilityPointerMotionFilter {
+
+ private final FullScreenMagnificationController mController;
+
+ public FullScreenMagnificationPointerMotionEventFilter(
+ FullScreenMagnificationController controller) {
+ mController = controller;
+ }
+
+ /**
+ * This call happens on the input hot path and it is extremely performance sensitive. It
+ * also must not call back into native code.
+ */
+ @Override
+ @NonNull
+ public float[] filterPointerMotionEvent(float dx, float dy, float currentX, float currentY,
+ int displayId) {
+ if (!mController.isActivated(displayId)) {
+ // unrelated display.
+ return new float[]{dx, dy};
+ }
+
+ // TODO(361817142): implement centered and edge following types.
+
+ // Continuous cursor following.
+ float scale = mController.getScale(displayId);
+ final float newCursorX = currentX + dx;
+ final float newCursorY = currentY + dy;
+ mController.setOffset(displayId,
+ newCursorX - newCursorX * scale, newCursorY - newCursorY * scale,
+ MAGNIFICATION_GESTURE_HANDLER_ID);
+
+ // In the continuous mode, the cursor speed in physical display is kept.
+ // Thus, we don't consume any motion delta.
+ return new float[]{dx, dy};
+ }
+}