Loading packages/SystemUI/res/layout/window_magnifier_view.xml +1 −2 Original line number Diff line number Diff line Loading @@ -77,8 +77,7 @@ android:layout_height="@dimen/magnification_drag_view_size" android:layout_margin="@dimen/magnification_inner_border_margin" android:layout_gravity="right|bottom" android:paddingEnd="@dimen/magnifier_drag_handle_padding" android:paddingBottom="@dimen/magnifier_drag_handle_padding" android:padding="@dimen/magnifier_drag_handle_padding" android:scaleType="center" android:importantForAccessibility="no" android:src="@drawable/ic_move_magnification"/> Loading packages/SystemUI/res/values/dimens.xml +3 −0 Original line number Diff line number Diff line Loading @@ -1080,6 +1080,9 @@ <!-- The extra padding to show the whole outer border --> <dimen name="magnifier_drag_handle_padding">3dp</dimen> <dimen name="magnification_max_frame_size">300dp</dimen> <!-- How far from the right edge of the screen you need to drag the window before the button repositions to the other side. --> <dimen name="magnification_button_reposition_threshold_from_edge">32dp</dimen> <!-- Home Controls --> <dimen name="controls_header_menu_size">48dp</dimen> Loading packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +9 −3 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.hardware.display.DisplayManager; import android.os.Handler; import android.view.Display; import android.view.SurfaceControl; import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.accessibility.IWindowMagnificationConnection; Loading Loading @@ -89,9 +90,14 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null); return new WindowMagnificationController( windowContext, mHandler, new WindowMagnificationAnimationController(windowContext), new SfVsyncFrameCallbackProvider(), null, new SurfaceControl.Transaction(), mWindowMagnifierCallback, mSysUiState); mHandler, new WindowMagnificationAnimationController(windowContext), new SfVsyncFrameCallbackProvider(), null, new SurfaceControl.Transaction(), mWindowMagnifierCallback, mSysUiState, WindowManagerGlobal::getWindowSession); } } Loading packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +64 −13 Original line number Diff line number Diff line Loading @@ -57,11 +57,11 @@ import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.WindowMetrics; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.widget.FrameLayout; import androidx.core.math.MathUtils; Loading @@ -75,6 +75,7 @@ import java.io.PrintWriter; import java.text.NumberFormat; import java.util.Collections; import java.util.Locale; import java.util.function.Supplier; /** * Class to handle adding and removing a window magnification. Loading @@ -92,6 +93,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold 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 @@ -163,8 +165,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private SurfaceView mMirrorSurfaceView; private int mMirrorSurfaceMargin; private int mBorderDragSize; private int mDragViewSize; private int mOuterBorderSize; /** * How far from the right edge of the screen you need to drag the window before the button * repositions to the other side. */ private int mButtonRepositionThresholdFromEdge; // The boundary of magnification frame. private final Rect mMagnificationFrameBoundary = new Rect(); // The top Y of the system gesture rect at the bottom. Set to -1 if it is invalid. Loading @@ -172,6 +179,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private int mMinWindowSize; private final WindowMagnificationAnimationController mAnimationController; private final Supplier<IWindowSession> mGlobalWindowSessionSupplier; private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; private final MagnificationGestureDetector mGestureDetector; private final int mBounceEffectDuration; Loading @@ -182,18 +190,25 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private SysUiState mSysUiState; // Set it to true when the view is overlapped with the gesture insets at the bottom. private boolean mOverlapWithGestureInsets; private boolean mIsDragging; @Nullable private MirrorWindowControl mMirrorWindowControl; WindowMagnificationController(@UiContext Context context, @NonNull Handler handler, WindowMagnificationController( @UiContext Context context, @NonNull Handler handler, @NonNull WindowMagnificationAnimationController animationController, SfVsyncFrameCallbackProvider sfVsyncFrameProvider, MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, @NonNull WindowMagnifierCallback callback, SysUiState sysUiState) { MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, @NonNull WindowMagnifierCallback callback, SysUiState sysUiState, @NonNull Supplier<IWindowSession> globalWindowSessionSupplier) { mContext = context; mHandler = handler; mAnimationController = animationController; mGlobalWindowSessionSupplier = globalWindowSessionSupplier; mAnimationController.setWindowMagnificationController(this); mSfVsyncFrameProvider = sfVsyncFrameProvider; mWindowMagnifierCallback = callback; Loading Loading @@ -249,8 +264,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold }; mMirrorSurfaceViewLayoutChangeListener = (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> applyTapExcludeRegion(); (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> mMirrorView.post(this::applyTapExcludeRegion); mMirrorViewGeometryVsyncCallback = l -> { Loading Loading @@ -283,10 +298,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold R.dimen.magnification_mirror_surface_margin); mBorderDragSize = mResources.getDimensionPixelSize( R.dimen.magnification_border_drag_size); mDragViewSize = mResources.getDimensionPixelSize( R.dimen.magnification_drag_view_size); mOuterBorderSize = mResources.getDimensionPixelSize( R.dimen.magnification_outer_border_margin); mButtonRepositionThresholdFromEdge = mResources.getDimensionPixelSize( R.dimen.magnification_button_reposition_threshold_from_edge); mMinWindowSize = mResources.getDimensionPixelSize( com.android.internal.R.dimen.accessibility_window_magnifier_min_size); } Loading Loading @@ -551,10 +567,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } private void applyTapExcludeRegion() { // Sometimes this can get posted and run after deleteWindowMagnification() is called. if (mMirrorView == null) return; final Region tapExcludeRegion = calculateTapExclude(); final IWindow window = IWindow.Stub.asInterface(mMirrorView.getWindowToken()); try { IWindowSession session = WindowManagerGlobal.getWindowSession(); IWindowSession session = mGlobalWindowSessionSupplier.get(); session.updateTapExcludeRegion(window, tapExcludeRegion); } catch (RemoteException e) { } Loading @@ -564,9 +583,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold Region regionInsideDragBorder = new Region(mBorderDragSize, mBorderDragSize, mMirrorView.getWidth() - mBorderDragSize, mMirrorView.getHeight() - mBorderDragSize); Rect dragArea = new Rect(mMirrorView.getWidth() - mDragViewSize - mBorderDragSize, mMirrorView.getHeight() - mDragViewSize - mBorderDragSize, mMirrorView.getWidth(), mMirrorView.getHeight()); Rect dragArea = new Rect(); mDragView.getHitRect(dragArea); regionInsideDragBorder.op(dragArea, Region.Op.DIFFERENCE); return regionInsideDragBorder; } Loading Loading @@ -713,6 +732,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorView.setTranslationX(translationX); mMirrorView.setTranslationY(translationY); mWm.updateViewLayout(mMirrorView, params); // If they are not dragging the handle, we can move the drag handle immediately without // disruption. But if they are dragging it, we avoid moving until the end of the drag. if (!mIsDragging) { mMirrorView.post(this::maybeRepositionButton); } } @Override Loading Loading @@ -1060,14 +1085,40 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold @Override public boolean onStart(float x, float y) { mIsDragging = true; return true; } @Override public boolean onFinish(float x, float y) { maybeRepositionButton(); mIsDragging = false; return false; } /** Moves the button to the opposite edge if the frame is against the edge of the screen. */ private void maybeRepositionButton() { if (mMirrorView == null) return; final float screenEdgeX = mWindowBounds.right - mButtonRepositionThresholdFromEdge; final FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mDragView.getLayoutParams(); mMirrorView.getBoundsOnScreen(mTmpRect); final int newGravity; if (mTmpRect.right >= screenEdgeX) { newGravity = Gravity.BOTTOM | Gravity.LEFT; } else { newGravity = Gravity.BOTTOM | Gravity.RIGHT; } if (newGravity != layoutParams.gravity) { layoutParams.gravity = newGravity; mDragView.setLayoutParams(layoutParams); mDragView.post(this::applyTapExcludeRegion); } } private void animateBounceEffect() { final ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(mMirrorView, PropertyValuesHolder.ofFloat(View.SCALE_X, 1, mBounceEffectAnimationScale, 1), Loading packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java +11 −2 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.testing.AndroidTestingRunner; import android.view.SurfaceControl; import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.animation.AccelerateInterpolator; Loading Loading @@ -761,8 +762,16 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { SfVsyncFrameCallbackProvider sfVsyncFrameProvider, MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, WindowMagnifierCallback callback, SysUiState sysUiState) { super(context, handler, animationController, sfVsyncFrameProvider, mirrorWindowControl, transaction, callback, sysUiState); super( context, handler, animationController, sfVsyncFrameProvider, mirrorWindowControl, transaction, callback, sysUiState, WindowManagerGlobal::getWindowSession); mSpyController = Mockito.mock(WindowMagnificationController.class); } Loading Loading
packages/SystemUI/res/layout/window_magnifier_view.xml +1 −2 Original line number Diff line number Diff line Loading @@ -77,8 +77,7 @@ android:layout_height="@dimen/magnification_drag_view_size" android:layout_margin="@dimen/magnification_inner_border_margin" android:layout_gravity="right|bottom" android:paddingEnd="@dimen/magnifier_drag_handle_padding" android:paddingBottom="@dimen/magnifier_drag_handle_padding" android:padding="@dimen/magnifier_drag_handle_padding" android:scaleType="center" android:importantForAccessibility="no" android:src="@drawable/ic_move_magnification"/> Loading
packages/SystemUI/res/values/dimens.xml +3 −0 Original line number Diff line number Diff line Loading @@ -1080,6 +1080,9 @@ <!-- The extra padding to show the whole outer border --> <dimen name="magnifier_drag_handle_padding">3dp</dimen> <dimen name="magnification_max_frame_size">300dp</dimen> <!-- How far from the right edge of the screen you need to drag the window before the button repositions to the other side. --> <dimen name="magnification_button_reposition_threshold_from_edge">32dp</dimen> <!-- Home Controls --> <dimen name="controls_header_menu_size">48dp</dimen> Loading
packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +9 −3 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.hardware.display.DisplayManager; import android.os.Handler; import android.view.Display; import android.view.SurfaceControl; import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.accessibility.IWindowMagnificationConnection; Loading Loading @@ -89,9 +90,14 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null); return new WindowMagnificationController( windowContext, mHandler, new WindowMagnificationAnimationController(windowContext), new SfVsyncFrameCallbackProvider(), null, new SurfaceControl.Transaction(), mWindowMagnifierCallback, mSysUiState); mHandler, new WindowMagnificationAnimationController(windowContext), new SfVsyncFrameCallbackProvider(), null, new SurfaceControl.Transaction(), mWindowMagnifierCallback, mSysUiState, WindowManagerGlobal::getWindowSession); } } Loading
packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +64 −13 Original line number Diff line number Diff line Loading @@ -57,11 +57,11 @@ import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.WindowMetrics; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.widget.FrameLayout; import androidx.core.math.MathUtils; Loading @@ -75,6 +75,7 @@ import java.io.PrintWriter; import java.text.NumberFormat; import java.util.Collections; import java.util.Locale; import java.util.function.Supplier; /** * Class to handle adding and removing a window magnification. Loading @@ -92,6 +93,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold 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 @@ -163,8 +165,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private SurfaceView mMirrorSurfaceView; private int mMirrorSurfaceMargin; private int mBorderDragSize; private int mDragViewSize; private int mOuterBorderSize; /** * How far from the right edge of the screen you need to drag the window before the button * repositions to the other side. */ private int mButtonRepositionThresholdFromEdge; // The boundary of magnification frame. private final Rect mMagnificationFrameBoundary = new Rect(); // The top Y of the system gesture rect at the bottom. Set to -1 if it is invalid. Loading @@ -172,6 +179,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private int mMinWindowSize; private final WindowMagnificationAnimationController mAnimationController; private final Supplier<IWindowSession> mGlobalWindowSessionSupplier; private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; private final MagnificationGestureDetector mGestureDetector; private final int mBounceEffectDuration; Loading @@ -182,18 +190,25 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private SysUiState mSysUiState; // Set it to true when the view is overlapped with the gesture insets at the bottom. private boolean mOverlapWithGestureInsets; private boolean mIsDragging; @Nullable private MirrorWindowControl mMirrorWindowControl; WindowMagnificationController(@UiContext Context context, @NonNull Handler handler, WindowMagnificationController( @UiContext Context context, @NonNull Handler handler, @NonNull WindowMagnificationAnimationController animationController, SfVsyncFrameCallbackProvider sfVsyncFrameProvider, MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, @NonNull WindowMagnifierCallback callback, SysUiState sysUiState) { MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, @NonNull WindowMagnifierCallback callback, SysUiState sysUiState, @NonNull Supplier<IWindowSession> globalWindowSessionSupplier) { mContext = context; mHandler = handler; mAnimationController = animationController; mGlobalWindowSessionSupplier = globalWindowSessionSupplier; mAnimationController.setWindowMagnificationController(this); mSfVsyncFrameProvider = sfVsyncFrameProvider; mWindowMagnifierCallback = callback; Loading Loading @@ -249,8 +264,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold }; mMirrorSurfaceViewLayoutChangeListener = (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> applyTapExcludeRegion(); (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> mMirrorView.post(this::applyTapExcludeRegion); mMirrorViewGeometryVsyncCallback = l -> { Loading Loading @@ -283,10 +298,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold R.dimen.magnification_mirror_surface_margin); mBorderDragSize = mResources.getDimensionPixelSize( R.dimen.magnification_border_drag_size); mDragViewSize = mResources.getDimensionPixelSize( R.dimen.magnification_drag_view_size); mOuterBorderSize = mResources.getDimensionPixelSize( R.dimen.magnification_outer_border_margin); mButtonRepositionThresholdFromEdge = mResources.getDimensionPixelSize( R.dimen.magnification_button_reposition_threshold_from_edge); mMinWindowSize = mResources.getDimensionPixelSize( com.android.internal.R.dimen.accessibility_window_magnifier_min_size); } Loading Loading @@ -551,10 +567,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } private void applyTapExcludeRegion() { // Sometimes this can get posted and run after deleteWindowMagnification() is called. if (mMirrorView == null) return; final Region tapExcludeRegion = calculateTapExclude(); final IWindow window = IWindow.Stub.asInterface(mMirrorView.getWindowToken()); try { IWindowSession session = WindowManagerGlobal.getWindowSession(); IWindowSession session = mGlobalWindowSessionSupplier.get(); session.updateTapExcludeRegion(window, tapExcludeRegion); } catch (RemoteException e) { } Loading @@ -564,9 +583,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold Region regionInsideDragBorder = new Region(mBorderDragSize, mBorderDragSize, mMirrorView.getWidth() - mBorderDragSize, mMirrorView.getHeight() - mBorderDragSize); Rect dragArea = new Rect(mMirrorView.getWidth() - mDragViewSize - mBorderDragSize, mMirrorView.getHeight() - mDragViewSize - mBorderDragSize, mMirrorView.getWidth(), mMirrorView.getHeight()); Rect dragArea = new Rect(); mDragView.getHitRect(dragArea); regionInsideDragBorder.op(dragArea, Region.Op.DIFFERENCE); return regionInsideDragBorder; } Loading Loading @@ -713,6 +732,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorView.setTranslationX(translationX); mMirrorView.setTranslationY(translationY); mWm.updateViewLayout(mMirrorView, params); // If they are not dragging the handle, we can move the drag handle immediately without // disruption. But if they are dragging it, we avoid moving until the end of the drag. if (!mIsDragging) { mMirrorView.post(this::maybeRepositionButton); } } @Override Loading Loading @@ -1060,14 +1085,40 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold @Override public boolean onStart(float x, float y) { mIsDragging = true; return true; } @Override public boolean onFinish(float x, float y) { maybeRepositionButton(); mIsDragging = false; return false; } /** Moves the button to the opposite edge if the frame is against the edge of the screen. */ private void maybeRepositionButton() { if (mMirrorView == null) return; final float screenEdgeX = mWindowBounds.right - mButtonRepositionThresholdFromEdge; final FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mDragView.getLayoutParams(); mMirrorView.getBoundsOnScreen(mTmpRect); final int newGravity; if (mTmpRect.right >= screenEdgeX) { newGravity = Gravity.BOTTOM | Gravity.LEFT; } else { newGravity = Gravity.BOTTOM | Gravity.RIGHT; } if (newGravity != layoutParams.gravity) { layoutParams.gravity = newGravity; mDragView.setLayoutParams(layoutParams); mDragView.post(this::applyTapExcludeRegion); } } private void animateBounceEffect() { final ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(mMirrorView, PropertyValuesHolder.ofFloat(View.SCALE_X, 1, mBounceEffectAnimationScale, 1), Loading
packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java +11 −2 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.testing.AndroidTestingRunner; import android.view.SurfaceControl; import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.animation.AccelerateInterpolator; Loading Loading @@ -761,8 +762,16 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { SfVsyncFrameCallbackProvider sfVsyncFrameProvider, MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, WindowMagnifierCallback callback, SysUiState sysUiState) { super(context, handler, animationController, sfVsyncFrameProvider, mirrorWindowControl, transaction, callback, sysUiState); super( context, handler, animationController, sfVsyncFrameProvider, mirrorWindowControl, transaction, callback, sysUiState, WindowManagerGlobal::getWindowSession); mSpyController = Mockito.mock(WindowMagnificationController.class); } Loading