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:
mincheli
2020-06-10 10:32:39 +08:00
parent 3c89ea1688
commit 8a0ffff1bf
3 changed files with 35 additions and 12 deletions

View File

@@ -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);

View File

@@ -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();
}
}
}

View File

@@ -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());
}
}