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

Commit ce5f4174 authored by Katie Dektar's avatar Katie Dektar
Browse files

[A11y] Move Magnification key handling to AccessibilityInputFilter

This change has no functional difference but moves magnification scale
and pan key press handling from KeyGestures to AccessibilityInputFilter.
In follow-up changes, this will allow Magnification users to hold the
magnification keys in order to continuously pan/scale the viewport,
and will allow handling of diagonal panning.

The magnification scale and pan keyboard shortcuts are moved to the
InputGestureManager blocklist so that they cannot be clobbered by
system shortcuts.

Bug: 388847194
Flag: com.android.hardware.input.enable_talkback_and_magnifier_key_gestures
Test: atest MagnificationKeyHandlerTest, AccessibilityInputFilterTest, and manual
Change-Id: I5a14908052d397b0b372d324d1971a3caec49ad0
parent 291ac766
Loading
Loading
Loading
Loading
+5 −29
Original line number Diff line number Diff line
@@ -122,17 +122,11 @@ public final class KeyGestureEvent {
    public static final int KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW = 69;
    public static final int KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW = 70;
    public static final int KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW = 71;
    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN = 72;
    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT = 73;
    public static final int KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION = 74;
    public static final int KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK = 75;
    public static final int KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW = 76;
    public static final int KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB = 77;
    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT = 78;
    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT = 79;
    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP = 80;
    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN = 81;
    public static final int KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS = 82;
    public static final int KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION = 72;
    public static final int KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK = 73;
    public static final int KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW = 74;
    public static final int KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB = 75;
    public static final int KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS = 76;

    public static final int FLAG_CANCELLED = 1;

@@ -220,16 +214,10 @@ public final class KeyGestureEvent {
            KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW,
            KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW,
            KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW,
            KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN,
            KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT,
            KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION,
            KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK,
            KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW,
            KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB,
            KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT,
            KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT,
            KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP,
            KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN,
            KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS,
    })
    @Retention(RetentionPolicy.SOURCE)
@@ -815,10 +803,6 @@ public final class KeyGestureEvent {
                return "KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW";
            case KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW:
                return "KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW";
            case KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN:
                return "KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN";
            case KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT:
                return "KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT";
            case KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION:
                return "KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION";
            case KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK:
@@ -827,14 +811,6 @@ public final class KeyGestureEvent {
                return "KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW";
            case KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB:
                return "KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB";
            case KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT:
                return "KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT";
            case KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT:
                return "KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT";
            case KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP:
                return "KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP";
            case KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN:
                return "KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN";
            case KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS:
                return "KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS";
            default:
+26 −86
Original line number Diff line number Diff line
@@ -21,14 +21,14 @@ import static android.view.MotionEvent.ACTION_SCROLL;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;

import static com.android.hardware.input.Flags.enableTalkbackAndMagnifierKeyGestures;

import android.accessibilityservice.AccessibilityTrace;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.content.Context;
import android.graphics.Region;
import android.hardware.input.InputManager;
import android.hardware.input.KeyGestureEvent;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -46,15 +46,13 @@ import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
import android.view.accessibility.AccessibilityEvent;

import androidx.annotation.Nullable;

import com.android.server.LocalServices;
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.FullScreenMagnificationVibrationHelper;
import com.android.server.accessibility.magnification.MagnificationController;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;
import com.android.server.accessibility.magnification.MagnificationKeyHandler;
import com.android.server.accessibility.magnification.MouseEventHandler;
import com.android.server.accessibility.magnification.WindowMagnificationGestureHandler;
import com.android.server.accessibility.magnification.WindowMagnificationPromptController;
@@ -209,6 +207,8 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo

    private MouseKeysInterceptor mMouseKeysInterceptor;

    private MagnificationKeyHandler mMagnificationKeyHandler;

    private boolean mInstalled;

    private int mUserId;
@@ -235,74 +235,6 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
     */
    private MotionEvent mLastActiveDeviceMotionEvent = null;

    private boolean mKeyGestureEventHandlerInstalled = false;
    private InputManager.KeyGestureEventHandler mKeyGestureEventHandler =
            new InputManager.KeyGestureEventHandler() {
                @Override
                public boolean handleKeyGestureEvent(
                        @NonNull KeyGestureEvent event,
                        @Nullable IBinder focusedToken) {
                    final boolean complete =
                            event.getAction() == KeyGestureEvent.ACTION_GESTURE_COMPLETE
                                    && !event.isCancelled();

                    // TODO(b/355499907): Receive and handle held key gestures, which can be used
                    // for continuous scaling and panning. In addition, handle multiple pan gestures
                    // at the same time (e.g. user may try to pan diagonally) reasonably, including
                    // decreasing diagonal movement by sqrt(2) to make it appear the same speed
                    // as non-diagonal movement.

                    if (!complete) {
                        return false;
                    }

                    final int gestureType = event.getKeyGestureType();
                    final int displayId = isDisplayIdValid(event.getDisplayId())
                            ? event.getDisplayId() : Display.DEFAULT_DISPLAY;

                    switch (gestureType) {
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN:
                                mAms.getMagnificationController().scaleMagnificationByStep(
                                        displayId, MagnificationController.ZOOM_DIRECTION_IN);
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT:
                                mAms.getMagnificationController().scaleMagnificationByStep(
                                        displayId, MagnificationController.ZOOM_DIRECTION_OUT);
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT:
                            mAms.getMagnificationController().panMagnificationByStep(
                                    displayId, MagnificationController.PAN_DIRECTION_LEFT);
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT:
                            mAms.getMagnificationController().panMagnificationByStep(
                                    displayId, MagnificationController.PAN_DIRECTION_RIGHT);
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP:
                            mAms.getMagnificationController().panMagnificationByStep(
                                    displayId, MagnificationController.PAN_DIRECTION_UP);
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN:
                            mAms.getMagnificationController().panMagnificationByStep(
                                    displayId, MagnificationController.PAN_DIRECTION_DOWN);
                            return true;
                    }
                    return false;
                }

                @Override
                public boolean isKeyGestureSupported(int gestureType) {
                    return switch (gestureType) {
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN -> true;
                        default -> false;
                    };
                }
            };

    private static MotionEvent cancelMotion(MotionEvent event) {
        if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
                || event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT
@@ -787,20 +719,11 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
                    });
        }

        if ((mEnabledFeatures & FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER) != 0
                || ((mEnabledFeatures & FLAG_FEATURE_MAGNIFICATION_SINGLE_FINGER_TRIPLE_TAP) != 0)
                || ((mEnabledFeatures & FLAG_FEATURE_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP) != 0)
                || ((mEnabledFeatures & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0)) {
        if (isAnyMagnificationEnabled()) {
            final MagnificationGestureHandler magnificationGestureHandler =
                    createMagnificationGestureHandler(displayId, displayContext);
            addFirstEventHandler(displayId, magnificationGestureHandler);
            mMagnificationGestureHandler.put(displayId, magnificationGestureHandler);

            if (com.android.hardware.input.Flags.enableTalkbackAndMagnifierKeyGestures()
                    && !mKeyGestureEventHandlerInstalled) {
                mInputManager.registerKeyGestureEventHandler(mKeyGestureEventHandler);
                mKeyGestureEventHandlerInstalled = true;
            }
        }

        if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
@@ -817,6 +740,8 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
        }

        if ((mEnabledFeatures & FLAG_FEATURE_FILTER_KEY_EVENTS) != 0) {
            // mKeyboardInterceptor does not forward KeyEvents to other EventStreamTransformations,
            // so it must be the last EventStreamTransformation for key events in the list.
            mKeyboardInterceptor = new KeyboardInterceptor(mAms,
                    LocalServices.getService(WindowManagerPolicy.class));
            // Since the display id of KeyEvent always would be -1 and it would be dispatched to
@@ -832,6 +757,19 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
                    Display.DEFAULT_DISPLAY);
            addFirstEventHandler(Display.DEFAULT_DISPLAY, mMouseKeysInterceptor);
        }

        if (enableTalkbackAndMagnifierKeyGestures() && isAnyMagnificationEnabled()) {
            mMagnificationKeyHandler = new MagnificationKeyHandler(
                    mAms.getMagnificationController());
            addFirstEventHandler(Display.DEFAULT_DISPLAY, mMagnificationKeyHandler);
        }
    }

    private boolean isAnyMagnificationEnabled() {
        return (mEnabledFeatures & FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER) != 0
                || ((mEnabledFeatures & FLAG_FEATURE_MAGNIFICATION_SINGLE_FINGER_TRIPLE_TAP) != 0)
                || ((mEnabledFeatures & FLAG_FEATURE_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP) != 0)
                || ((mEnabledFeatures & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0);
    }

    /**
@@ -921,9 +859,9 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
            mMouseKeysInterceptor = null;
        }

        if (mKeyGestureEventHandlerInstalled) {
            mInputManager.unregisterKeyGestureEventHandler(mKeyGestureEventHandler);
            mKeyGestureEventHandlerInstalled = false;
        if (mMagnificationKeyHandler != null) {
            mMagnificationKeyHandler.onDestroy();
            mMagnificationKeyHandler = null;
        }
    }

@@ -1365,6 +1303,8 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
                        joiner.add("AutoclickController");
                    } else if (next instanceof MotionEventInjector) {
                        joiner.add("MotionEventInjector");
                    } else if (next instanceof MagnificationKeyHandler) {
                        joiner.add("MagnificationKeyHandler");
                    }
                    next = next.getNext();
                }
+31 −1
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ import java.util.concurrent.Executor;
 *  is done and before invoking {@link TransitionCallBack#onResult}.
 */
public class MagnificationController implements MagnificationConnectionManager.Callback,
        MagnificationGestureHandler.Callback,
        MagnificationGestureHandler.Callback, MagnificationKeyHandler.Callback,
        FullScreenMagnificationController.MagnificationInfoChangedCallback,
        WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks {

@@ -347,6 +347,36 @@ public class MagnificationController implements MagnificationConnectionManager.C
        handleUserInteractionChanged(displayId, mode);
    }

    @Override
    public void onPanMagnificationStart(int displayId,
            @MagnificationController.PanDirection int direction) {
        // TODO(b/355499907): Handle multiple pan gestures at the same time (e.g. user may try to
        // pan diagonally) by decreasing diagonal movement by sqrt(2) to make it appear the same
        // speed as non-diagonal movement.
        panMagnificationByStep(displayId, direction);
    }

    @Override
    public void onPanMagnificationStop(int displayId,
            @MagnificationController.PanDirection int direction) {
        // TODO(b/388847283): Handle held key gestures, which can be used
        // for continuous scaling and panning, until they are released.

    }

    @Override
    public void onScaleMagnificationStart(int displayId,
            @MagnificationController.ZoomDirection int direction) {
        scaleMagnificationByStep(displayId, direction);
    }

    @Override
    public void onScaleMagnificationStop(int displayId,
            @MagnificationController.ZoomDirection int direction) {
        // TODO(b/388847283): Handle held key gestures, which can be used
        // for continuous scaling and panning, until they are released.
    }

    private void handleUserInteractionChanged(int displayId, int mode) {
        if (mMagnificationCapabilities != Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL) {
            return;
+133 −0
Original line number Diff line number Diff line
/*
 * 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 android.view.Display;
import android.view.KeyEvent;

import com.android.server.accessibility.BaseEventStreamTransformation;

/*
 * A class that listens to key presses used to control magnification.
 */
public class MagnificationKeyHandler extends BaseEventStreamTransformation {

    /** Callback interface to report that a user is intending to interact with Magnification. */
    public interface Callback {
        /**
         * Called when a keyboard shortcut to pan magnification in direction {@code direction} is
         * pressed by a user. Note that this can be called for multiple directions if multiple
         * arrows are pressed at the same time (e.g. diagonal panning).
         *
         * @param displayId The logical display ID
         * @param direction The direction to start panning
         */
        void onPanMagnificationStart(int displayId,
                @MagnificationController.PanDirection int direction);

        /**
         * Called when a keyboard shortcut to pan magnification in direction {@code direction} is
         * unpressed by a user. Note that this can be called for multiple directions if multiple
         * arrows had been pressed at the same time (e.g. diagonal panning).
         *
         * @param displayId The logical display ID
         * @param direction The direction in which panning stopped
         */
        void onPanMagnificationStop(int displayId,
                @MagnificationController.PanDirection int direction);

        /**
         * Called when a keyboard shortcut to scale magnification in direction `direction` is
         * pressed by a user.
         *
         * @param displayId The logical display ID
         * @param direction The direction in which scaling started
         */
        void onScaleMagnificationStart(int displayId,
                @MagnificationController.ZoomDirection int direction);

        /**
         * Called when a keyboard shortcut to scale magnification in direction `direction` is
         * unpressed by a user.
         *
         * @param displayId The logical display ID
         * @param direction The direction in which scaling stopped
         */
        void onScaleMagnificationStop(int displayId,
                @MagnificationController.ZoomDirection int direction);
    }

    protected final MagnificationKeyHandler.Callback mCallback;

    public MagnificationKeyHandler(Callback callback) {
        mCallback = callback;
    }

    @Override
    public void onKeyEvent(KeyEvent event, int policyFlags) {
        if (!com.android.hardware.input.Flags.enableTalkbackAndMagnifierKeyGestures()) {
            // Send to the rest of the handlers.
            super.onKeyEvent(event, policyFlags);
            return;
        }
        boolean modifiersPressed = event.isAltPressed() && event.isMetaPressed();
        if (!modifiersPressed) {
            super.onKeyEvent(event, policyFlags);
            return;
        }
        boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;
        int keyCode = event.getKeyCode();
        if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
                || keyCode == KeyEvent.KEYCODE_DPAD_UP || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
            int panDirection = switch(keyCode) {
                case KeyEvent.KEYCODE_DPAD_LEFT -> MagnificationController.PAN_DIRECTION_LEFT;
                case KeyEvent.KEYCODE_DPAD_RIGHT -> MagnificationController.PAN_DIRECTION_RIGHT;
                case KeyEvent.KEYCODE_DPAD_UP -> MagnificationController.PAN_DIRECTION_UP;
                default -> MagnificationController.PAN_DIRECTION_DOWN;
            };
            if (isDown) {
                mCallback.onPanMagnificationStart(getDisplayId(event), panDirection);
            } else {
                mCallback.onPanMagnificationStop(getDisplayId(event), panDirection);
            }
            return;
        } else if (keyCode == KeyEvent.KEYCODE_EQUALS || keyCode == KeyEvent.KEYCODE_MINUS) {
            int zoomDirection = MagnificationController.ZOOM_DIRECTION_OUT;
            if (keyCode == KeyEvent.KEYCODE_EQUALS) {
                zoomDirection = MagnificationController.ZOOM_DIRECTION_IN;
            }
            if (isDown) {
                mCallback.onScaleMagnificationStart(getDisplayId(event), zoomDirection);
            } else {
                mCallback.onScaleMagnificationStop(getDisplayId(event), zoomDirection);
            }
            return;
        }

        // Continue down the eventing chain if this was unused.
        super.onKeyEvent(event, policyFlags);
    }

    private int getDisplayId(KeyEvent event) {
        // Display ID may be invalid, e.g. for external keyboard attached to phone.
        // In that case, use the default display.
        if (event.getDisplayId() != Display.INVALID_DISPLAY) {
            return event.getDisplayId();
        }
        return Display.DEFAULT_DISPLAY;
    }
}
+14 −19
Original line number Diff line number Diff line
@@ -87,7 +87,20 @@ final class InputGestureManager {
            createKeyTrigger(KeyEvent.KEYCODE_V, KeyEvent.META_CTRL_ON),
            createKeyTrigger(KeyEvent.KEYCODE_X, KeyEvent.META_CTRL_ON),
            createKeyTrigger(KeyEvent.KEYCODE_Z, KeyEvent.META_CTRL_ON),
            createKeyTrigger(KeyEvent.KEYCODE_Y, KeyEvent.META_CTRL_ON)
            createKeyTrigger(KeyEvent.KEYCODE_Y, KeyEvent.META_CTRL_ON),
            // Used for magnification viewport control.
            createKeyTrigger(KeyEvent.KEYCODE_MINUS,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON),
            createKeyTrigger(KeyEvent.KEYCODE_EQUALS,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON),
            createKeyTrigger(KeyEvent.KEYCODE_DPAD_LEFT,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON),
            createKeyTrigger(KeyEvent.KEYCODE_DPAD_RIGHT,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON),
            createKeyTrigger(KeyEvent.KEYCODE_DPAD_UP,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON),
            createKeyTrigger(KeyEvent.KEYCODE_DPAD_DOWN,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON)
    ));

    public InputGestureManager(Context context) {
@@ -216,24 +229,6 @@ final class InputGestureManager {
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_T,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_MINUS,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_EQUALS,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_LEFT,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_RIGHT,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_UP,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_DOWN,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_M,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION));
Loading