diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index 2d28b143796cd..426e400c9fb93 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -30,6 +30,7 @@ import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.SystemUI; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.CommandQueue; @@ -94,7 +95,9 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall //TODO: b/144080869 support multi-display. if (mWindowMagnificationController == null) { mWindowMagnificationController = new WindowMagnificationController(mContext, - mHandler, null, + mHandler, + new SfVsyncFrameCallbackProvider(), + null, this); } mWindowMagnificationController.enableWindowMagnification(scale, centerX, centerY); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 18e7778383918..7e9faff8c2964 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -33,6 +33,7 @@ import android.graphics.Region; import android.os.Handler; import android.os.RemoteException; import android.util.Log; +import android.view.Choreographer; import android.view.Display; import android.view.Gravity; import android.view.IWindow; @@ -47,6 +48,7 @@ import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.R; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -98,15 +100,27 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold // The boundary of magnification frame. 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(); + } + }; + @Nullable private MirrorWindowControl mMirrorWindowControl; WindowMagnificationController(Context context, @NonNull Handler handler, + SfVsyncFrameCallbackProvider sfVsyncFrameProvider, MirrorWindowControl mirrorWindowControl, @NonNull WindowMagnifierCallback callback) { mContext = context; mHandler = handler; + mSfVsyncFrameProvider = sfVsyncFrameProvider; mWindowMagnifierCallback = callback; Display display = mContext.getDisplay(); display.getRealSize(mDisplaySize); @@ -316,7 +330,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold .reparent(mMirrorSurface, mMirrorSurfaceView.getSurfaceControl()); modifyWindowMagnification(mTransaction); - mTransaction.apply(); } private void addDragTouchListeners() { @@ -337,14 +350,13 @@ 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) { - Rect sourceBounds = getSourceBounds(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()); updateMirrorViewLayout(); - t.setGeometry(mMirrorSurface, sourceBounds, mTmpRect, Surface.ROTATION_0); + mSfVsyncFrameProvider.postFrameCallback(mMirrorViewGeometryVsyncCallback); } /** @@ -505,7 +517,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold showControls(); } else { modifyWindowMagnification(mTransaction); - mTransaction.apply(); } } @@ -535,7 +546,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } if (updateMagnificationFramePosition((int) offsetX, (int) offsetY)) { modifyWindowMagnification(mTransaction); - mTransaction.apply(); } } } 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 bfb95b0db3e38..a898c3ce27730 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -16,8 +16,8 @@ package com.android.systemui.accessibility; - import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.verify; import android.app.Instrumentation; @@ -27,6 +27,7 @@ import android.testing.AndroidTestingRunner; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.SysuiTestCase; import org.junit.After; @@ -43,6 +44,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Mock Handler mHandler; @Mock + SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; + @Mock MirrorWindowControl mMirrorWindowControl; @Mock WindowMagnifierCallback mWindowMagnifierCallback; @@ -54,7 +57,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mInstrumentation = InstrumentationRegistry.getInstrumentation(); mWindowMagnificationController = new WindowMagnificationController(getContext(), - mHandler, + mHandler, mSfVsyncFrameProvider, mMirrorWindowControl, mWindowMagnifierCallback); verify(mMirrorWindowControl).setWindowDelegate( any(MirrorWindowControl.MirrorWindowDelegate.class)); @@ -65,7 +68,6 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.deleteWindowMagnification(); }); - mInstrumentation.waitForIdleSync(); } @Test @@ -74,7 +76,6 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); }); - mInstrumentation.waitForIdleSync(); verify(mMirrorWindowControl).showControl(); } @@ -84,13 +85,22 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); }); - mInstrumentation.waitForIdleSync(); mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.deleteWindowMagnification(); }); - mInstrumentation.waitForIdleSync(); verify(mMirrorWindowControl).destroyControl(); } + + @Test + public void moveMagnifier_schedulesFrame() { + mInstrumentation.runOnMainSync(() -> { + mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, + Float.NaN); + mWindowMagnificationController.moveWindowMagnifier(100f, 100f); + }); + + verify(mSfVsyncFrameProvider, atLeastOnce()).postFrameCallback(any()); + } }