Adds moveWindowMagnifierToPosition method

For following typing focus feature, we add a
moveWindowMagnifierToPosition method for a window magnifier to move it
to the center of onRectangleOnScreenRequested.

Apart from calling this method to fulfill movement functionality, we can
separate the movement from calling enableWindowMagnification which is a
temporary replacement for movement functionality. Therefore, we can
distinguish whether the it is enabled by the first time or the further
movement behavior. It would help us differentiate the condition whether
we should reset the following typing focus to on/off state. (b/216394179)

Bug: 219654280
Test: atest IWindowMagnificationConnectionTest
      atest WindowMagnificationTest
      atest WindowMagnificationAnimationControllerTest
      atest WindowMagnificationControllerTest
      atest WindowMagnificationConnectionWrapperTest
      atest WindowMagnificationManagerTest
Change-Id: Iaac3ca6868d948571c1aee54a5f122c9697059d8
This commit is contained in:
Daniel Hsieh
2022-02-15 15:14:02 +00:00
parent 0153cbf9c4
commit 0dae9e4f47
13 changed files with 425 additions and 35 deletions

View File

@@ -32,7 +32,7 @@ oneway interface IWindowMagnificationConnection {
/**
* Enables window magnification on specified display with given center and scale and animation.
*
* @param displayId The logical display id.
* @param displayId the logical display id.
* @param scale magnification scale.
* @param centerX the screen-relative X coordinate around which to center,
* or {@link Float#NaN} to leave unchanged.
@@ -51,7 +51,7 @@ oneway interface IWindowMagnificationConnection {
/**
* Sets the scale of the window magnifier on specified display.
*
* @param displayId The logical display id.
* @param displayId the logical display id.
* @param scale magnification scale.
*/
void setScale(int displayId, float scale);
@@ -59,7 +59,7 @@ oneway interface IWindowMagnificationConnection {
/**
* Disables window magnification on specified display with animation.
*
* @param displayId The logical display id.
* @param displayId the logical display id.
* @param callback The callback called when the animation is completed or interrupted.
*/
void disableWindowMagnification(int displayId,
@@ -68,6 +68,7 @@ oneway interface IWindowMagnificationConnection {
/**
* Moves the window magnifier on the specified display. It has no effect while animating.
*
* @param displayId the logical display id.
* @param offsetX the amount in pixels to offset the window magnifier in the X direction, in
* current screen pixels.
* @param offsetY the amount in pixels to offset the window magnifier in the Y direction, in
@@ -75,10 +76,21 @@ oneway interface IWindowMagnificationConnection {
*/
void moveWindowMagnifier(int displayId, float offsetX, float offsetY);
/**
* Moves the window magnifier on the given display.
*
* @param displayId the logical display id.
* @param positionX the x-axis position of the center of the magnified source bounds.
* @param positionY the y-axis position of the center of the magnified source bounds.
* @param callback the callback called when the animation is completed or interrupted.
*/
void moveWindowMagnifierToPosition(int displayId, float positionX, float positionY,
in IRemoteMagnificationAnimationCallback callback);
/**
* Requests System UI show magnification mode button UI on the specified display.
*
* @param displayId The logical display id.
* @param displayId the logical display id.
* @param magnificationMode the current magnification mode.
*/
void showMagnificationButton(int displayId, int magnificationMode);
@@ -86,7 +98,7 @@ oneway interface IWindowMagnificationConnection {
/**
* Requests System UI remove magnification mode button UI on the specified display.
*
* @param displayId The logical display id.
* @param displayId the logical display id.
*/
void removeMagnificationButton(int displayId);

View File

@@ -171,6 +171,17 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie
}
}
@MainThread
void moveWindowMagnifierToPositionInternal(int displayId, float positionX, float positionY,
IRemoteMagnificationAnimationCallback callback) {
final WindowMagnificationController windowMagnificationController =
mMagnificationControllerSupplier.get(displayId);
if (windowMagnificationController != null) {
windowMagnificationController.moveWindowMagnifierToPosition(positionX, positionY,
callback);
}
}
@MainThread
void disableWindowMagnification(int displayId,
@Nullable IRemoteMagnificationAnimationCallback callback) {

View File

@@ -156,6 +156,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
}
mAnimationCallback = animationCallback;
setupEnableAnimationSpecs(scale, centerX, centerY);
if (mEndSpec.equals(mStartSpec)) {
if (mState == STATE_DISABLED) {
mController.enableWindowMagnificationInternal(scale, centerX, centerY,
@@ -178,6 +179,24 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
}
}
void moveWindowMagnifierToPosition(float centerX, float centerY,
IRemoteMagnificationAnimationCallback callback) {
if (mState == STATE_ENABLED) {
// We set the animation duration to shortAnimTime which would be reset at the end.
mValueAnimator.setDuration(mContext.getResources()
.getInteger(com.android.internal.R.integer.config_shortAnimTime));
enableWindowMagnification(Float.NaN, centerX, centerY,
/* magnificationFrameOffsetRatioX */ Float.NaN,
/* magnificationFrameOffsetRatioY */ Float.NaN, callback);
} else if (mState == STATE_ENABLING) {
sendAnimationCallback(false);
mAnimationCallback = callback;
mValueAnimator.setDuration(mContext.getResources()
.getInteger(com.android.internal.R.integer.config_shortAnimTime));
setupEnableAnimationSpecs(Float.NaN, centerX, centerY);
}
}
private void setupEnableAnimationSpecs(float scale, float centerX, float centerY) {
if (mController == null) {
return;
@@ -193,9 +212,16 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
R.integer.magnification_default_scale) : scale, centerX, centerY);
} else {
mStartSpec.set(currentScale, currentCenterX, currentCenterY);
mEndSpec.set(Float.isNaN(scale) ? currentScale : scale,
Float.isNaN(centerX) ? currentCenterX : centerX,
Float.isNaN(centerY) ? currentCenterY : centerY);
final float endScale = (mState == STATE_ENABLING ? mEndSpec.mScale : currentScale);
final float endCenterX =
(mState == STATE_ENABLING ? mEndSpec.mCenterX : currentCenterX);
final float endCenterY =
(mState == STATE_ENABLING ? mEndSpec.mCenterY : currentCenterY);
mEndSpec.set(Float.isNaN(scale) ? endScale : scale,
Float.isNaN(centerX) ? endCenterX : centerX,
Float.isNaN(centerY) ? endCenterY : centerY);
}
if (DEBUG) {
Log.d(TAG, "SetupEnableAnimationSpecs : mStartSpec = " + mStartSpec + ", endSpec = "
@@ -269,6 +295,9 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
setState(STATE_ENABLED);
}
sendAnimationCallback(true);
// We reset the duration to config_longAnimTime
mValueAnimator.setDuration(mContext.getResources()
.getInteger(com.android.internal.R.integer.config_longAnimTime));
}
@Override
@@ -313,10 +342,10 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
}
private static ValueAnimator newValueAnimator(Resources resources) {
private static ValueAnimator newValueAnimator(Resources resource) {
final ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(
resources.getInteger(com.android.internal.R.integer.config_longAnimTime));
resource.getInteger(com.android.internal.R.integer.config_longAnimTime));
valueAnimator.setInterpolator(new AccelerateInterpolator(2.5f));
valueAnimator.setFloatValues(0.0f, 1.0f);
return valueAnimator;

View File

@@ -76,6 +76,13 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S
() -> mWindowMagnification.moveWindowMagnifier(displayId, offsetX, offsetY));
}
@Override
public void moveWindowMagnifierToPosition(int displayId, float positionX, float positionY,
IRemoteMagnificationAnimationCallback callback) {
mHandler.post(() -> mWindowMagnification.moveWindowMagnifierToPositionInternal(
displayId, positionX, positionY, callback));
}
@Override
public void showMagnificationButton(int displayId, int magnificationMode) {
mHandler.post(

View File

@@ -985,6 +985,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
}
}
void moveWindowMagnifierToPosition(float positionX, float positionY,
IRemoteMagnificationAnimationCallback callback) {
if (mMirrorSurfaceView == null) {
return;
}
mAnimationController.moveWindowMagnifierToPosition(positionX, positionY, callback);
}
/**
* Gets the scale.
*

View File

@@ -133,6 +133,16 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase {
verify(mWindowMagnificationController).moveWindowMagnifier(100f, 200f);
}
@Test
public void moveWindowMagnifierToPosition() throws RemoteException {
mIWindowMagnificationConnection.moveWindowMagnifierToPosition(TEST_DISPLAY,
100f, 200f, mAnimationCallback);
waitForIdleSync();
verify(mWindowMagnificationController).moveWindowMagnifierToPosition(
eq(100f), eq(200f), any(IRemoteMagnificationAnimationCallback.class));
}
@Test
public void showMagnificationButton() throws RemoteException {
mIWindowMagnificationConnection.showMagnificationButton(TEST_DISPLAY,

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.accessibility;
import android.os.RemoteException;
import android.view.accessibility.IRemoteMagnificationAnimationCallback;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class MockMagnificationAnimationCallback extends IRemoteMagnificationAnimationCallback.Stub {
private final CountDownLatch mCountDownLatch;
private final AtomicInteger mSuccessCount;
private final AtomicInteger mFailedCount;
MockMagnificationAnimationCallback(CountDownLatch countDownLatch) {
mCountDownLatch = countDownLatch;
mSuccessCount = new AtomicInteger();
mFailedCount = new AtomicInteger();
}
public int getSuccessCount() {
return mSuccessCount.get();
}
public int getFailedCount() {
return mFailedCount.get();
}
@Override
public void onResult(boolean success) throws RemoteException {
mCountDownLatch.countDown();
if (success) {
mSuccessCount.getAndIncrement();
} else {
mFailedCount.getAndIncrement();
}
}
}

View File

@@ -60,6 +60,8 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@Ignore
@@ -217,6 +219,29 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
verify(mAnimationCallback2).onResult(true);
}
@Test
public void enableWindowMagnificationWithUnchanged_enabling_expectedValuesToDefault()
throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(2);
final MockMagnificationAnimationCallback animationCallback =
new MockMagnificationAnimationCallback(countDownLatch);
enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
animationCallback);
mInstrumentation.runOnMainSync(
() -> {
mWindowMagnificationAnimationController.enableWindowMagnification(Float.NaN,
Float.NaN, Float.NaN, animationCallback);
});
assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
// The callback in 2nd enableWindowMagnification will return true
assertEquals(1, animationCallback.getSuccessCount());
// The callback in 1st enableWindowMagnification will return false
assertEquals(1, animationCallback.getFailedCount());
verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
}
@Test
public void enableWindowMagnificationWithScaleOne_enabled_AnimationAndInvokeCallback()
throws RemoteException {
@@ -424,6 +449,102 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
Math.round(offsetRatio * mirrorViewBound.height() / 2), 0.1f);
}
@Test
public void moveWindowMagnifierToPosition_enabled_expectedValues()
throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(1);
final MockMagnificationAnimationCallback animationCallback =
new MockMagnificationAnimationCallback(countDownLatch);
final float targetCenterX = DEFAULT_CENTER_X + 100;
final float targetCenterY = DEFAULT_CENTER_Y + 100;
enableWindowMagnificationWithoutAnimation();
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
targetCenterX, targetCenterY, animationCallback);
});
assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
assertEquals(1, animationCallback.getSuccessCount());
assertEquals(0, animationCallback.getFailedCount());
verifyFinalSpec(DEFAULT_SCALE, targetCenterX, targetCenterY);
}
@Test
public void moveWindowMagnifierToPositionMultipleTimes_enabled_expectedValuesToLastOne()
throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(4);
final MockMagnificationAnimationCallback animationCallback =
new MockMagnificationAnimationCallback(countDownLatch);
enableWindowMagnificationWithoutAnimation();
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
DEFAULT_CENTER_X + 10, DEFAULT_CENTER_Y + 10, animationCallback);
mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
DEFAULT_CENTER_X + 20, DEFAULT_CENTER_Y + 20, animationCallback);
mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
DEFAULT_CENTER_X + 30, DEFAULT_CENTER_Y + 30, animationCallback);
mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
DEFAULT_CENTER_X + 40, DEFAULT_CENTER_Y + 40, animationCallback);
});
assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
// only the last one callback will return true
assertEquals(1, animationCallback.getSuccessCount());
// the others will return false
assertEquals(3, animationCallback.getFailedCount());
verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + 40, DEFAULT_CENTER_Y + 40);
}
@Test
public void moveWindowMagnifierToPosition_enabling_expectedValuesToLastOne()
throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(2);
final MockMagnificationAnimationCallback animationCallback =
new MockMagnificationAnimationCallback(countDownLatch);
final float targetCenterX = DEFAULT_CENTER_X + 100;
final float targetCenterY = DEFAULT_CENTER_Y + 100;
enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
animationCallback);
mInstrumentation.runOnMainSync(
() -> {
mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
targetCenterX, targetCenterY, animationCallback);
});
assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
// The callback in moveWindowMagnifierToPosition will return true
assertEquals(1, animationCallback.getSuccessCount());
// The callback in enableWindowMagnification will return false
assertEquals(1, animationCallback.getFailedCount());
verifyFinalSpec(DEFAULT_SCALE, targetCenterX, targetCenterY);
}
@Test
public void moveWindowMagnifierToPositionWithCenterUnchanged_enabling_expectedValuesToDefault()
throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(2);
final MockMagnificationAnimationCallback animationCallback =
new MockMagnificationAnimationCallback(countDownLatch);
enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod,
animationCallback);
mInstrumentation.runOnMainSync(
() -> {
mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
Float.NaN, Float.NaN, animationCallback);
});
assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
// The callback in moveWindowMagnifierToPosition will return true
assertEquals(1, animationCallback.getSuccessCount());
// The callback in enableWindowMagnification will return false
assertEquals(1, animationCallback.getFailedCount());
verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
}
@Test
public void enableWindowMagnificationWithSameScale_enabled_doNothingButInvokeCallback()
throws RemoteException {
@@ -569,6 +690,20 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + 100f, DEFAULT_CENTER_Y + 100f);
}
@Test
public void moveWindowMagnifierToPosition_enabled() {
final float targetCenterX = DEFAULT_CENTER_X + 100;
final float targetCenterY = DEFAULT_CENTER_Y + 100;
enableWindowMagnificationWithoutAnimation();
mInstrumentation.runOnMainSync(
() -> mController.moveWindowMagnifierToPosition(targetCenterX, targetCenterY,
mAnimationCallback));
SystemClock.sleep(mWaitingAnimationPeriod);
verifyFinalSpec(DEFAULT_SCALE, targetCenterX, targetCenterY);
}
private void verifyFinalSpec(float expectedScale, float expectedCenterX,
float expectedCenterY) {
assertEquals(expectedScale, mController.getScale(), 0f);
@@ -662,6 +797,13 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
mSpyController.moveWindowMagnifier(offsetX, offsetY);
}
@Override
void moveWindowMagnifierToPosition(float positionX, float positionY,
IRemoteMagnificationAnimationCallback callback) {
super.moveWindowMagnifierToPosition(positionX, positionY, callback);
mSpyController.moveWindowMagnifierToPosition(positionX, positionY, callback);
}
@Override
void setScale(float scale) {
super.setScale(scale);

View File

@@ -88,6 +88,8 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@LargeTest
@@ -96,12 +98,16 @@ import java.util.concurrent.atomic.AtomicInteger;
public class WindowMagnificationControllerTest extends SysuiTestCase {
private static final int LAYOUT_CHANGE_TIMEOUT_MS = 5000;
private static final long ANIMATION_DURATION_MS = 300;
private final long mWaitingAnimationPeriod = 2 * ANIMATION_DURATION_MS;
@Mock
private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
@Mock
private MirrorWindowControl mMirrorWindowControl;
@Mock
private WindowMagnifierCallback mWindowMagnifierCallback;
@Mock
IRemoteMagnificationAnimationCallback mAnimationCallback;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
@@ -286,6 +292,82 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
verify(mSfVsyncFrameProvider, atLeastOnce()).postFrameCallback(any());
}
@Test
public void moveWindowMagnifierToPositionWithAnimation_expectedValuesAndInvokeCallback()
throws InterruptedException {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
Float.NaN, 0, 0, null);
});
final CountDownLatch countDownLatch = new CountDownLatch(1);
final MockMagnificationAnimationCallback animationCallback =
new MockMagnificationAnimationCallback(countDownLatch);
final ArgumentCaptor<Rect> sourceBoundsCaptor = ArgumentCaptor.forClass(Rect.class);
verify(mWindowMagnifierCallback, timeout(LAYOUT_CHANGE_TIMEOUT_MS))
.onSourceBoundsChanged((eq(mContext.getDisplayId())), sourceBoundsCaptor.capture());
final float targetCenterX = sourceBoundsCaptor.getValue().exactCenterX() + 10;
final float targetCenterY = sourceBoundsCaptor.getValue().exactCenterY() + 10;
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.moveWindowMagnifierToPosition(
targetCenterX, targetCenterY, animationCallback);
});
assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
assertEquals(1, animationCallback.getSuccessCount());
assertEquals(0, animationCallback.getFailedCount());
verify(mWindowMagnifierCallback, timeout(LAYOUT_CHANGE_TIMEOUT_MS))
.onSourceBoundsChanged((eq(mContext.getDisplayId())), sourceBoundsCaptor.capture());
assertEquals(mWindowMagnificationController.getCenterX(),
sourceBoundsCaptor.getValue().exactCenterX(), 0);
assertEquals(mWindowMagnificationController.getCenterY(),
sourceBoundsCaptor.getValue().exactCenterY(), 0);
assertEquals(mWindowMagnificationController.getCenterX(), targetCenterX, 0);
assertEquals(mWindowMagnificationController.getCenterY(), targetCenterY, 0);
}
@Test
public void moveWindowMagnifierToPositionMultipleTimes_expectedValuesAndInvokeCallback()
throws InterruptedException {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
Float.NaN, 0, 0, null);
});
final CountDownLatch countDownLatch = new CountDownLatch(4);
final MockMagnificationAnimationCallback animationCallback =
new MockMagnificationAnimationCallback(countDownLatch);
final ArgumentCaptor<Rect> sourceBoundsCaptor = ArgumentCaptor.forClass(Rect.class);
verify(mWindowMagnifierCallback, timeout(LAYOUT_CHANGE_TIMEOUT_MS))
.onSourceBoundsChanged((eq(mContext.getDisplayId())), sourceBoundsCaptor.capture());
final float centerX = sourceBoundsCaptor.getValue().exactCenterX();
final float centerY = sourceBoundsCaptor.getValue().exactCenterY();
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.moveWindowMagnifierToPosition(
centerX + 10, centerY + 10, animationCallback);
mWindowMagnificationController.moveWindowMagnifierToPosition(
centerX + 20, centerY + 20, animationCallback);
mWindowMagnificationController.moveWindowMagnifierToPosition(
centerX + 30, centerY + 30, animationCallback);
mWindowMagnificationController.moveWindowMagnifierToPosition(
centerX + 40, centerY + 40, animationCallback);
});
assertTrue(countDownLatch.await(mWaitingAnimationPeriod, TimeUnit.MILLISECONDS));
// only the last one callback will return true
assertEquals(1, animationCallback.getSuccessCount());
// the others will return false
assertEquals(3, animationCallback.getFailedCount());
verify(mWindowMagnifierCallback, timeout(LAYOUT_CHANGE_TIMEOUT_MS))
.onSourceBoundsChanged((eq(mContext.getDisplayId())), sourceBoundsCaptor.capture());
assertEquals(mWindowMagnificationController.getCenterX(),
sourceBoundsCaptor.getValue().exactCenterX(), 0);
assertEquals(mWindowMagnificationController.getCenterY(),
sourceBoundsCaptor.getValue().exactCenterY(), 0);
assertEquals(mWindowMagnificationController.getCenterX(), centerX + 40, 0);
assertEquals(mWindowMagnificationController.getCenterY(), centerY + 40, 0);
}
@Test
public void setScale_enabled_expectedValueAndUpdateStateDescription() {
mInstrumentation.runOnMainSync(

View File

@@ -133,6 +133,25 @@ class WindowMagnificationConnectionWrapper {
return true;
}
boolean moveWindowMagnifierToPosition(int displayId, float positionX, float positionY,
@Nullable MagnificationAnimationCallback callback) {
if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
mTrace.logTrace(TAG + ".moveWindowMagnifierToPosition",
FLAGS_WINDOW_MAGNIFICATION_CONNECTION, "displayId=" + displayId
+ ";positionX=" + positionX + ";positionY=" + positionY);
}
try {
mConnection.moveWindowMagnifierToPosition(displayId, positionX, positionY,
transformToRemoteCallback(callback, mTrace));
} catch (RemoteException e) {
if (DBG) {
Slog.e(TAG, "Error calling moveWindowMagnifierToPosition()", e);
}
return false;
}
return true;
}
boolean showMagnificationButton(int displayId, int magnificationMode) {
if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
mTrace.logTrace(TAG + ".showMagnificationButton",

View File

@@ -314,9 +314,12 @@ public class WindowMagnificationManager implements
float toCenterX = (float) (left + right) / 2;
float toCenterY = (float) (top + bottom) / 2;
if (!isPositionInSourceBounds(displayId, toCenterX, toCenterY)
&& isTrackingTypingFocusEnabled(displayId)) {
enableWindowMagnification(displayId, Float.NaN, toCenterX, toCenterY);
synchronized (mLock) {
if (!isPositionInSourceBounds(displayId, toCenterX, toCenterY)
&& isTrackingTypingFocusEnabled(displayId)) {
moveWindowMagnifierToPositionInternal(displayId, toCenterX, toCenterY,
STUB_ANIMATION_CALLBACK);
}
}
}
@@ -563,14 +566,13 @@ public class WindowMagnificationManager implements
}
}
@GuardedBy("mLock")
boolean isPositionInSourceBounds(int displayId, float x, float y) {
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
return false;
}
return magnifier.isPositionInSourceBounds(x, y);
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
return false;
}
return magnifier.isPositionInSourceBounds(x, y);
}
/**
@@ -962,7 +964,6 @@ public class WindowMagnificationManager implements
return mIdOfLastServiceToControl;
}
@GuardedBy("mLock")
int pointersInWindow(MotionEvent motionEvent) {
int count = 0;
final int pointerCount = motionEvent.getPointerCount();
@@ -1050,8 +1051,16 @@ public class WindowMagnificationManager implements
displayId, animationCallback);
}
@GuardedBy("mLock")
private boolean moveWindowMagnifierInternal(int displayId, float offsetX, float offsetY) {
return mConnectionWrapper != null && mConnectionWrapper.moveWindowMagnifier(
displayId, offsetX, offsetY);
}
@GuardedBy("mLock")
private boolean moveWindowMagnifierToPositionInternal(int displayId, float positionX,
float positionY, MagnificationAnimationCallback animationCallback) {
return mConnectionWrapper != null && mConnectionWrapper.moveWindowMagnifierToPosition(
displayId, positionX, positionY, animationCallback);
}
}

View File

@@ -93,6 +93,14 @@ public class WindowMagnificationConnectionWrapperTest {
verify(mConnection).moveWindowMagnifier(TEST_DISPLAY, 100, 150);
}
@Test
public void moveWindowMagnifierToPosition() throws RemoteException {
mConnectionWrapper.moveWindowMagnifierToPosition(TEST_DISPLAY, 100, 150,
mAnimationCallback);
verify(mConnection).moveWindowMagnifierToPosition(eq(TEST_DISPLAY),
eq(100f), eq(150f), any(IRemoteMagnificationAnimationCallback.class));
}
@Test
public void showMagnificationButton() throws RemoteException {
mConnectionWrapper.showMagnificationButton(TEST_DISPLAY,

View File

@@ -21,6 +21,8 @@ import static com.android.server.accessibility.magnification.MockWindowMagnifica
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.doAnswer;
@@ -288,9 +290,8 @@ public class WindowMagnificationManagerTest {
mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY,
requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom);
verify(mMockConnection.getConnection(), never()).enableWindowMagnification(eq(TEST_DISPLAY),
eq(3f), eq(requestedRect.exactCenterX()), eq(requestedRect.exactCenterY()),
eq(0f), eq(0f), notNull());
verify(mMockConnection.getConnection(), never())
.moveWindowMagnifierToPosition(anyInt(), anyFloat(), anyFloat(), any());
}
@@ -310,9 +311,8 @@ public class WindowMagnificationManagerTest {
mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY,
requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom);
verify(mMockConnection.getConnection(), never()).enableWindowMagnification(eq(TEST_DISPLAY),
eq(3f), eq(requestedRect.exactCenterX()), eq(requestedRect.exactCenterY()),
eq(0f), eq(0f), notNull());
verify(mMockConnection.getConnection(), never())
.moveWindowMagnifierToPosition(anyInt(), anyFloat(), anyFloat(), any());
}
@Test
@@ -328,8 +328,8 @@ public class WindowMagnificationManagerTest {
mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY,
requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom);
verify(mMockConnection.getConnection(), never()).enableWindowMagnification(eq(TEST_DISPLAY),
eq(3f), eq(500f), eq(500f), eq(0f), eq(0f), notNull());
verify(mMockConnection.getConnection(), never())
.moveWindowMagnifierToPosition(anyInt(), anyFloat(), anyFloat(), any());
}
@Test
@@ -345,9 +345,9 @@ public class WindowMagnificationManagerTest {
mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY,
requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom);
verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(3f),
verify(mMockConnection.getConnection()).moveWindowMagnifierToPosition(eq(TEST_DISPLAY),
eq(requestedRect.exactCenterX()), eq(requestedRect.exactCenterY()),
eq(0f), eq(0f), notNull());
any(IRemoteMagnificationAnimationCallback.class));
}
@Test
@@ -367,14 +367,13 @@ public class WindowMagnificationManagerTest {
mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY,
requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom);
verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY),
eq(3f), eq(requestedRect.exactCenterX()), eq(requestedRect.exactCenterY()),
eq(0f), eq(0f), notNull());
verify(mMockConnection.getConnection()).moveWindowMagnifierToPosition(eq(TEST_DISPLAY),
eq(requestedRect.exactCenterX()), eq(requestedRect.exactCenterY()),
any(IRemoteMagnificationAnimationCallback.class));
}
@Test
public void onRectangleOnScreenRequested_followTypingIsDisabled_withoutMovingMagnification()
throws RemoteException {
public void onRectangleOnScreenRequested_followTypingIsDisabled_withoutMovingMagnification() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f);
final Region beforeRegion = new Region();