Loading core/java/android/hardware/input/KeyGestureEvent.java +17 −2 Original line number Diff line number Diff line Loading @@ -125,7 +125,10 @@ public final class KeyGestureEvent { 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_MAGNIFIER_PAN_LEFT = 78; public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT = 79; public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP = 80; public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN = 81; public static final int FLAG_CANCELLED = 1; Loading Loading @@ -217,7 +220,11 @@ public final class KeyGestureEvent { 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_TOGGLE_DO_NOT_DISTURB, KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT, KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT, KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP, KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN, }) @Retention(RetentionPolicy.SOURCE) public @interface KeyGestureType { Loading Loading @@ -792,6 +799,14 @@ 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_MAGNIFIER_PAN_LEFT: return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT"; case KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT: return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT"; case KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP: return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP"; case KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN: return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN"; default: return Integer.toHexString(value); } Loading services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +32 −5 Original line number Diff line number Diff line Loading @@ -245,22 +245,45 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo 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_MAGNIFIER_ZOOM_IN: if (complete) { mAms.getMagnificationController().scaleMagnificationByStep( displayId, MagnificationController.ZOOM_DIRECTION_IN); } return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT: if (complete) { mAms.getMagnificationController().scaleMagnificationByStep( displayId, MagnificationController.ZOOM_DIRECTION_OUT); } return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT: mAms.getMagnificationController().panMagnificationByStep( displayId, MagnificationController.PAN_DIRECTION_LEFT); return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT: mAms.getMagnificationController().panMagnificationByStep( displayId, MagnificationController.PAN_DIRECTION_RIGHT); return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP: mAms.getMagnificationController().panMagnificationByStep( displayId, MagnificationController.PAN_DIRECTION_UP); return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN: mAms.getMagnificationController().panMagnificationByStep( displayId, MagnificationController.PAN_DIRECTION_DOWN); return true; } return false; Loading @@ -270,7 +293,11 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo public boolean isKeyGestureSupported(int gestureType) { return switch (gestureType) { case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT -> true; KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN -> true; default -> false; }; } Loading services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +144 −7 Original line number Diff line number Diff line Loading @@ -35,14 +35,19 @@ import android.content.Context; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.DisplayManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.DisplayMetrics; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseDoubleArray; import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.TypedValue; import android.view.Display; import android.view.accessibility.MagnificationAnimationCallback; import com.android.internal.accessibility.util.AccessibilityStatsLogUtils; Loading Loading @@ -102,6 +107,7 @@ public class MagnificationController implements MagnificationConnectionManager.C /** Whether the platform supports window magnification feature. */ private final boolean mSupportWindowMagnification; private final MagnificationScaleStepProvider mScaleStepProvider; private final MagnificationPanStepProvider mPanStepProvider; private final Executor mBackgroundExecutor; Loading Loading @@ -132,7 +138,7 @@ public class MagnificationController implements MagnificationConnectionManager.C .UiChangesForAccessibilityCallbacks> mAccessibilityCallbacksDelegateArray = new SparseArray<>(); // Direction magnifier scale can be altered. // Direction magnification scale can be altered. public static final int ZOOM_DIRECTION_IN = 0; public static final int ZOOM_DIRECTION_OUT = 1; Loading @@ -140,6 +146,16 @@ public class MagnificationController implements MagnificationConnectionManager.C public @interface ZoomDirection { } // Directions magnification center can be moved. public static final int PAN_DIRECTION_LEFT = 0; public static final int PAN_DIRECTION_RIGHT = 1; public static final int PAN_DIRECTION_UP = 2; public static final int PAN_DIRECTION_DOWN = 3; @IntDef({PAN_DIRECTION_LEFT, PAN_DIRECTION_RIGHT, PAN_DIRECTION_UP, PAN_DIRECTION_DOWN}) public @interface PanDirection { } /** * A callback to inform the magnification transition result on the given display. */ Loading Loading @@ -188,6 +204,87 @@ public class MagnificationController implements MagnificationConnectionManager.C } } /** * An interface to configure how much the magnification center should be affected when panning * in steps. */ public interface MagnificationPanStepProvider { /** * Calculate the next value based on the current scale. * * @param currentScale The current magnification scale value. * @param displayId The displayId for the display being magnified. * @return The next pan step value. */ float nextPanStep(float currentScale, int displayId); } public static class DefaultMagnificationPanStepProvider implements MagnificationPanStepProvider, DisplayManager.DisplayListener { // We want panning to be 40 dip per keystroke at scale 2, and 1 dip per keystroke at scale // 20. This can be defined using y = mx + b to get the slope and intercept. // This works even if the device does not allow magnification up to 20x; we will still get // a reasonable lineary ramp of panning movement for each scale step. private static final float DEFAULT_SCALE = 2.0f; private static final float PAN_STEP_AT_DEFAULT_SCALE_DIP = 40.0f; private static final float SCALE_FOR_1_DIP_PAN = 20.0f; private SparseDoubleArray mPanStepSlopes; private SparseDoubleArray mPanStepIntercepts; private final DisplayManager mDisplayManager; DefaultMagnificationPanStepProvider(Context context) { mDisplayManager = context.getSystemService(DisplayManager.class); mDisplayManager.registerDisplayListener(this, /*handler=*/null); mPanStepSlopes = new SparseDoubleArray(); mPanStepIntercepts = new SparseDoubleArray(); } @Override public void onDisplayAdded(int displayId) { updateForDisplay(displayId); } @Override public void onDisplayChanged(int displayId) { updateForDisplay(displayId); } @Override public void onDisplayRemoved(int displayId) { mPanStepSlopes.delete(displayId); mPanStepIntercepts.delete(displayId); } @Override public float nextPanStep(float currentScale, int displayId) { if (mPanStepSlopes.indexOfKey(displayId) < 0) { updateForDisplay(displayId); } return Math.max((float) (mPanStepSlopes.get(displayId) * currentScale + mPanStepIntercepts.get(displayId)), 1); } private void updateForDisplay(int displayId) { Display display = mDisplayManager.getDisplay(displayId); if (display == null) { return; } DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); final float panStepAtDefaultScaleInPx = TypedValue.convertDimensionToPixels( TypedValue.COMPLEX_UNIT_DIP, PAN_STEP_AT_DEFAULT_SCALE_DIP, metrics); final float panStepAtMaxScaleInPx = TypedValue.convertDimensionToPixels( TypedValue.COMPLEX_UNIT_DIP, 1.0f, metrics); final float panStepSlope = (panStepAtMaxScaleInPx - panStepAtDefaultScaleInPx) / (SCALE_FOR_1_DIP_PAN - DEFAULT_SCALE); mPanStepSlopes.put(displayId, panStepSlope); mPanStepIntercepts.put(displayId, panStepAtDefaultScaleInPx - panStepSlope * DEFAULT_SCALE); } } public MagnificationController(AccessibilityManagerService ams, Object lock, Context context, MagnificationScaleProvider scaleProvider, Executor backgroundExecutor) { Loading @@ -201,6 +298,7 @@ public class MagnificationController implements MagnificationConnectionManager.C mSupportWindowMagnification = context.getPackageManager().hasSystemFeature( FEATURE_WINDOW_MAGNIFICATION); mScaleStepProvider = new DefaultMagnificationScaleStepProvider(); mPanStepProvider = new DefaultMagnificationPanStepProvider(mContext); mAlwaysOnMagnificationFeatureFlag = new AlwaysOnMagnificationFeatureFlag(context); mAlwaysOnMagnificationFeatureFlag.addOnChangedListener( Loading Loading @@ -935,13 +1033,12 @@ public class MagnificationController implements MagnificationConnectionManager.C } /** * Scales the magnifier on the given display one step in/out based on the zoomIn param. * Scales the magnifier on the given display one step in/out based on the direction param. * * @param displayId The logical display id. * @param direction Whether the scale should be zoomed in or out. * @return {@code true} if the magnification scale was affected. */ public boolean scaleMagnificationByStep(int displayId, @ZoomDirection int direction) { public void scaleMagnificationByStep(int displayId, @ZoomDirection int direction) { if (getFullScreenMagnificationController().isActivated(displayId)) { final float magnificationScale = getFullScreenMagnificationController().getScale( displayId); Loading @@ -950,7 +1047,6 @@ public class MagnificationController implements MagnificationConnectionManager.C getFullScreenMagnificationController().setScaleAndCenter(displayId, nextMagnificationScale, Float.NaN, Float.NaN, true, MAGNIFICATION_GESTURE_HANDLER_ID); return nextMagnificationScale != magnificationScale; } if (getMagnificationConnectionManager().isWindowMagnifierEnabled(displayId)) { Loading @@ -959,10 +1055,51 @@ public class MagnificationController implements MagnificationConnectionManager.C final float nextMagnificationScale = mScaleStepProvider.nextScaleStep( magnificationScale, direction); getMagnificationConnectionManager().setScale(displayId, nextMagnificationScale); return nextMagnificationScale != magnificationScale; } } return false; /** * Pans the magnifier on the given display one step left/right/up/down based on the direction * param. * * @param displayId The logical display id. * @param direction Whether the direction should be left/right/up/down. */ public void panMagnificationByStep(int displayId, @PanDirection int direction) { final boolean fullscreenActivated = getFullScreenMagnificationController().isActivated(displayId); final boolean windowActivated = getMagnificationConnectionManager().isWindowMagnifierEnabled(displayId); if (!fullscreenActivated && !windowActivated) { return; } final float scale = fullscreenActivated ? getFullScreenMagnificationController().getScale(displayId) : getMagnificationConnectionManager().getScale(displayId); final float step = mPanStepProvider.nextPanStep(scale, displayId); float offsetX = 0; float offsetY = 0; if (direction == PAN_DIRECTION_LEFT) { offsetX = -step; } else if (direction == PAN_DIRECTION_RIGHT) { offsetX = step; } else if (direction == PAN_DIRECTION_UP) { offsetY = -step; } else if (direction == PAN_DIRECTION_DOWN) { offsetY = step; } if (fullscreenActivated) { final float centerX = getFullScreenMagnificationController().getCenterX(displayId); final float centerY = getFullScreenMagnificationController().getCenterY(displayId); getFullScreenMagnificationController().setScaleAndCenter(displayId, scale, centerX + offsetX, centerY + offsetY, true, MAGNIFICATION_GESTURE_HANDLER_ID); } else { getMagnificationConnectionManager().moveWindowMagnification(displayId, offsetX, offsetY); } } private final class DisableMagnificationCallback implements Loading services/core/java/com/android/server/input/InputGestureManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -221,6 +221,18 @@ final class InputGestureManager { systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_EQUALS, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_UP, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_M, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION)); Loading services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java +233 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/hardware/input/KeyGestureEvent.java +17 −2 Original line number Diff line number Diff line Loading @@ -125,7 +125,10 @@ public final class KeyGestureEvent { 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_MAGNIFIER_PAN_LEFT = 78; public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT = 79; public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP = 80; public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN = 81; public static final int FLAG_CANCELLED = 1; Loading Loading @@ -217,7 +220,11 @@ public final class KeyGestureEvent { 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_TOGGLE_DO_NOT_DISTURB, KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT, KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT, KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP, KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN, }) @Retention(RetentionPolicy.SOURCE) public @interface KeyGestureType { Loading Loading @@ -792,6 +799,14 @@ 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_MAGNIFIER_PAN_LEFT: return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT"; case KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT: return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT"; case KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP: return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP"; case KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN: return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN"; default: return Integer.toHexString(value); } Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +32 −5 Original line number Diff line number Diff line Loading @@ -245,22 +245,45 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo 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_MAGNIFIER_ZOOM_IN: if (complete) { mAms.getMagnificationController().scaleMagnificationByStep( displayId, MagnificationController.ZOOM_DIRECTION_IN); } return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT: if (complete) { mAms.getMagnificationController().scaleMagnificationByStep( displayId, MagnificationController.ZOOM_DIRECTION_OUT); } return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT: mAms.getMagnificationController().panMagnificationByStep( displayId, MagnificationController.PAN_DIRECTION_LEFT); return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT: mAms.getMagnificationController().panMagnificationByStep( displayId, MagnificationController.PAN_DIRECTION_RIGHT); return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP: mAms.getMagnificationController().panMagnificationByStep( displayId, MagnificationController.PAN_DIRECTION_UP); return true; case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN: mAms.getMagnificationController().panMagnificationByStep( displayId, MagnificationController.PAN_DIRECTION_DOWN); return true; } return false; Loading @@ -270,7 +293,11 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo public boolean isKeyGestureSupported(int gestureType) { return switch (gestureType) { case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT -> true; KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN -> true; default -> false; }; } Loading
services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +144 −7 Original line number Diff line number Diff line Loading @@ -35,14 +35,19 @@ import android.content.Context; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.DisplayManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.DisplayMetrics; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseDoubleArray; import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.TypedValue; import android.view.Display; import android.view.accessibility.MagnificationAnimationCallback; import com.android.internal.accessibility.util.AccessibilityStatsLogUtils; Loading Loading @@ -102,6 +107,7 @@ public class MagnificationController implements MagnificationConnectionManager.C /** Whether the platform supports window magnification feature. */ private final boolean mSupportWindowMagnification; private final MagnificationScaleStepProvider mScaleStepProvider; private final MagnificationPanStepProvider mPanStepProvider; private final Executor mBackgroundExecutor; Loading Loading @@ -132,7 +138,7 @@ public class MagnificationController implements MagnificationConnectionManager.C .UiChangesForAccessibilityCallbacks> mAccessibilityCallbacksDelegateArray = new SparseArray<>(); // Direction magnifier scale can be altered. // Direction magnification scale can be altered. public static final int ZOOM_DIRECTION_IN = 0; public static final int ZOOM_DIRECTION_OUT = 1; Loading @@ -140,6 +146,16 @@ public class MagnificationController implements MagnificationConnectionManager.C public @interface ZoomDirection { } // Directions magnification center can be moved. public static final int PAN_DIRECTION_LEFT = 0; public static final int PAN_DIRECTION_RIGHT = 1; public static final int PAN_DIRECTION_UP = 2; public static final int PAN_DIRECTION_DOWN = 3; @IntDef({PAN_DIRECTION_LEFT, PAN_DIRECTION_RIGHT, PAN_DIRECTION_UP, PAN_DIRECTION_DOWN}) public @interface PanDirection { } /** * A callback to inform the magnification transition result on the given display. */ Loading Loading @@ -188,6 +204,87 @@ public class MagnificationController implements MagnificationConnectionManager.C } } /** * An interface to configure how much the magnification center should be affected when panning * in steps. */ public interface MagnificationPanStepProvider { /** * Calculate the next value based on the current scale. * * @param currentScale The current magnification scale value. * @param displayId The displayId for the display being magnified. * @return The next pan step value. */ float nextPanStep(float currentScale, int displayId); } public static class DefaultMagnificationPanStepProvider implements MagnificationPanStepProvider, DisplayManager.DisplayListener { // We want panning to be 40 dip per keystroke at scale 2, and 1 dip per keystroke at scale // 20. This can be defined using y = mx + b to get the slope and intercept. // This works even if the device does not allow magnification up to 20x; we will still get // a reasonable lineary ramp of panning movement for each scale step. private static final float DEFAULT_SCALE = 2.0f; private static final float PAN_STEP_AT_DEFAULT_SCALE_DIP = 40.0f; private static final float SCALE_FOR_1_DIP_PAN = 20.0f; private SparseDoubleArray mPanStepSlopes; private SparseDoubleArray mPanStepIntercepts; private final DisplayManager mDisplayManager; DefaultMagnificationPanStepProvider(Context context) { mDisplayManager = context.getSystemService(DisplayManager.class); mDisplayManager.registerDisplayListener(this, /*handler=*/null); mPanStepSlopes = new SparseDoubleArray(); mPanStepIntercepts = new SparseDoubleArray(); } @Override public void onDisplayAdded(int displayId) { updateForDisplay(displayId); } @Override public void onDisplayChanged(int displayId) { updateForDisplay(displayId); } @Override public void onDisplayRemoved(int displayId) { mPanStepSlopes.delete(displayId); mPanStepIntercepts.delete(displayId); } @Override public float nextPanStep(float currentScale, int displayId) { if (mPanStepSlopes.indexOfKey(displayId) < 0) { updateForDisplay(displayId); } return Math.max((float) (mPanStepSlopes.get(displayId) * currentScale + mPanStepIntercepts.get(displayId)), 1); } private void updateForDisplay(int displayId) { Display display = mDisplayManager.getDisplay(displayId); if (display == null) { return; } DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); final float panStepAtDefaultScaleInPx = TypedValue.convertDimensionToPixels( TypedValue.COMPLEX_UNIT_DIP, PAN_STEP_AT_DEFAULT_SCALE_DIP, metrics); final float panStepAtMaxScaleInPx = TypedValue.convertDimensionToPixels( TypedValue.COMPLEX_UNIT_DIP, 1.0f, metrics); final float panStepSlope = (panStepAtMaxScaleInPx - panStepAtDefaultScaleInPx) / (SCALE_FOR_1_DIP_PAN - DEFAULT_SCALE); mPanStepSlopes.put(displayId, panStepSlope); mPanStepIntercepts.put(displayId, panStepAtDefaultScaleInPx - panStepSlope * DEFAULT_SCALE); } } public MagnificationController(AccessibilityManagerService ams, Object lock, Context context, MagnificationScaleProvider scaleProvider, Executor backgroundExecutor) { Loading @@ -201,6 +298,7 @@ public class MagnificationController implements MagnificationConnectionManager.C mSupportWindowMagnification = context.getPackageManager().hasSystemFeature( FEATURE_WINDOW_MAGNIFICATION); mScaleStepProvider = new DefaultMagnificationScaleStepProvider(); mPanStepProvider = new DefaultMagnificationPanStepProvider(mContext); mAlwaysOnMagnificationFeatureFlag = new AlwaysOnMagnificationFeatureFlag(context); mAlwaysOnMagnificationFeatureFlag.addOnChangedListener( Loading Loading @@ -935,13 +1033,12 @@ public class MagnificationController implements MagnificationConnectionManager.C } /** * Scales the magnifier on the given display one step in/out based on the zoomIn param. * Scales the magnifier on the given display one step in/out based on the direction param. * * @param displayId The logical display id. * @param direction Whether the scale should be zoomed in or out. * @return {@code true} if the magnification scale was affected. */ public boolean scaleMagnificationByStep(int displayId, @ZoomDirection int direction) { public void scaleMagnificationByStep(int displayId, @ZoomDirection int direction) { if (getFullScreenMagnificationController().isActivated(displayId)) { final float magnificationScale = getFullScreenMagnificationController().getScale( displayId); Loading @@ -950,7 +1047,6 @@ public class MagnificationController implements MagnificationConnectionManager.C getFullScreenMagnificationController().setScaleAndCenter(displayId, nextMagnificationScale, Float.NaN, Float.NaN, true, MAGNIFICATION_GESTURE_HANDLER_ID); return nextMagnificationScale != magnificationScale; } if (getMagnificationConnectionManager().isWindowMagnifierEnabled(displayId)) { Loading @@ -959,10 +1055,51 @@ public class MagnificationController implements MagnificationConnectionManager.C final float nextMagnificationScale = mScaleStepProvider.nextScaleStep( magnificationScale, direction); getMagnificationConnectionManager().setScale(displayId, nextMagnificationScale); return nextMagnificationScale != magnificationScale; } } return false; /** * Pans the magnifier on the given display one step left/right/up/down based on the direction * param. * * @param displayId The logical display id. * @param direction Whether the direction should be left/right/up/down. */ public void panMagnificationByStep(int displayId, @PanDirection int direction) { final boolean fullscreenActivated = getFullScreenMagnificationController().isActivated(displayId); final boolean windowActivated = getMagnificationConnectionManager().isWindowMagnifierEnabled(displayId); if (!fullscreenActivated && !windowActivated) { return; } final float scale = fullscreenActivated ? getFullScreenMagnificationController().getScale(displayId) : getMagnificationConnectionManager().getScale(displayId); final float step = mPanStepProvider.nextPanStep(scale, displayId); float offsetX = 0; float offsetY = 0; if (direction == PAN_DIRECTION_LEFT) { offsetX = -step; } else if (direction == PAN_DIRECTION_RIGHT) { offsetX = step; } else if (direction == PAN_DIRECTION_UP) { offsetY = -step; } else if (direction == PAN_DIRECTION_DOWN) { offsetY = step; } if (fullscreenActivated) { final float centerX = getFullScreenMagnificationController().getCenterX(displayId); final float centerY = getFullScreenMagnificationController().getCenterY(displayId); getFullScreenMagnificationController().setScaleAndCenter(displayId, scale, centerX + offsetX, centerY + offsetY, true, MAGNIFICATION_GESTURE_HANDLER_ID); } else { getMagnificationConnectionManager().moveWindowMagnification(displayId, offsetX, offsetY); } } private final class DisableMagnificationCallback implements Loading
services/core/java/com/android/server/input/InputGestureManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -221,6 +221,18 @@ final class InputGestureManager { systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_EQUALS, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_UP, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN)); systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_M, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION)); Loading
services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java +233 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes