Makes dragging window magnification smoother on low-medium device
It takes some time to update the geometry of the mirror window of window magnification. If the peformance of the device is not so good, the dragging of window magnification would looks sluggish. To improve this, we use Choreographer to update the mirror view geometry. It make the refresh rate sync with display frame rendering. Bug: 158264842 Test: atest WindowMagnificationControllerTest Change-Id: Ia2eaca85ccec90b735dab9114c58a94108cdbed1
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user