Loading packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +52 −18 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static android.view.WindowManager.LayoutParams; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; Loading @@ -28,7 +30,6 @@ import android.content.res.Resources; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; Loading Loading @@ -66,7 +67,7 @@ import java.util.Locale; * Class to handle adding and removing a window magnification. */ class WindowMagnificationController implements View.OnTouchListener, SurfaceHolder.Callback, MirrorWindowControl.MirrorWindowDelegate { MirrorWindowControl.MirrorWindowDelegate, MagnificationGestureDetector.OnGestureListener { private static final String TAG = "WindowMagnificationController"; // Delay to avoid updating state description too frequently. Loading @@ -74,6 +75,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold // It should be consistent with the value defined in WindowMagnificationGestureHandler. private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(2.0f, 8.0f); private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f; private static final float ANIMATION_BOUNCE_EFFECT_SCALE = 1.05f; private final Context mContext; private final Resources mResources; private final Handler mHandler; Loading Loading @@ -102,7 +104,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private View mRightDrag; private View mBottomDrag; private final PointF mLastDrag = new PointF(); @NonNull private final WindowMagnifierCallback mWindowMagnifierCallback; Loading @@ -123,9 +124,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private int mNavGestureHeight; private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; private final MagnificationGestureDetector mGestureDetector; private final int mBounceEffectDuration; private Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback; private Locale mLocale; private NumberFormat mPercentFormat; private float mBounceEffectAnimationScale; @Nullable private MirrorWindowControl mMirrorWindowControl; Loading @@ -147,14 +151,19 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mResources = mContext.getResources(); mScale = mResources.getInteger(R.integer.magnification_default_scale); mBounceEffectDuration = mResources.getInteger( com.android.internal.R.integer.config_shortAnimTime); updateDimensions(); setInitialStartBounds(); computeBounceAnimationScale(); mMirrorWindowControl = mirrorWindowControl; if (mMirrorWindowControl != null) { mMirrorWindowControl.setWindowDelegate(this); } mTransaction = transaction; setInitialStartBounds(); mGestureDetector = new MagnificationGestureDetector(mContext, handler, this); // Initialize listeners. mMirrorViewRunnable = () -> { Loading Loading @@ -203,6 +212,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold updateNavigationBarDimensions(); } private void computeBounceAnimationScale() { final float windowWidth = mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin; final float visibleWindowWidth = windowWidth - 2 * mOuterBorderSize; final float animationScaleMax = windowWidth / visibleWindowWidth; mBounceEffectAnimationScale = Math.min(animationScaleMax, ANIMATION_BOUNCE_EFFECT_SCALE); } private void updateNavigationBarDimensions() { if (!supportsSwipeUpGesture()) { mNavGestureHeight = 0; Loading Loading @@ -248,6 +264,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold void onConfigurationChanged(int configDiff) { if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) { updateDimensions(); computeBounceAnimationScale(); if (isWindowVisible()) { deleteWindowMagnification(); enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); Loading Loading @@ -483,20 +500,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold public boolean onTouch(View v, MotionEvent event) { if (v == mDragView || v == mLeftDrag || v == mTopDrag || v == mRightDrag || v == mBottomDrag) { return handleDragTouchEvent(event); } return false; } private boolean handleDragTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastDrag.set(event.getRawX(), event.getRawY()); return true; case MotionEvent.ACTION_MOVE: moveWindowMagnifier(event.getRawX() - mLastDrag.x, event.getRawY() - mLastDrag.y); mLastDrag.set(event.getRawX(), event.getRawY()); return true; return mGestureDetector.onTouch(event); } return false; } Loading Loading @@ -685,6 +689,36 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return mPercentFormat.format(scale); } @Override public boolean onSingleTap() { animateBounceEffect(); return true; } @Override public boolean onDrag(float offsetX, float offsetY) { moveWindowMagnifier(offsetX, offsetY); return true; } @Override public boolean onStart(float x, float y) { return true; } @Override public boolean onFinish(float x, float y) { return false; } private void animateBounceEffect() { final ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(mMirrorView, PropertyValuesHolder.ofFloat(View.SCALE_X, 1, mBounceEffectAnimationScale, 1), PropertyValuesHolder.ofFloat(View.SCALE_Y, 1, mBounceEffectAnimationScale, 1)); scaleAnimator.setDuration(mBounceEffectDuration); scaleAnimator.start(); } private class MirrorWindowA11yDelegate extends View.AccessibilityDelegate { @Override Loading packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +24 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; Loading @@ -40,6 +41,7 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.os.Handler; import android.os.SystemClock; import android.testing.AndroidTestingRunner; import android.testing.TestableResources; import android.view.Display; Loading Loading @@ -347,4 +349,26 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { verify(mWindowManager).updateViewLayout(eq(mMirrorView), paramsArgumentCaptor.capture()); assertEquals(newA11yWindowTitle, paramsArgumentCaptor.getValue().accessibilityTitle); } @Test public void onSingleTap_enabled_scaleIsChanged() { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); }); mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.onSingleTap(); }); final long timeout = SystemClock.uptimeMillis() + 1000; while (SystemClock.uptimeMillis() < timeout) { SystemClock.sleep(10); if (Float.compare(1.0f, mMirrorView.getScaleX()) < 0) { return; } } fail("mMirrorView scale is not changed"); } } Loading
packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +52 −18 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static android.view.WindowManager.LayoutParams; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; Loading @@ -28,7 +30,6 @@ import android.content.res.Resources; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; Loading Loading @@ -66,7 +67,7 @@ import java.util.Locale; * Class to handle adding and removing a window magnification. */ class WindowMagnificationController implements View.OnTouchListener, SurfaceHolder.Callback, MirrorWindowControl.MirrorWindowDelegate { MirrorWindowControl.MirrorWindowDelegate, MagnificationGestureDetector.OnGestureListener { private static final String TAG = "WindowMagnificationController"; // Delay to avoid updating state description too frequently. Loading @@ -74,6 +75,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold // It should be consistent with the value defined in WindowMagnificationGestureHandler. private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(2.0f, 8.0f); private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f; private static final float ANIMATION_BOUNCE_EFFECT_SCALE = 1.05f; private final Context mContext; private final Resources mResources; private final Handler mHandler; Loading Loading @@ -102,7 +104,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private View mRightDrag; private View mBottomDrag; private final PointF mLastDrag = new PointF(); @NonNull private final WindowMagnifierCallback mWindowMagnifierCallback; Loading @@ -123,9 +124,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private int mNavGestureHeight; private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; private final MagnificationGestureDetector mGestureDetector; private final int mBounceEffectDuration; private Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback; private Locale mLocale; private NumberFormat mPercentFormat; private float mBounceEffectAnimationScale; @Nullable private MirrorWindowControl mMirrorWindowControl; Loading @@ -147,14 +151,19 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mResources = mContext.getResources(); mScale = mResources.getInteger(R.integer.magnification_default_scale); mBounceEffectDuration = mResources.getInteger( com.android.internal.R.integer.config_shortAnimTime); updateDimensions(); setInitialStartBounds(); computeBounceAnimationScale(); mMirrorWindowControl = mirrorWindowControl; if (mMirrorWindowControl != null) { mMirrorWindowControl.setWindowDelegate(this); } mTransaction = transaction; setInitialStartBounds(); mGestureDetector = new MagnificationGestureDetector(mContext, handler, this); // Initialize listeners. mMirrorViewRunnable = () -> { Loading Loading @@ -203,6 +212,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold updateNavigationBarDimensions(); } private void computeBounceAnimationScale() { final float windowWidth = mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin; final float visibleWindowWidth = windowWidth - 2 * mOuterBorderSize; final float animationScaleMax = windowWidth / visibleWindowWidth; mBounceEffectAnimationScale = Math.min(animationScaleMax, ANIMATION_BOUNCE_EFFECT_SCALE); } private void updateNavigationBarDimensions() { if (!supportsSwipeUpGesture()) { mNavGestureHeight = 0; Loading Loading @@ -248,6 +264,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold void onConfigurationChanged(int configDiff) { if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) { updateDimensions(); computeBounceAnimationScale(); if (isWindowVisible()) { deleteWindowMagnification(); enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); Loading Loading @@ -483,20 +500,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold public boolean onTouch(View v, MotionEvent event) { if (v == mDragView || v == mLeftDrag || v == mTopDrag || v == mRightDrag || v == mBottomDrag) { return handleDragTouchEvent(event); } return false; } private boolean handleDragTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastDrag.set(event.getRawX(), event.getRawY()); return true; case MotionEvent.ACTION_MOVE: moveWindowMagnifier(event.getRawX() - mLastDrag.x, event.getRawY() - mLastDrag.y); mLastDrag.set(event.getRawX(), event.getRawY()); return true; return mGestureDetector.onTouch(event); } return false; } Loading Loading @@ -685,6 +689,36 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return mPercentFormat.format(scale); } @Override public boolean onSingleTap() { animateBounceEffect(); return true; } @Override public boolean onDrag(float offsetX, float offsetY) { moveWindowMagnifier(offsetX, offsetY); return true; } @Override public boolean onStart(float x, float y) { return true; } @Override public boolean onFinish(float x, float y) { return false; } private void animateBounceEffect() { final ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(mMirrorView, PropertyValuesHolder.ofFloat(View.SCALE_X, 1, mBounceEffectAnimationScale, 1), PropertyValuesHolder.ofFloat(View.SCALE_Y, 1, mBounceEffectAnimationScale, 1)); scaleAnimator.setDuration(mBounceEffectDuration); scaleAnimator.start(); } private class MirrorWindowA11yDelegate extends View.AccessibilityDelegate { @Override Loading
packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +24 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; Loading @@ -40,6 +41,7 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.os.Handler; import android.os.SystemClock; import android.testing.AndroidTestingRunner; import android.testing.TestableResources; import android.view.Display; Loading Loading @@ -347,4 +349,26 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { verify(mWindowManager).updateViewLayout(eq(mMirrorView), paramsArgumentCaptor.capture()); assertEquals(newA11yWindowTitle, paramsArgumentCaptor.getValue().accessibilityTitle); } @Test public void onSingleTap_enabled_scaleIsChanged() { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); }); mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.onSingleTap(); }); final long timeout = SystemClock.uptimeMillis() + 1000; while (SystemClock.uptimeMillis() < timeout) { SystemClock.sleep(10); if (Float.compare(1.0f, mMirrorView.getScaleX()) < 0) { return; } } fail("mMirrorView scale is not changed"); } }