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

Commit 42d7f747 authored by Yongshun Liu's avatar Yongshun Liu
Browse files

a11y: Link cursor following mode backend with user preference

This makes sure the cursor following mode value is populated to the
pointer motion event filter. It links the user preference with the
backend.

This also moves the pointer motion event filter from
`FullScreenMagnificationController` to `AccessibilityInputFilter`. The
reason is that we do not need one event filter per display, and it's
easier to manage at `AccessibilityInputFilter` level.

Bug: b/355503630
Bug: b/355727440
Flag: com.android.server.accessibility.enable_magnification_follows_mouse_with_pointer_motion_filter
Test: FrameworksServicesTests:com.android.server.accessibility.AccessibilityInputFilterTest
Test: FrameworksServicesTests:com.android.server.accessibility.AccessibilityManagerServiceTest
Test: FrameworksServicesTests:com.android.server.accessibility.AccessibilityUserStateTest
Test: FrameworksServicesTests:com.android.server.accessibility.magnification.FullScreenMagnificationControllerTest
Change-Id: I044e735b75db3452a3c3e016c1325783ddb8a667
parent 45dd543e
Loading
Loading
Loading
Loading
+90 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY
import android.accessibilityservice.AccessibilityTrace;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Region;
import android.hardware.input.InputManager;
@@ -31,6 +32,7 @@ import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.provider.Settings.Secure.AccessibilityMagnificationCursorFollowingMode;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -51,11 +53,13 @@ import com.android.server.accessibility.autoclick.AutoclickController;
import com.android.server.accessibility.gestures.TouchExplorer;
import com.android.server.accessibility.magnification.FullScreenMagnificationController;
import com.android.server.accessibility.magnification.FullScreenMagnificationGestureHandler;
import com.android.server.accessibility.magnification.FullScreenMagnificationPointerMotionEventFilter;
import com.android.server.accessibility.magnification.FullScreenMagnificationVibrationHelper;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;
import com.android.server.accessibility.magnification.MagnificationKeyHandler;
import com.android.server.accessibility.magnification.WindowMagnificationGestureHandler;
import com.android.server.accessibility.magnification.WindowMagnificationPromptController;
import com.android.server.input.InputManagerInternal;
import com.android.server.policy.WindowManagerPolicy;

import java.io.FileDescriptor;
@@ -198,6 +202,10 @@ public class AccessibilityInputFilter extends InputFilter implements EventStream
    private final SparseArray<MagnificationGestureHandler> mMagnificationGestureHandler =
            new SparseArray<>(0);

    @Nullable
    private FullScreenMagnificationPointerMotionEventFilter
            mFullScreenMagnificationPointerMotionEventFilter;

    private final SparseArray<MotionEventInjector> mMotionEventInjectors = new SparseArray<>(0);

    private AutoclickController mAutoclickController;
@@ -649,6 +657,8 @@ public class AccessibilityInputFilter extends InputFilter implements EventStream
            enableFeaturesForDisplay(displaysList.get(i));
        }
        enableDisplayIndependentFeatures();

        registerPointerMotionFilter(/* enabled= */ isAnyFullScreenMagnificationEnabled());
    }

    private void enableFeaturesForDisplay(Display display) {
@@ -774,6 +784,19 @@ public class AccessibilityInputFilter extends InputFilter implements EventStream
                || ((mEnabledFeatures & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0);
    }

    private boolean isAnyFullScreenMagnificationEnabled() {
        if (!isAnyMagnificationEnabled()) {
            return false;
        }
        for (final Display display : mAms.getValidDisplayList()) {
            final int mode = mAms.getMagnificationMode(display.getDisplayId());
            if (mode != Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
                return true;
            }
        }
        return false;
    }

    /**
     * Adds an event handler to the event handler chain for giving display. The handler is added at
     * the beginning of the chain.
@@ -802,6 +825,8 @@ public class AccessibilityInputFilter extends InputFilter implements EventStream
        disableDisplayIndependentFeatures();

        resetAllStreamState();

        registerPointerMotionFilter(/* enabled= */ false);
    }

    private void disableFeaturesForDisplay(int displayId) {
@@ -867,6 +892,69 @@ public class AccessibilityInputFilter extends InputFilter implements EventStream
        }
    }

    @VisibleForTesting
    @Nullable
    FullScreenMagnificationPointerMotionEventFilter
            getFullScreenMagnificationPointerMotionEventFilter() {
        return mFullScreenMagnificationPointerMotionEventFilter;
    }

    private void createFullScreenMagnificationPointerMotionEventFilter() {
        if (!Flags.enableMagnificationFollowsMouseWithPointerMotionFilter()) {
            return;
        }

        final FullScreenMagnificationController controller =
                mAms.getMagnificationController().getFullScreenMagnificationController();
        mFullScreenMagnificationPointerMotionEventFilter =
                new FullScreenMagnificationPointerMotionEventFilter(controller);
        @AccessibilityMagnificationCursorFollowingMode
        final int cursorFollowingMode = mAms.getMagnificationCursorFollowingMode();
        setCursorFollowingMode(cursorFollowingMode);
    }

    /**
     * Sets cursor following mode. No operation if the feature flag is
     * not enabled.
     *
     * @param cursorFollowingMode The cursor following mode
     */
    public void setCursorFollowingMode(
            @AccessibilityMagnificationCursorFollowingMode int cursorFollowingMode) {
        if (!Flags.enableMagnificationFollowsMouseWithPointerMotionFilter()) {
            return;
        }

        if (mFullScreenMagnificationPointerMotionEventFilter != null) {
            mFullScreenMagnificationPointerMotionEventFilter.setMode(cursorFollowingMode);
        }
    }

    @VisibleForTesting
    void registerPointerMotionFilter(boolean enabled) {
        if (!Flags.enableMagnificationFollowsMouseWithPointerMotionFilter()) {
            return;
        }

        if (enabled == (mFullScreenMagnificationPointerMotionEventFilter != null)) {
            return;
        }

        InputManagerInternal inputManager = LocalServices.getService(InputManagerInternal.class);
        if (inputManager == null) {
            return;
        }

        if (enabled) {
            createFullScreenMagnificationPointerMotionEventFilter();
        } else {
            mFullScreenMagnificationPointerMotionEventFilter = null;
        }

        inputManager.registerAccessibilityPointerMotionFilter(
                mFullScreenMagnificationPointerMotionEventFilter);
    }

    private MagnificationGestureHandler createMagnificationGestureHandler(
            int displayId, Context displayContext) {
        final boolean detectControlGestures = (mEnabledFeatures
@@ -964,6 +1052,8 @@ public class AccessibilityInputFilter extends InputFilter implements EventStream
        switchEventStreamTransformation(displayId, magnificationGestureHandler,
                currentMagnificationGestureHandler);
        mMagnificationGestureHandler.put(displayId, currentMagnificationGestureHandler);

        registerPointerMotionFilter(/* enabled= */ isAnyFullScreenMagnificationEnabled());
    }

    @MainThread
+46 −0
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Secure.AccessibilityMagnificationCursorFollowingMode;
import android.provider.SettingsStringUtil.SettingStringHelper;
import android.safetycenter.SafetyCenterManager;
import android.text.TextUtils;
@@ -420,6 +421,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
    private final HearingDevicePhoneCallNotificationController mHearingDeviceNotificationController;
    private final UserManagerInternal mUmi;

    @NonNull
    private AccessibilityUserState getCurrentUserStateLocked() {
        return getUserStateLocked(mCurrentUserId);
    }
@@ -3483,6 +3485,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState);
        somethingChanged |= readMagnificationModeForDefaultDisplayLocked(userState);
        somethingChanged |= readMagnificationCapabilitiesLocked(userState);
        somethingChanged |= readMagnificationCursorFollowingMode(userState);
        somethingChanged |= readMagnificationFollowTypingLocked(userState);
        somethingChanged |= readMagnificationFollowKeyboardLocked(userState);
        somethingChanged |= readAlwaysOnMagnificationLocked(userState);
@@ -5811,6 +5814,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        private final Uri mMagnificationCapabilityUri = Settings.Secure.getUriFor(
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY);

        private final Uri mMagnificationCursorFollowingModeUri = Settings.Secure.getUriFor(
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CURSOR_FOLLOWING_MODE);

        private final Uri mMagnificationFollowTypingUri = Settings.Secure.getUriFor(
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED);

@@ -5881,6 +5887,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                    mMagnificationModeUri, false, this, UserHandle.USER_ALL);
            contentResolver.registerContentObserver(
                    mMagnificationCapabilityUri, false, this, UserHandle.USER_ALL);
            contentResolver.registerContentObserver(
                    mMagnificationCursorFollowingModeUri, false, this, UserHandle.USER_ALL);
            contentResolver.registerContentObserver(
                    mMagnificationFollowTypingUri, false, this, UserHandle.USER_ALL);
            contentResolver.registerContentObserver(
@@ -5979,6 +5987,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                    if (readMagnificationCapabilitiesLocked(userState)) {
                        updateMagnificationCapabilitiesSettingsChangeLocked(userState);
                    }
                } else if (mMagnificationCursorFollowingModeUri.equals(uri)) {
                    readMagnificationCursorFollowingMode(userState);
                } else if (mMagnificationFollowTypingUri.equals(uri)) {
                    readMagnificationFollowTypingLocked(userState);
                } else if (mMagnificationFollowKeyboardUri.equals(uri)) {
@@ -6092,6 +6102,42 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        return false;
    }

    /**
     * Gets the magnification cursor following mode.
     *
     * @return cursor following mode.
     */
    @AccessibilityMagnificationCursorFollowingMode
    public int getMagnificationCursorFollowingMode() {
        synchronized (mLock) {
            return getCurrentUserStateLocked().getMagnificationCursorFollowingMode();
        }
    }

    boolean readMagnificationCursorFollowingMode(AccessibilityUserState userState) {
        if (!Flags.enableMagnificationFollowsMouseWithPointerMotionFilter()) {
            return false;
        }

        @AccessibilityMagnificationCursorFollowingMode
        final int cursorFollowingMode = Settings.Secure.getIntForUser(
                mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CURSOR_FOLLOWING_MODE,
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CURSOR_FOLLOWING_MODE_CONTINUOUS,
                userState.mUserId);
        @AccessibilityMagnificationCursorFollowingMode
        final int userCursorFollowingMode = userState.getMagnificationCursorFollowingMode();

        if (cursorFollowingMode != userCursorFollowingMode) {
            userState.setMagnificationCursorFollowingMode(cursorFollowingMode);
            if (mHasInputFilter && mInputFilter != null) {
                mInputFilter.setCursorFollowingMode(cursorFollowingMode);
            }
            return true;
        }
        return false;
    }

    boolean readMagnificationFollowTypingLocked(AccessibilityUserState userState) {
        final boolean followTypeEnabled = Settings.Secure.getIntForUser(
                mContext.getContentResolver(),
+32 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.RemoteCallbackList;
import android.provider.Settings;
import android.provider.Settings.Secure.AccessibilityMagnificationCursorFollowingMode;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -157,6 +158,10 @@ public class AccessibilityUserState {
    private final SparseIntArray mMagnificationModes = new SparseIntArray();
    // The magnification capabilities used to know magnification mode could be switched.
    private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
    // The magnification cursor following mode.
    @AccessibilityMagnificationCursorFollowingMode
    private int mMagnificationCursorFollowingMode =
            Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CURSOR_FOLLOWING_MODE_CONTINUOUS;
    // Whether the following typing focus feature for magnification is enabled.
    private boolean mMagnificationFollowTypingEnabled = true;
    // Whether the following keyboard focus feature for magnification is enabled.
@@ -256,6 +261,8 @@ public class AccessibilityUserState {
        mMagnificationModes.clear();
        mFocusStrokeWidth = mFocusStrokeWidthDefaultValue;
        mFocusColor = mFocusColorDefaultValue;
        mMagnificationCursorFollowingMode =
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CURSOR_FOLLOWING_MODE_CONTINUOUS;
        mMagnificationFollowTypingEnabled = true;
        mMagnificationFollowKeyboardEnabled = false;
        mAlwaysOnMagnificationEnabled = false;
@@ -580,6 +587,8 @@ public class AccessibilityUserState {
                .append(String.valueOf(mMagnificationCapabilities));
        pw.append(", audioDescriptionByDefaultEnabled=")
                .append(String.valueOf(mIsAudioDescriptionByDefaultRequested));
        pw.append(", magnificationCursorFollowingMode=").append(
                String.valueOf(mMagnificationCursorFollowingMode));
        pw.append(", magnificationFollowTypingEnabled=")
                .append(String.valueOf(mMagnificationFollowTypingEnabled));
        pw.append(", magnificationFollowKeyboardEnabled=")
@@ -768,6 +777,29 @@ public class AccessibilityUserState {
        mMagnificationCapabilities = capabilities;
    }

    /**
     * Gets the magnification cursor following mode.
     * @return magnification cursor following mode
     *
     * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_CURSOR_FOLLOWING_MODE_CONTINUOUS
     * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_CURSOR_FOLLOWING_MODE_CENTER
     * @see Settings.Secure#ACCESSIBILITY_MAGNIFICATION_CURSOR_FOLLOWING_MODE_EDGE
     */
    @AccessibilityMagnificationCursorFollowingMode
    public int getMagnificationCursorFollowingMode() {
        return mMagnificationCursorFollowingMode;
    }

    /**
     * Sets the magnification cursor following mode.
     *
     * @param mode The magnification cursor following mode.
     */
    public void setMagnificationCursorFollowingMode(
            @AccessibilityMagnificationCursorFollowingMode int mode) {
        mMagnificationCursorFollowingMode = mode;
    }

    public void setMagnificationFollowTypingEnabled(boolean enabled) {
        mMagnificationFollowTypingEnabled = enabled;
    }
+0 −20
Original line number Diff line number Diff line
@@ -123,8 +123,6 @@ public class FullScreenMagnificationController implements
    @NonNull private final Supplier<MagnificationThumbnail> mThumbnailSupplier;
    @NonNull private final Supplier<Boolean> mMagnificationConnectionStateSupplier;

    private boolean mIsPointerMotionFilterInstalled = false;

    /**
     * Full screen magnification data for {@link FullScreenMagnificationPointerMotionEventFilter}.
     */
@@ -1189,7 +1187,6 @@ public class FullScreenMagnificationController implements
            if (display.register()) {
                mDisplays.put(displayId, display);
                mScreenStateObserver.registerIfNecessary();
                configurePointerMotionFilter(true);
            }
        }
    }
@@ -2076,7 +2073,6 @@ public class FullScreenMagnificationController implements
        }
        if (!hasRegister) {
            mScreenStateObserver.unregister();
            configurePointerMotionFilter(false);
        }
    }

@@ -2092,22 +2088,6 @@ 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);
+2 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ public class FullScreenMagnificationPointerMotionEventFilter implements
    @VisibleForTesting
    static final float EDGE_MODE_MARGIN_PX = 100.f;

    @NonNull
    private final FullScreenMagnificationController mController;

    @NonNull
@@ -53,7 +54,7 @@ public class FullScreenMagnificationPointerMotionEventFilter implements
            ACCESSIBILITY_MAGNIFICATION_CURSOR_FOLLOWING_MODE_CONTINUOUS);

    public FullScreenMagnificationPointerMotionEventFilter(
            FullScreenMagnificationController controller) {
            @NonNull FullScreenMagnificationController controller) {
        mController = controller;
        mMagnificationData = new FullScreenMagnificationController.FullScreenMagnificationData();
    }
Loading