diff options
6 files changed, 97 insertions, 25 deletions
diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl index 2d05591a8131..2343bf3e8d19 100644 --- a/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl +++ b/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl @@ -19,7 +19,7 @@ package android.view.accessibility; import android.graphics.Rect; /** - * interface to notify the change of the window magnifier bounds and request to change + * interface to notify the changes of the window magnification and request to change * the magnification mode. * * @hide @@ -27,12 +27,13 @@ import android.graphics.Rect; oneway interface IWindowMagnificationConnectionCallback { /** - * Called when the bounds of the window magnifier is changed. + * Called when the bounds of the mirrow window is changed. * * @param displayId The logical display id. * @param bounds The window magnifier bounds in screen coordinates. */ void onWindowMagnifierBoundsChanged(int displayId, in Rect bounds); + /** * Changes the magnification mode on specified display. It is invoked by System UI when the * switch button is toggled. @@ -41,4 +42,12 @@ import android.graphics.Rect; * @param magnificationMode new magnification mode. */ void onChangeMagnificationMode(int displayId, int magnificationMode); + + /** + * Called when the magnified bounds is changed. + * + * @param displayId The logical display id. + * @param sourceBounds The magnified bounds in screen coordinates. + */ + void onSourceBoundsChanged(int displayId, in Rect sourceBounds); } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index 426e400c9fb9..78af8aa19b44 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -25,6 +25,7 @@ import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; import android.util.Log; +import android.view.SurfaceControl; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; @@ -97,7 +98,7 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall mWindowMagnificationController = new WindowMagnificationController(mContext, mHandler, new SfVsyncFrameCallbackProvider(), - null, + null, new SurfaceControl.Transaction(), this); } mWindowMagnificationController.enableWindowMagnification(scale, centerX, centerY); @@ -136,6 +137,13 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall } @Override + public void onSourceBoundsChanged(int displayId, Rect sourceBounds) { + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onSourceBoundsChanged(displayId, sourceBounds); + } + } + + @Override public void requestWindowMagnificationConnection(boolean connect) { if (connect) { setWindowMagnificationConnection(); @@ -225,5 +233,15 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall } } } + + void onSourceBoundsChanged(int displayId, Rect sourceBounds) { + if (mConnectionCallback != null) { + try { + mConnectionCallback.onSourceBoundsChanged(displayId, sourceBounds); + } catch (RemoteException e) { + Log.e(TAG, "Failed to inform source bounds changed", e); + } + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 8b6581ff1856..798b751c03ee 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -67,7 +67,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold @Surface.Rotation private int mRotation; private final Rect mMagnificationFrame = new Rect(); - private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); + private final SurfaceControl.Transaction mTransaction; private final WindowManager mWm; @@ -75,6 +75,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private final Rect mTmpRect = new Rect(); private final Rect mMirrorViewBounds = new Rect(); + private final Rect mSourceBounds = new Rect(); // The root of the mirrored content private SurfaceControl mMirrorSurface; @@ -101,22 +102,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private final Rect mMagnificationFrameBoundary = new Rect(); private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; - private final Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback = - l -> { - if (mMirrorView != null) { - final Rect sourceBounds = getSourceBounds(mMagnificationFrame, mScale); - mTransaction.setGeometry(mMirrorSurface, sourceBounds, mTmpRect, - Surface.ROTATION_0).apply(); - } - }; + private Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback; @Nullable private MirrorWindowControl mMirrorWindowControl; - WindowMagnificationController(Context context, - @NonNull Handler handler, + WindowMagnificationController(Context context, @NonNull Handler handler, SfVsyncFrameCallbackProvider sfVsyncFrameProvider, - MirrorWindowControl mirrorWindowControl, + MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, @NonNull WindowMagnifierCallback callback) { mContext = context; mHandler = handler; @@ -137,6 +130,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold if (mMirrorWindowControl != null) { mMirrorWindowControl.setWindowDelegate(this); } + mTransaction = transaction; setInitialStartBounds(); // Initialize listeners. @@ -153,6 +147,20 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorSurfaceViewLayoutChangeListener = (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> applyTapExcludeRegion(); + + mMirrorViewGeometryVsyncCallback = + l -> { + if (mMirrorView != null && mMirrorSurface != null) { + calculateSourceBounds(mMagnificationFrame, mScale); + // The final destination for the magnification surface should be at 0,0 + // since the ViewRootImpl's position will change + mTmpRect.set(0, 0, mMagnificationFrame.width(), + mMagnificationFrame.height()); + mTransaction.setGeometry(mMirrorSurface, mSourceBounds, mTmpRect, + Surface.ROTATION_0).apply(); + mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, mSourceBounds); + } + }; } private void updateDimensions() { @@ -350,13 +358,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * Modifies the placement of the mirrored content when the position of mMirrorView is updated. */ private void modifyWindowMagnification(SurfaceControl.Transaction t) { - // The final destination for the magnification surface should be at 0,0 since the - // ViewRootImpl's position will change - mTmpRect.set(0, 0, mMagnificationFrame.width(), mMagnificationFrame.height()); - + mSfVsyncFrameProvider.postFrameCallback(mMirrorViewGeometryVsyncCallback); updateMirrorViewLayout(); - mSfVsyncFrameProvider.postFrameCallback(mMirrorViewGeometryVsyncCallback); } /** @@ -420,14 +424,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * Calculates the desired source bounds. This will be the area under from the center of the * displayFrame, factoring in scale. */ - private Rect getSourceBounds(Rect displayFrame, float scale) { + private void calculateSourceBounds(Rect displayFrame, float scale) { int halfWidth = displayFrame.width() / 2; int halfHeight = displayFrame.height() / 2; int left = displayFrame.left + (halfWidth - (int) (halfWidth / scale)); int right = displayFrame.right - (halfWidth - (int) (halfWidth / scale)); int top = displayFrame.top + (halfHeight - (int) (halfHeight / scale)); int bottom = displayFrame.bottom - (halfHeight - (int) (halfHeight / scale)); - return new Rect(left, top, right, bottom); + mSourceBounds.set(left, top, right, bottom); } private void setMagnificationFrameBoundary() { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java index 2adb3ebb7bce..e405a89766e2 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java @@ -29,4 +29,12 @@ interface WindowMagnifierCallback { * @param bounds The bounds of window magnifier on the screen. */ void onWindowMagnifierBoundsChanged(int displayId, Rect bounds); + + /** + * Called when the magnified bounds is changed. + * + * @param displayId The logical display id. + * @param sourceBounds The magnified bounds in screen coordinates. + */ + void onSourceBoundsChanged(int displayId, Rect sourceBounds); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index a898c3ce2773..2007fbb8fc6c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -16,13 +16,19 @@ package com.android.systemui.accessibility; +import static android.view.Choreographer.FrameCallback; + import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.Instrumentation; import android.os.Handler; import android.testing.AndroidTestingRunner; +import android.view.SurfaceControl; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -49,6 +55,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { MirrorWindowControl mMirrorWindowControl; @Mock WindowMagnifierCallback mWindowMagnifierCallback; + @Mock + SurfaceControl.Transaction mTransaction; private WindowMagnificationController mWindowMagnificationController; private Instrumentation mInstrumentation; @@ -56,9 +64,19 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { public void setUp() { MockitoAnnotations.initMocks(this); mInstrumentation = InstrumentationRegistry.getInstrumentation(); + doAnswer(invocation -> { + FrameCallback callback = invocation.getArgument(0); + callback.doFrame(0); + return null; + }).when(mSfVsyncFrameProvider).postFrameCallback( + any(FrameCallback.class)); + when(mTransaction.remove(any())).thenReturn(mTransaction); + when(mTransaction.setGeometry(any(), any(), any(), + anyInt())).thenReturn(mTransaction); + mWindowMagnificationController = new WindowMagnificationController(getContext(), mHandler, mSfVsyncFrameProvider, - mMirrorWindowControl, mWindowMagnifierCallback); + mMirrorWindowControl, mTransaction, mWindowMagnifierCallback); verify(mMirrorWindowControl).setWindowDelegate( any(MirrorWindowControl.MirrorWindowDelegate.class)); } @@ -71,7 +89,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { } @Test - public void createWindowMagnification_showControl() { + public void enableWindowMagnification_showControl() { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java index a08c2dd4292d..ed2b26f24478 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java @@ -384,7 +384,7 @@ public class WindowMagnificationManager implements synchronized (mLock) { WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); if (magnifier == null) { - return; + magnifier = createWindowMagnifier(displayId); } if (DBG) { Slog.i(TAG, @@ -401,6 +401,15 @@ public class WindowMagnificationManager implements } @Override + public void onSourceBoundsChanged(int displayId, Rect sourceBounds) { + WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); + if (magnifier == null) { + magnifier = createWindowMagnifier(displayId); + } + magnifier.onSourceBoundsChanged(sourceBounds); + } + + @Override public void binderDied() { synchronized (mLock) { Slog.w(TAG, "binderDied DeathRecipient :" + mExpiredDeathRecipient); @@ -427,6 +436,8 @@ public class WindowMagnificationManager implements private final WindowMagnificationManager mWindowMagnificationManager; //Records the bounds of window magnifier. private final Rect mBounds = new Rect(); + //The magnified bounds on the screen. + private final Rect mSourceBounds = new Rect(); WindowMagnifier(int displayId, WindowMagnificationManager windowMagnificationManager) { mDisplayId = displayId; mWindowMagnificationManager = windowMagnificationManager; @@ -502,6 +513,10 @@ public class WindowMagnificationManager implements void reset() { mEnabled = false; } + + public void onSourceBoundsChanged(Rect sourceBounds) { + mSourceBounds.set(sourceBounds); + } } private boolean enableWindowMagnification(int displayId, float scale, float centerX, |