Merge "feat(#AlwaysOnMagnifier)!: Supports activated field in MagnificationConfig"

This commit is contained in:
Roy Chou
2023-01-31 06:58:24 +00:00
committed by Android (Google) Code Review
8 changed files with 223 additions and 33 deletions

View File

@@ -3538,6 +3538,7 @@ package android.accessibilityservice {
method public float getCenterY();
method public int getMode();
method public float getScale();
method public boolean isActivated();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.MagnificationConfig> CREATOR;
field public static final int MAGNIFICATION_MODE_DEFAULT = 0; // 0x0
@@ -3548,6 +3549,7 @@ package android.accessibilityservice {
public static final class MagnificationConfig.Builder {
ctor public MagnificationConfig.Builder();
method @NonNull public android.accessibilityservice.MagnificationConfig build();
method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setActivated(boolean);
method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setCenterX(float);
method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setCenterY(float);
method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setMode(int);

View File

@@ -76,6 +76,7 @@ public final class MagnificationConfig implements Parcelable {
}
private int mMode = MAGNIFICATION_MODE_DEFAULT;
private boolean mActivated = false;
private float mScale = Float.NaN;
private float mCenterX = Float.NaN;
private float mCenterY = Float.NaN;
@@ -86,6 +87,7 @@ public final class MagnificationConfig implements Parcelable {
private MagnificationConfig(@NonNull Parcel parcel) {
mMode = parcel.readInt();
mActivated = parcel.readBoolean();
mScale = parcel.readFloat();
mCenterX = parcel.readFloat();
mCenterY = parcel.readFloat();
@@ -101,10 +103,21 @@ public final class MagnificationConfig implements Parcelable {
return mMode;
}
/**
* Returns the activated state of the controlling magnifier. The controlling magnifier can be
* activated even if the scale returned by {@link MagnificationConfig#getScale()} equals to 1.0.
*
* @return {@code true} if the magnifier is showing on screen,
* {@code false} otherwise.
*/
public boolean isActivated() {
return mActivated;
}
/**
* Returns the magnification scale of the controlling magnifier
*
* @return the scale If the controlling magnifier is not activated, it returns 1 by default
* @return The magnification scale
*/
public float getScale() {
return mScale;
@@ -113,9 +126,7 @@ public final class MagnificationConfig implements Parcelable {
/**
* Returns the screen-relative X coordinate of the center of the magnification viewport.
*
* @return the X coordinate. If the controlling magnifier is {@link #MAGNIFICATION_MODE_WINDOW}
* but not enabled, it returns {@link Float#NaN}. If the controlling magnifier is {@link
* #MAGNIFICATION_MODE_FULLSCREEN} but not enabled, it returns 0
* @return The X coordinate
*/
public float getCenterX() {
return mCenterX;
@@ -124,9 +135,7 @@ public final class MagnificationConfig implements Parcelable {
/**
* Returns the screen-relative Y coordinate of the center of the magnification viewport.
*
* @return the Y coordinate If the controlling magnifier is {@link #MAGNIFICATION_MODE_WINDOW}
* but not enabled, it returns {@link Float#NaN}. If the controlling magnifier is {@link
* #MAGNIFICATION_MODE_FULLSCREEN} but not enabled, it returns 0
* @return The Y coordinate
*/
public float getCenterY() {
return mCenterY;
@@ -138,6 +147,8 @@ public final class MagnificationConfig implements Parcelable {
StringBuilder stringBuilder = new StringBuilder("MagnificationConfig[");
stringBuilder.append("mode: ").append(getMode());
stringBuilder.append(", ");
stringBuilder.append("activated: ").append(isActivated());
stringBuilder.append(", ");
stringBuilder.append("scale: ").append(getScale());
stringBuilder.append(", ");
stringBuilder.append("centerX: ").append(getCenterX());
@@ -155,6 +166,7 @@ public final class MagnificationConfig implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeInt(mMode);
parcel.writeBoolean(mActivated);
parcel.writeFloat(mScale);
parcel.writeFloat(mCenterX);
parcel.writeFloat(mCenterY);
@@ -166,6 +178,7 @@ public final class MagnificationConfig implements Parcelable {
public static final class Builder {
private int mMode = MAGNIFICATION_MODE_DEFAULT;
private boolean mActivated = true;
private float mScale = Float.NaN;
private float mCenterX = Float.NaN;
private float mCenterY = Float.NaN;
@@ -188,6 +201,18 @@ public final class MagnificationConfig implements Parcelable {
return this;
}
/**
* Sets magnification activated state.
*
* @param activated The magnification activated state
* @return This builder
*/
@NonNull
public MagnificationConfig.Builder setActivated(boolean activated) {
mActivated = activated;
return this;
}
/**
* Sets the magnification scale.
*
@@ -237,6 +262,7 @@ public final class MagnificationConfig implements Parcelable {
public MagnificationConfig build() {
MagnificationConfig magnificationConfig = new MagnificationConfig();
magnificationConfig.mMode = mMode;
magnificationConfig.mActivated = mActivated;
magnificationConfig.mScale = mScale;
magnificationConfig.mCenterX = mCenterX;
magnificationConfig.mCenterY = mCenterY;

View File

@@ -371,6 +371,7 @@ public class FullScreenMagnificationController implements
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(MAGNIFICATION_MODE_FULLSCREEN)
.setActivated(mMagnificationActivated)
.setScale(scale)
.setCenterX(getCenterX())
.setCenterY(getCenterY()).build();

View File

@@ -284,6 +284,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
}
synchronized (mLock) {
final int targetMode = config.getMode();
final boolean targetActivated = config.isActivated();
final PointF currentCenter = getCurrentMagnificationCenterLocked(displayId, targetMode);
final PointF magnificationCenter = new PointF(config.getCenterX(), config.getCenterY());
if (currentCenter != null) {
@@ -310,20 +311,30 @@ public class MagnificationController implements WindowMagnificationManager.Callb
: config.getScale();
try {
setTransitionState(displayId, targetMode);
// Activate or deactivate target mode depending on config activated value
if (targetMode == MAGNIFICATION_MODE_WINDOW) {
screenMagnificationController.reset(displayId, false);
windowMagnificationMgr.enableWindowMagnification(displayId,
targetScale, magnificationCenter.x, magnificationCenter.y,
animate ? STUB_ANIMATION_CALLBACK : null, id);
if (targetActivated) {
windowMagnificationMgr.enableWindowMagnification(displayId,
targetScale, magnificationCenter.x, magnificationCenter.y,
animate ? STUB_ANIMATION_CALLBACK : null, id);
} else {
windowMagnificationMgr.disableWindowMagnification(displayId, false);
}
} else if (targetMode == MAGNIFICATION_MODE_FULLSCREEN) {
windowMagnificationMgr.disableWindowMagnification(displayId, false, null);
if (!screenMagnificationController.isRegistered(displayId)) {
screenMagnificationController.register(displayId);
if (targetActivated) {
if (!screenMagnificationController.isRegistered(displayId)) {
screenMagnificationController.register(displayId);
}
screenMagnificationController.setScaleAndCenter(displayId, targetScale,
magnificationCenter.x, magnificationCenter.y, animate,
id);
} else {
if (screenMagnificationController.isRegistered(displayId)) {
screenMagnificationController.reset(displayId, false);
}
}
screenMagnificationController.setScaleAndCenter(displayId, targetScale,
magnificationCenter.x, magnificationCenter.y, animate,
id);
}
} finally {
// Reset transition state after enabling target mode.
@@ -454,6 +465,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
if (shouldNotifyMagnificationChange(displayId, MAGNIFICATION_MODE_WINDOW)) {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(MAGNIFICATION_MODE_WINDOW)
.setActivated(getWindowMagnificationMgr().isWindowMagnifierEnabled(displayId))
.setScale(getWindowMagnificationMgr().getScale(displayId))
.setCenterX(bounds.exactCenterX())
.setCenterY(bounds.exactCenterY()).build();
@@ -834,6 +846,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
new MagnificationConfig.Builder();
Region region = new Region();
configBuilder.setMode(MAGNIFICATION_MODE_FULLSCREEN)
.setActivated(screenMagnificationController.isActivated(mDisplayId))
.setScale(screenMagnificationController.getScale(mDisplayId))
.setCenterX(screenMagnificationController.getCenterX(mDisplayId))
.setCenterY(screenMagnificationController.getCenterY(mDisplayId));

View File

@@ -79,6 +79,7 @@ public class MagnificationProcessor {
final FullScreenMagnificationController fullScreenMagnificationController =
mController.getFullScreenMagnificationController();
builder.setMode(mode)
.setActivated(mController.isActivated(displayId, MAGNIFICATION_MODE_FULLSCREEN))
.setScale(fullScreenMagnificationController.getScale(displayId))
.setCenterX(fullScreenMagnificationController.getCenterX(displayId))
.setCenterY(fullScreenMagnificationController.getCenterY(displayId));
@@ -86,9 +87,13 @@ public class MagnificationProcessor {
final WindowMagnificationManager windowMagnificationManager =
mController.getWindowMagnificationMgr();
builder.setMode(mode)
.setActivated(mController.isActivated(displayId, MAGNIFICATION_MODE_WINDOW))
.setScale(windowMagnificationManager.getScale(displayId))
.setCenterX(windowMagnificationManager.getCenterX(displayId))
.setCenterY(windowMagnificationManager.getCenterY(displayId));
} else {
// For undefined mode, set enabled to false
builder.setActivated(false);
}
return builder.build();
}
@@ -118,15 +123,26 @@ public class MagnificationProcessor {
if (configMode == MAGNIFICATION_MODE_DEFAULT) {
configMode = getControllingMode(displayId);
}
// Check should activate or deactivate the target mode in config
boolean configActivated = config.isActivated();
if (configMode == MAGNIFICATION_MODE_FULLSCREEN) {
return setScaleAndCenterForFullScreenMagnification(displayId, config.getScale(),
config.getCenterX(), config.getCenterY(),
animate, id);
if (configActivated) {
return setScaleAndCenterForFullScreenMagnification(displayId, config.getScale(),
config.getCenterX(), config.getCenterY(),
animate, id);
} else {
return resetFullscreenMagnification(displayId, animate);
}
} else if (configMode == MAGNIFICATION_MODE_WINDOW) {
return mController.getWindowMagnificationMgr().enableWindowMagnification(displayId,
config.getScale(), config.getCenterX(), config.getCenterY(),
animate ? STUB_ANIMATION_CALLBACK : null,
id);
if (configActivated) {
return mController.getWindowMagnificationMgr().enableWindowMagnification(displayId,
config.getScale(), config.getCenterX(), config.getCenterY(),
animate ? STUB_ANIMATION_CALLBACK : null,
id);
} else {
return mController.getWindowMagnificationMgr()
.disableWindowMagnification(displayId, false);
}
}
return false;
}

View File

@@ -632,7 +632,7 @@ public class WindowMagnificationManager implements
* @param clear {@true} Clears the state of window magnification.
* @return {@code true} if the magnification is turned to be disabled successfully
*/
boolean disableWindowMagnification(int displayId, boolean clear) {
public boolean disableWindowMagnification(int displayId, boolean clear) {
return disableWindowMagnification(displayId, clear, STUB_ANIMATION_CALLBACK);
}
@@ -697,7 +697,6 @@ public class WindowMagnificationManager implements
* @param displayId The logical display id.
* @return {@code true} if the window magnification is enabled.
*/
@VisibleForTesting
public boolean isWindowMagnifierEnabled(int displayId) {
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);

View File

@@ -24,6 +24,7 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
@@ -70,7 +71,6 @@ public class MagnificationProcessorTest {
WindowMagnificationManagerStub mWindowMagnificationManagerStub;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mFullScreenMagnificationControllerStub = new FullScreenMagnificationControllerStub(
@@ -433,27 +433,60 @@ public class MagnificationProcessorTest {
eq(newConfig), anyBoolean(), anyInt());
}
@Test
public void setMagnificationConfigWithActivatedFalse_fullScreenEnabled_resetMagnification() {
setMagnificationActivated(TEST_DISPLAY, MAGNIFICATION_MODE_FULLSCREEN);
final MagnificationConfig config = new MagnificationConfig.Builder()
.setActivated(false).build();
mMagnificationProcessor.setMagnificationConfig(TEST_DISPLAY, config, false, SERVICE_ID);
verify(mMockFullScreenMagnificationController).reset(eq(TEST_DISPLAY), anyBoolean());
}
@Test
public void setMagnificationConfigWithActivatedFalse_windowEnabled_disableMagnification() {
setMagnificationActivated(TEST_DISPLAY, MAGNIFICATION_MODE_WINDOW);
final MagnificationConfig config = new MagnificationConfig.Builder()
.setActivated(false).build();
mMagnificationProcessor.setMagnificationConfig(TEST_DISPLAY, config, false, SERVICE_ID);
verify(mMockWindowMagnificationManager)
.disableWindowMagnification(eq(TEST_DISPLAY), anyBoolean());
}
@Test
public void setMagnificationConfigWithActivatedFalse_expectedReturnedValue() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setActivated(false).build();
assertFalse(mMagnificationProcessor.setMagnificationConfig(
TEST_DISPLAY, config, false, SERVICE_ID));
}
private void setMagnificationActivated(int displayId, int configMode) {
setMagnificationActivated(displayId,
new MagnificationConfig.Builder().setMode(configMode).build());
new MagnificationConfig.Builder()
.setMode(configMode)
.setScale(TEST_SCALE).build());
}
private void setMagnificationActivated(int displayId, MagnificationConfig config) {
if (!config.isActivated()) {
fail("setMagnificationActivated method should be called with config activated true");
}
when(mMockMagnificationController.isActivated(displayId, config.getMode())).thenReturn(
true);
mMagnificationProcessor.setMagnificationConfig(displayId, config, false, SERVICE_ID);
if (config.getMode() == MAGNIFICATION_MODE_FULLSCREEN) {
when(mMockMagnificationController.isActivated(displayId,
MAGNIFICATION_MODE_WINDOW)).thenReturn(false);
mFullScreenMagnificationControllerStub.resetAndStubMethods();
mMockFullScreenMagnificationController.setScaleAndCenter(displayId, config.getScale(),
config.getCenterX(), config.getCenterY(), false, SERVICE_ID);
mWindowMagnificationManagerStub.deactivateIfNeed();
} else if (config.getMode() == MAGNIFICATION_MODE_WINDOW) {
when(mMockMagnificationController.isActivated(displayId,
MAGNIFICATION_MODE_FULLSCREEN)).thenReturn(false);
mWindowMagnificationManagerStub.resetAndStubMethods();
mMockWindowMagnificationManager.enableWindowMagnification(displayId, config.getScale(),
config.getCenterX(), config.getCenterY());
mFullScreenMagnificationControllerStub.deactivateIfNeed();
}
}
@@ -469,6 +502,7 @@ public class MagnificationProcessorTest {
private float mScale = 1.0f;
private float mCenterX = 0;
private float mCenterY = 0;
private boolean mIsActivated = false;
private boolean mIsRegistered = false;
FullScreenMagnificationControllerStub(
@@ -485,7 +519,11 @@ public class MagnificationProcessorTest {
TEST_DISPLAY);
doAnswer(invocation -> mIsRegistered).when(mScreenMagnificationController).isRegistered(
TEST_DISPLAY);
doAnswer(invocation -> mIsActivated).when(mScreenMagnificationController).isActivated(
TEST_DISPLAY);
Answer enableMagnificationStubAnswer = invocation -> {
mIsActivated = true;
mScale = invocation.getArgument(1);
mCenterX = invocation.getArgument(2);
mCenterY = invocation.getArgument(3);
@@ -495,6 +533,13 @@ public class MagnificationProcessorTest {
mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), anyFloat(),
anyFloat(), anyFloat(), anyBoolean(), eq(SERVICE_ID));
Answer disableMagnificationStubAnswer = invocation -> {
deactivateIfNeed();
return true;
};
doAnswer(disableMagnificationStubAnswer).when(
mScreenMagnificationController).reset(eq(TEST_DISPLAY), anyBoolean());
Answer registerStubAnswer = invocation -> {
mIsRegistered = true;
return true;
@@ -508,14 +553,19 @@ public class MagnificationProcessorTest {
};
doAnswer(unregisterStubAnswer).when(
mScreenMagnificationController).unregister(eq(TEST_DISPLAY));
doAnswer(unregisterStubAnswer).when(
mScreenMagnificationController).reset(eq(TEST_DISPLAY), anyBoolean());
}
public void resetAndStubMethods() {
Mockito.reset(mScreenMagnificationController);
stubMethods();
}
public void deactivateIfNeed() {
mScale = 1.0f;
mCenterX = 0;
mCenterY = 0;
mIsActivated = false;
}
}
private static class WindowMagnificationManagerStub {
@@ -523,6 +573,7 @@ public class MagnificationProcessorTest {
private float mScale = 1.0f;
private float mCenterX = 0;
private float mCenterY = 0;
private boolean mIsEnabled = false;
WindowMagnificationManagerStub(
WindowMagnificationManager windowMagnificationManager) {
@@ -536,7 +587,11 @@ public class MagnificationProcessorTest {
TEST_DISPLAY);
doAnswer(invocation -> mCenterY).when(mWindowMagnificationManager).getCenterY(
TEST_DISPLAY);
doAnswer(invocation -> mIsEnabled).when(mWindowMagnificationManager)
.isWindowMagnifierEnabled(TEST_DISPLAY);
Answer enableWindowMagnificationStubAnswer = invocation -> {
mIsEnabled = true;
mScale = invocation.getArgument(1);
mCenterX = invocation.getArgument(2);
mCenterY = invocation.getArgument(3);
@@ -548,11 +603,29 @@ public class MagnificationProcessorTest {
doAnswer(enableWindowMagnificationStubAnswer).when(
mWindowMagnificationManager).enableWindowMagnification(eq(TEST_DISPLAY),
anyFloat(), anyFloat(), anyFloat(), any(), anyInt());
Answer disableWindowMagnificationStubAnswer = invocation -> {
deactivateIfNeed();
return true;
};
doAnswer(disableWindowMagnificationStubAnswer).when(
mWindowMagnificationManager).disableWindowMagnification(eq(TEST_DISPLAY),
anyBoolean());
doAnswer(disableWindowMagnificationStubAnswer).when(
mWindowMagnificationManager).disableWindowMagnification(eq(TEST_DISPLAY),
anyBoolean(), any());
}
public void resetAndStubMethods() {
Mockito.reset(mWindowMagnificationManager);
stubMethods();
}
public void deactivateIfNeed() {
mScale = 1.0f;
mCenterX = Float.NaN;
mCenterY = Float.NaN;
mIsEnabled = false;
}
}
}

View File

@@ -26,6 +26,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
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.anyLong;
@@ -403,6 +404,22 @@ public class MagnificationControllerTest {
assertEquals(MAGNIFIED_CENTER_Y, mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 0);
}
@Test
public void
configTransitionToWindowModeAndActivatedFalse_fullScreenMagnifying_doNotEnableWindow()
throws RemoteException {
activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
MagnificationConfig config = (new MagnificationConfig.Builder())
.setMode(MODE_WINDOW).setActivated(false).build();
mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
config, false, TEST_SERVICE_ID);
verify(mMockConnection.getConnection(), never()).enableWindowMagnification(anyInt(),
anyFloat(), anyFloat(), anyFloat(), anyFloat(), anyFloat(),
nullable(IRemoteMagnificationAnimationCallback.class));
}
@Test
public void configTransitionToFullScreen_windowMagnifying_disableWindowAndEnableFullScreen()
throws RemoteException {
@@ -419,6 +436,49 @@ public class MagnificationControllerTest {
animate, TEST_SERVICE_ID);
}
@Test
public void
configTransitionToFullScreenAndActivatedFalse_windowMagnifying_doNotEnableFullScreen()
throws RemoteException {
final boolean animate = true;
activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
MagnificationConfig config = (new MagnificationConfig.Builder())
.setMode(MODE_FULLSCREEN).setActivated(false).build();
mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
config, animate, TEST_SERVICE_ID);
mMockConnection.invokeCallbacks();
verify(mScreenMagnificationController, never()).setScaleAndCenter(anyInt(),
anyFloat(), anyFloat(), anyFloat(),
anyBoolean(), anyInt());
}
@Test
public void configTransitionToActivatedFalse_fullScreenMagnifying_disableFullScreen()
throws RemoteException {
activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
MagnificationConfig config = (new MagnificationConfig.Builder())
.setMode(MODE_FULLSCREEN).setActivated(false).build();
mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
config, false, TEST_SERVICE_ID);
verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY), eq(false));
}
@Test
public void configTransitionToActivatedFalse_windowMagnifying_disableWindow()
throws RemoteException {
final boolean animate = true;
activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
MagnificationConfig config = (new MagnificationConfig.Builder())
.setMode(MODE_WINDOW).setActivated(false).build();
mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
config, animate, TEST_SERVICE_ID);
verify(mMockConnection.getConnection()).disableWindowMagnification(anyInt(),
nullable(IRemoteMagnificationAnimationCallback.class));
}
@Test
public void configTransitionToFullScreen_userSettingsDisablingFullScreen_enableFullScreen()
throws RemoteException {