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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user