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

Commit f0f805b7 authored by Yongshun Liu's avatar Yongshun Liu Committed by Android (Google) Code Review
Browse files

Merge changes I044e735b,Iaf2b3c45 into main

* changes:
  a11y: Link cursor following mode backend with user preference
  a11y: Add cursor following center+edge mode
parents afd6eace 42d7f747
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;
    }
+138 −19
Original line number Diff line number Diff line
@@ -123,7 +123,117 @@ 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}.
     */
    public static class FullScreenMagnificationData {
        // LINT.IfChange(data_declaration)
        private boolean mActivated;
        private float mScale;
        @NonNull
        private Rect mBounds;
        private float mOffsetX;
        private float mMinOffsetX;
        private float mMaxOffsetX;
        private float mOffsetY;
        private float mMinOffsetY;
        private float mMaxOffsetY;
        // LINT.ThenChange(FullScreenMagnificationController.java:data_reset)

        public FullScreenMagnificationData() {
            mBounds = new Rect();
        }

        public boolean isActivated() {
            return mActivated;
        }

        public void setActivated(boolean activated) {
            mActivated = activated;
        }

        public float getScale() {
            return mScale;
        }

        public void setScale(float scale) {
            mScale = scale;
        }

        @NonNull
        public Rect getBounds() {
            return mBounds;
        }

        public void setBounds(@NonNull Rect bounds) {
            mBounds = bounds;
        }

        public float getOffsetX() {
            return mOffsetX;
        }

        public void setOffsetX(float offsetX) {
            mOffsetX = offsetX;
        }

        public float getMinOffsetX() {
            return mMinOffsetX;
        }

        public void setMinOffsetX(float minOffsetX) {
            mMinOffsetX = minOffsetX;
        }

        public float getMaxOffsetX() {
            return mMaxOffsetX;
        }

        public void setMaxOffsetX(float maxOffsetX) {
            mMaxOffsetX = maxOffsetX;
        }

        public float getOffsetY() {
            return mOffsetY;
        }

        public void setOffsetY(float offsetY) {
            mOffsetY = offsetY;
        }

        public float getMinOffsetY() {
            return mMinOffsetY;
        }

        public void setMinOffsetY(float minOffsetY) {
            mMinOffsetY = minOffsetY;
        }

        public float getMaxOffsetY() {
            return mMaxOffsetY;
        }

        public void setMaxOffsetY(float maxOffsetY) {
            mMaxOffsetY = maxOffsetY;
        }

        /**
         * Resets the data to default.
         */
        public void reset() {
            // LINT.IfChange(data_reset)
            mActivated = false;
            mScale = 1.0f;
            mBounds.setEmpty();
            mOffsetX = 0.0f;
            mMinOffsetX = 0.0f;
            mMaxOffsetX = 0.0f;
            mOffsetY = 0.0f;
            mMinOffsetY = 0.0f;
            mMaxOffsetY = 0.0f;
            // LINT.ThenChange(FullScreenMagnificationController.java:data_declaration)
        }
    }

    /**
     * This class implements {@link WindowManagerInternal.MagnificationCallbacks} and holds
@@ -1077,7 +1187,6 @@ public class FullScreenMagnificationController implements
            if (display.register()) {
                mDisplays.put(displayId, display);
                mScreenStateObserver.registerIfNecessary();
                configurePointerMotionFilter(true);
            }
        }
    }
@@ -1255,6 +1364,33 @@ public class FullScreenMagnificationController implements
        }
    }

    /**
     * Gets the full screen magnification data needed by
     * {@link #FullScreenMagnificationPointerMotionEventFilter}.
     *
     * @param displayId The logical display id.
     * @param outMagnificationData The magnification data to populate.
     */
    public void getFullScreenMagnificationData(int displayId,
            @NonNull FullScreenMagnificationData outMagnificationData) {
        synchronized (mLock) {
            final DisplayMagnification display = mDisplays.get(displayId);
            if (display == null) {
                outMagnificationData.reset();
            } else {
                outMagnificationData.mActivated = display.isActivated();
                outMagnificationData.mScale = display.getScale();
                display.getMagnificationBounds(outMagnificationData.mBounds);
                outMagnificationData.mOffsetX = display.getOffsetX();
                outMagnificationData.mMinOffsetX = display.getMinOffsetXLocked();
                outMagnificationData.mMaxOffsetX = display.getMaxOffsetXLocked();
                outMagnificationData.mOffsetY = display.getOffsetY();
                outMagnificationData.mMinOffsetY = display.getMinOffsetYLocked();
                outMagnificationData.mMaxOffsetY = display.getMaxOffsetYLocked();
            }
        }
    }

    /**
     * Populates the specified rect with the screen-relative bounds of the
     * magnification region. If magnification is not enabled, the returned
@@ -1937,7 +2073,6 @@ public class FullScreenMagnificationController implements
        }
        if (!hasRegister) {
            mScreenStateObserver.unregister();
            configurePointerMotionFilter(false);
        }
    }

@@ -1953,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);
+108 −9

File changed.

Preview size limit exceeded, changes collapsed.

Loading