Merge changes from topics "presubmit-am-8e1f6f3832184ab4980013d926d31388", "presubmit-am-a0b2814b27254513b7a62e0a1e0044ff" into tm-dev
* changes: Enables following typing functionality when the window magnifier is on again. Adds moveWindowMagnifierToPosition method
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",
|
||||
|
||||
@@ -383,9 +383,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +429,7 @@ public class WindowMagnificationManager implements
|
||||
* @param displayId The logical display id.
|
||||
* @param trackingTypingFocusEnabled Enabled or disable the function of tracking typing focus.
|
||||
*/
|
||||
private void setTrackingTypingFocusEnabled(int displayId, boolean trackingTypingFocusEnabled) {
|
||||
void setTrackingTypingFocusEnabled(int displayId, boolean trackingTypingFocusEnabled) {
|
||||
synchronized (mLock) {
|
||||
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
|
||||
if (magnifier == null) {
|
||||
@@ -569,8 +572,11 @@ public class WindowMagnificationManager implements
|
||||
animationCallback, windowPosition, id);
|
||||
}
|
||||
|
||||
if (enabled && !previousEnabled) {
|
||||
mCallback.onWindowMagnificationActivationState(displayId, true);
|
||||
if (enabled) {
|
||||
setTrackingTypingFocusEnabled(displayId, true);
|
||||
if (!previousEnabled) {
|
||||
mCallback.onWindowMagnificationActivationState(displayId, true);
|
||||
}
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
@@ -632,14 +638,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -954,7 +959,6 @@ public class WindowMagnificationManager implements
|
||||
mWindowMagnificationManager = windowMagnificationManager;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
boolean enableWindowMagnificationInternal(float scale, float centerX, float centerY,
|
||||
@Nullable MagnificationAnimationCallback animationCallback,
|
||||
@WindowPosition int windowPosition, int id) {
|
||||
@@ -1032,7 +1036,6 @@ public class WindowMagnificationManager implements
|
||||
return mIdOfLastServiceToControl;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
int pointersInWindow(MotionEvent motionEvent) {
|
||||
int count = 0;
|
||||
final int pointerCount = motionEvent.getPointerCount();
|
||||
@@ -1131,8 +1134,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;
|
||||
@@ -291,7 +293,7 @@ public class WindowMagnificationManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRectangleOnScreenRequested_trackingDisabledByOnDrag_withoutMovingMagnification()
|
||||
public void onRectangleOnScreenRequested_trackingDisabledByOnDrag_withoutMovingMagnifier()
|
||||
throws RemoteException {
|
||||
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
|
||||
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f);
|
||||
@@ -304,14 +306,13 @@ 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
|
||||
public void onRectangleOnScreenRequested_trackingDisabledByScroll_withoutMovingMagnification()
|
||||
public void onRectangleOnScreenRequested_trackingDisabledByScroll_withoutMovingMagnifier()
|
||||
throws RemoteException {
|
||||
final float distanceX = 10f;
|
||||
final float distanceY = 10f;
|
||||
@@ -326,13 +327,12 @@ 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
|
||||
public void onRectangleOnScreenRequested_requestRectangleInBound_withoutMovingMagnification()
|
||||
public void onRectangleOnScreenRequested_requestRectangleInBound_withoutMovingMagnifier()
|
||||
throws RemoteException {
|
||||
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
|
||||
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f);
|
||||
@@ -344,12 +344,12 @@ 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
|
||||
public void onRectangleOnScreenRequested_trackingEnabledByDefault_movingMagnification()
|
||||
public void onRectangleOnScreenRequested_trackingEnabledByDefault_movingMagnifier()
|
||||
throws RemoteException {
|
||||
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
|
||||
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f);
|
||||
@@ -361,18 +361,16 @@ 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
|
||||
public void onRectangleOnScreenRequested_trackingEnabledByDragAndReset_movingMagnification()
|
||||
public void onRectangleOnScreenRequested_trackingEnabledByDragAndReset_movingMagnifier()
|
||||
throws RemoteException {
|
||||
final PointF initialPoint = new PointF(50f, 50f);
|
||||
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
|
||||
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f,
|
||||
initialPoint.x, initialPoint.y);
|
||||
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f);
|
||||
mMockConnection.getConnectionCallback().onDrag(TEST_DISPLAY);
|
||||
mWindowMagnificationManager.onImeWindowVisibilityChanged(true);
|
||||
final Region outRegion = new Region();
|
||||
@@ -383,14 +381,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_withoutMovingMagnifier() {
|
||||
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
|
||||
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f);
|
||||
final Region beforeRegion = new Region();
|
||||
@@ -407,6 +404,46 @@ public class WindowMagnificationManagerTest {
|
||||
assertEquals(afterRegion, beforeRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRectangleOnScreenRequested_trackingDisabled_withoutMovingMagnifier() {
|
||||
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
|
||||
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f);
|
||||
mWindowMagnificationManager.setTrackingTypingFocusEnabled(TEST_DISPLAY, false);
|
||||
final Region beforeRegion = new Region();
|
||||
mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion);
|
||||
final Rect requestedRect = beforeRegion.getBounds();
|
||||
requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10);
|
||||
|
||||
mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY,
|
||||
requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom);
|
||||
|
||||
final Region afterRegion = new Region();
|
||||
mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, afterRegion);
|
||||
assertEquals(afterRegion, beforeRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRectangleOnScreenRequested_trackingDisabledAndEnabledMagnifier_movingMagnifier()
|
||||
throws RemoteException {
|
||||
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
|
||||
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f);
|
||||
mWindowMagnificationManager.setTrackingTypingFocusEnabled(TEST_DISPLAY, false);
|
||||
final Region beforeRegion = new Region();
|
||||
mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion);
|
||||
final Rect requestedRect = beforeRegion.getBounds();
|
||||
requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10);
|
||||
mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false);
|
||||
// Enabling a window magnifier again will turn on the tracking typing focus functionality.
|
||||
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, NaN, NaN, NaN);
|
||||
|
||||
mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY,
|
||||
requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom);
|
||||
|
||||
verify(mMockConnection.getConnection()).moveWindowMagnifierToPosition(eq(TEST_DISPLAY),
|
||||
eq(requestedRect.exactCenterX()), eq(requestedRect.exactCenterY()),
|
||||
any(IRemoteMagnificationAnimationCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveWindowMagnifier_enabled_invokeConnectionMethod() throws RemoteException {
|
||||
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
|
||||
|
||||
Reference in New Issue
Block a user