MagnificationProcessor uses MagnificationConfig to control the specified magnifier

MagnificationConfig stores the magnification configuration of the
controlling magnifier, such as magnification mode, scale and center
postion.
And MagnificationProcessor uses the config to controll the magnifier for
AccessibilityService.

See
API review doc: go/b200769372
Design doc: go/a11yservice_control_magnification_in_t
   The chapter at Proposal A and  MagnificationConfig
CTS: ag/15824302

Bug: 199732498
Test: atest AbstractAccessibilityServiceConnectionTest,
      atest MagnificationProcessorTest,
      atest WindowMagnificationManagerTest,
      atest MagnificationConfigTest
Change-Id: I20323865d2efe1b40626f0c86767848733856482
This commit is contained in:
mincheli
2021-09-12 04:21:51 +08:00
committed by Minche Li
parent 821b4cdf55
commit 1a07e0dbe7
10 changed files with 935 additions and 103 deletions

View File

@@ -3254,6 +3254,28 @@ package android.accessibilityservice {
method public boolean willContinue();
}
public final class MagnificationConfig implements android.os.Parcelable {
method public int describeContents();
method public float getCenterX();
method public float getCenterY();
method public int getMode();
method public float getScale();
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 DEFAULT_MODE = 0; // 0x0
field public static final int FULLSCREEN_MODE = 1; // 0x1
field public static final int WINDOW_MODE = 2; // 0x2
}
public static final class MagnificationConfig.Builder {
ctor public MagnificationConfig.Builder();
method @NonNull public android.accessibilityservice.MagnificationConfig build();
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);
method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setScale(float);
}
public final class TouchInteractionController {
method public int getDisplayId();
method public int getMaxPointerCount();

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2021 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 android.accessibilityservice;
parcelable MagnificationConfig;

View File

@@ -0,0 +1,250 @@
/*
* Copyright (C) 2021 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 android.accessibilityservice;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* This class describes the magnification config for {@link AccessibilityService} to control the
* magnification.
*
* <p>
* When the magnification config uses {@link #DEFAULT_MODE},
* {@link AccessibilityService} will be able to control the activated magnifier on the display.
* If there is no magnifier activated, it controls the last-activated magnification mode.
* If there is no magnifier activated before, it controls full-screen magnifier by default.
* </p>
*
* <p>
* When the magnification config uses {@link #FULLSCREEN_MODE}. {@link AccessibilityService} will
* be able to control full-screen magnifier on the display.
* </p>
*
* <p>
* When the magnification config uses {@link #WINDOW_MODE}. {@link AccessibilityService} will be
* able to control the activated window magnifier on the display.
* </p>
*
* <p>
* If the other magnification configs, scale centerX and centerY, are not set by the
* {@link Builder}, the configs should be current values or default values. And the center
* position ordinarily is the center of the screen.
* </p>
*/
public final class MagnificationConfig implements Parcelable {
/** The controlling magnification mode. It controls the activated magnifier. */
public static final int DEFAULT_MODE = 0;
/** The controlling magnification mode. It controls fullscreen magnifier. */
public static final int FULLSCREEN_MODE = 1;
/** The controlling magnification mode. It controls window magnifier. */
public static final int WINDOW_MODE = 2;
@IntDef(prefix = {"MAGNIFICATION_MODE"}, value = {
DEFAULT_MODE,
FULLSCREEN_MODE,
WINDOW_MODE,
})
@Retention(RetentionPolicy.SOURCE)
@interface MAGNIFICATION_MODE {
}
private int mMode = DEFAULT_MODE;
private float mScale = Float.NaN;
private float mCenterX = Float.NaN;
private float mCenterY = Float.NaN;
private MagnificationConfig() {
/* do nothing */
}
private MagnificationConfig(@NonNull Parcel parcel) {
mMode = parcel.readInt();
mScale = parcel.readFloat();
mCenterX = parcel.readFloat();
mCenterY = parcel.readFloat();
}
/**
* Returns the magnification mode that is the current activated mode or the controlling mode of
* the config.
*
* @return The magnification mode
*/
public int getMode() {
return mMode;
}
/**
* Returns the magnification scale of the controlling magnifier
*
* @return the scale If the controlling magnifier is not activated, it returns 1 by default
*/
public float getScale() {
return mScale;
}
/**
* Returns the screen-relative X coordinate of the center of the magnification viewport.
*
* @return the X coordinate. If the controlling magnifier is {@link #WINDOW_MODE} but not
* enabled, it returns {@link Float#NaN}. If the controlling magnifier is {@link
* #FULLSCREEN_MODE} but not enabled, it returns 0
*/
public float getCenterX() {
return mCenterX;
}
/**
* Returns the screen-relative Y coordinate of the center of the magnification viewport.
*
* @return the Y coordinate If the controlling magnifier is {@link #WINDOW_MODE} but not
* enabled, it returns {@link Float#NaN}. If the controlling magnifier is {@link
* #FULLSCREEN_MODE} but not enabled, it returns 0
*/
public float getCenterY() {
return mCenterY;
}
@NonNull
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder("MagnificationConfig[");
stringBuilder.append("mode: ").append(getMode());
stringBuilder.append(", ");
stringBuilder.append("scale: ").append(getScale());
stringBuilder.append(", ");
stringBuilder.append("centerX: ").append(getCenterX());
stringBuilder.append(", ");
stringBuilder.append("centerY: ").append(getCenterY());
stringBuilder.append("] ");
return stringBuilder.toString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeInt(mMode);
parcel.writeFloat(mScale);
parcel.writeFloat(mCenterX);
parcel.writeFloat(mCenterY);
}
/**
* Builder for creating {@link MagnificationConfig} objects.
*/
public static final class Builder {
private int mMode = DEFAULT_MODE;
private float mScale = Float.NaN;
private float mCenterX = Float.NaN;
private float mCenterY = Float.NaN;
/**
* Creates a new Builder.
*/
public Builder() {
}
/**
* Sets the magnification mode.
*
* @param mode The magnification mode
* @return This builder
*/
@NonNull
public MagnificationConfig.Builder setMode(@MAGNIFICATION_MODE int mode) {
mMode = mode;
return this;
}
/**
* Sets the magnification scale.
*
* @param scale The magnification scale
* @return This builder
*/
@NonNull
public MagnificationConfig.Builder setScale(float scale) {
mScale = scale;
return this;
}
/**
* Sets the X coordinate of the center of the magnification viewport.
*
* @param centerX the screen-relative X coordinate around which to
* center and scale, or {@link Float#NaN} to leave unchanged
* @return This builder
*/
@NonNull
public MagnificationConfig.Builder setCenterX(float centerX) {
mCenterX = centerX;
return this;
}
/**
* Sets the Y coordinate of the center of the magnification viewport.
*
* @param centerY the screen-relative Y coordinate around which to
* center and scale, or {@link Float#NaN} to leave unchanged
* @return This builder
*/
@NonNull
public MagnificationConfig.Builder setCenterY(float centerY) {
mCenterY = centerY;
return this;
}
/**
* Builds and returns a {@link MagnificationConfig}
*/
@NonNull
public MagnificationConfig build() {
MagnificationConfig magnificationConfig = new MagnificationConfig();
magnificationConfig.mMode = mMode;
magnificationConfig.mScale = mScale;
magnificationConfig.mCenterX = mCenterX;
magnificationConfig.mCenterY = mCenterY;
return magnificationConfig;
}
}
/**
* @see Parcelable.Creator
*/
public static final @NonNull Parcelable.Creator<MagnificationConfig> CREATOR =
new Parcelable.Creator<MagnificationConfig>() {
public MagnificationConfig createFromParcel(Parcel parcel) {
return new MagnificationConfig(parcel);
}
public MagnificationConfig[] newArray(int size) {
return new MagnificationConfig[size];
}
};
}

View File

@@ -39,6 +39,7 @@ import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.accessibilityservice.MagnificationConfig;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -1101,8 +1102,12 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
try {
MagnificationProcessor magnificationProcessor =
mSystemSupport.getMagnificationProcessor();
return magnificationProcessor
.setScaleAndCenter(displayId, scale, centerX, centerY, animate, mId);
final MagnificationConfig config = new MagnificationConfig.Builder()
.setScale(scale)
.setCenterX(centerX)
.setCenterY(centerY).build();
return magnificationProcessor.setMagnificationConfig(displayId, config, animate,
mId);
} finally {
Binder.restoreCallingIdentity(identity);
}

View File

@@ -84,6 +84,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb
@GuardedBy("mLock")
private int mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
@GuardedBy("mLock")
private int mLastActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
// Track the active user to reset the magnification and get the associated user settings.
private @UserIdInt int mUserId = UserHandle.USER_SYSTEM;
@GuardedBy("mLock")
@@ -239,6 +241,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
synchronized (mLock) {
mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
mLastActivatedMode = mActivatedMode;
}
logMagnificationModeWithImeOnIfNeeded();
disableFullScreenMagnificationIfNeeded(displayId);
@@ -276,6 +279,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
synchronized (mLock) {
mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
mLastActivatedMode = mActivatedMode;
}
logMagnificationModeWithImeOnIfNeeded();
} else {
@@ -297,6 +301,16 @@ public class MagnificationController implements WindowMagnificationManager.Callb
logMagnificationModeWithImeOnIfNeeded();
}
/**
* Returns the last activated magnification mode. If there is no activated magnifier before, it
* returns fullscreen mode by default.
*/
public int getLastActivatedMode() {
synchronized (mLock) {
return mLastActivatedMode;
}
}
/**
* Wrapper method of logging the magnification activated mode and its duration of the usage
* when the magnification is disabled.
@@ -336,6 +350,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
synchronized (mLock) {
fullMagnificationController = mFullScreenMagnificationController;
windowMagnificationManager = mWindowMagnificationMgr;
mLastActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
}
mScaleProvider.onUserChanged(userId);
@@ -462,7 +477,15 @@ public class MagnificationController implements WindowMagnificationManager.Callb
return mTempPoint;
}
private boolean isActivated(int displayId, int mode) {
/**
* Return {@code true} if the specified magnification mode on the given display is activated
* or not.
*
* @param displayId The logical displayId.
* @param mode It's either ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN or
* ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW.
*/
public boolean isActivated(int displayId, int mode) {
boolean isActivated = false;
if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) {
synchronized (mLock) {

View File

@@ -16,6 +16,13 @@
package com.android.server.accessibility.magnification;
import static android.accessibilityservice.MagnificationConfig.DEFAULT_MODE;
import static android.accessibilityservice.MagnificationConfig.FULLSCREEN_MODE;
import static android.accessibilityservice.MagnificationConfig.WINDOW_MODE;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
import android.accessibilityservice.MagnificationConfig;
import android.annotation.NonNull;
import android.graphics.Region;
@@ -23,6 +30,22 @@ import android.graphics.Region;
* Processor class for AccessibilityService connection to control magnification on the specified
* display. This wraps the function of magnification controller.
*
* <p>
* If the magnification config uses {@link DEFAULT_MODE}. This processor will control the current
* activated magnifier on the display. If there is no magnifier activated, it controls
* full-screen magnifier by default.
* </p>
*
* <p>
* If the magnification config uses {@link FULLSCREEN_MODE}. This processor will control
* full-screen magnifier on the display.
* </p>
*
* <p>
* If the magnification config uses {@link WINDOW_MODE}. This processor will control
* the activated window magnifier on the display.
* </p>
*
* @see MagnificationController
* @see FullScreenMagnificationController
*/
@@ -35,53 +58,166 @@ public class MagnificationProcessor {
}
/**
* {@link FullScreenMagnificationController#getScale(int)}
* Gets the magnification config of the display.
*
* @param displayId The logical display id
* @return the magnification config
*/
public @NonNull MagnificationConfig getMagnificationConfig(int displayId) {
final int mode = getControllingMode(displayId);
MagnificationConfig.Builder builder = new MagnificationConfig.Builder();
if (mode == FULLSCREEN_MODE) {
final FullScreenMagnificationController fullScreenMagnificationController =
mController.getFullScreenMagnificationController();
builder.setMode(mode)
.setScale(fullScreenMagnificationController.getScale(displayId))
.setCenterX(fullScreenMagnificationController.getCenterX(displayId))
.setCenterY(fullScreenMagnificationController.getCenterY(displayId));
} else if (mode == WINDOW_MODE) {
final WindowMagnificationManager windowMagnificationManager =
mController.getWindowMagnificationMgr();
builder.setMode(mode)
.setScale(windowMagnificationManager.getScale(displayId))
.setCenterX(windowMagnificationManager.getCenterX(displayId))
.setCenterY(windowMagnificationManager.getCenterY(displayId));
}
return builder.build();
}
/**
* Sets the magnification config of the display. If animation is disabled, the transition
* is immediate.
*
* @param displayId The logical display id
* @param config The magnification config
* @param animate {@code true} to animate from the current config or
* {@code false} to set the config immediately
* @param id The ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if the spec did not
* change
*/
public boolean setMagnificationConfig(int displayId, @NonNull MagnificationConfig config,
boolean animate, int id) {
int configMode = config.getMode();
if (configMode == DEFAULT_MODE) {
configMode = getControllingMode(displayId);
}
if (configMode == FULLSCREEN_MODE) {
return setScaleAndCenterForFullScreenMagnification(displayId, config.getScale(),
config.getCenterX(), config.getCenterY(),
animate, id);
} else if (configMode == WINDOW_MODE) {
return mController.getWindowMagnificationMgr().enableWindowMagnification(displayId,
config.getScale(), config.getCenterX(), config.getCenterY());
}
return false;
}
/**
* Returns the magnification scale. If an animation is in progress,
* this reflects the end state of the animation.
*
* @param displayId The logical display id.
* @return the scale
*/
public float getScale(int displayId) {
return mController.getFullScreenMagnificationController().getScale(displayId);
int mode = getControllingMode(displayId);
if (mode == FULLSCREEN_MODE) {
return mController.getFullScreenMagnificationController().getScale(displayId);
} else if (mode == WINDOW_MODE) {
return mController.getWindowMagnificationMgr().getScale(displayId);
}
return 0;
}
/**
* {@link FullScreenMagnificationController#getCenterX(int)}
* Returns the magnification center in X coordinate of the controlling magnification mode.
* If the service can control magnification but fullscreen magnifier is not registered, it will
* register the magnifier for this call then unregister the magnifier finally to make the
* magnification center correct.
*
* @param displayId The logical display id
* @param canControlMagnification Whether the service can control magnification
* @return the X coordinate
*/
public float getCenterX(int displayId, boolean canControlMagnification) {
boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
canControlMagnification);
try {
return mController.getFullScreenMagnificationController().getCenterX(displayId);
} finally {
if (registeredJustForThisCall) {
unregister(displayId);
int mode = getControllingMode(displayId);
if (mode == FULLSCREEN_MODE) {
boolean registeredJustForThisCall = registerDisplayMagnificationIfNeeded(displayId,
canControlMagnification);
try {
return mController.getFullScreenMagnificationController().getCenterX(displayId);
} finally {
if (registeredJustForThisCall) {
unregister(displayId);
}
}
} else if (mode == WINDOW_MODE) {
return mController.getWindowMagnificationMgr().getCenterX(displayId);
}
return 0;
}
/**
* {@link FullScreenMagnificationController#getCenterY(int)}
* Returns the magnification center in Y coordinate of the controlling magnification mode.
* If the service can control magnification but fullscreen magnifier is not registered, it will
* register the magnifier for this call then unregister the magnifier finally to make the
* magnification center correct.
*
* @param displayId The logical display id
* @param canControlMagnification Whether the service can control magnification
* @return the Y coordinate
*/
public float getCenterY(int displayId, boolean canControlMagnification) {
boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
canControlMagnification);
try {
return mController.getFullScreenMagnificationController().getCenterY(displayId);
} finally {
if (registeredJustForThisCall) {
unregister(displayId);
int mode = getControllingMode(displayId);
if (mode == FULLSCREEN_MODE) {
boolean registeredJustForThisCall = registerDisplayMagnificationIfNeeded(displayId,
canControlMagnification);
try {
return mController.getFullScreenMagnificationController().getCenterY(displayId);
} finally {
if (registeredJustForThisCall) {
unregister(displayId);
}
}
} else if (mode == WINDOW_MODE) {
return mController.getWindowMagnificationMgr().getCenterY(displayId);
}
return 0;
}
/**
* {@link FullScreenMagnificationController#getMagnificationRegion(int, Region)}
* Return the magnification bounds of the current controlling magnification on the given
* display. If the magnifier is not enabled, it returns an empty region.
* If the service can control magnification but fullscreen magnifier is not registered, it will
* register the magnifier for this call then unregister the magnifier finally to make
* the magnification region correct.
*
* @param displayId The logical display id
* @param outRegion the region to populate
* @param canControlMagnification Whether the service can control magnification
* @return outRegion the magnification bounds of full-screen magnifier or the magnification
* source bounds of window magnifier
*/
public Region getMagnificationRegion(int displayId, @NonNull Region outRegion,
boolean canControlMagnification) {
boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
int mode = getControllingMode(displayId);
if (mode == FULLSCREEN_MODE) {
getFullscreenMagnificationRegion(displayId, outRegion, canControlMagnification);
} else if (mode == WINDOW_MODE) {
mController.getWindowMagnificationMgr().getMagnificationSourceBounds(displayId,
outRegion);
}
return outRegion;
}
private void getFullscreenMagnificationRegion(int displayId, @NonNull Region outRegion,
boolean canControlMagnification) {
boolean registeredJustForThisCall = registerDisplayMagnificationIfNeeded(displayId,
canControlMagnification);
try {
mController.getFullScreenMagnificationController().getMagnificationRegion(displayId,
outRegion);
return outRegion;
} finally {
if (registeredJustForThisCall) {
unregister(displayId);
@@ -89,67 +225,105 @@ public class MagnificationProcessor {
}
}
/**
* {@link FullScreenMagnificationController#setScaleAndCenter(int, float, float, float, boolean,
* int)}
*/
public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
private boolean setScaleAndCenterForFullScreenMagnification(int displayId, float scale,
float centerX, float centerY,
boolean animate, int id) {
if (!isRegistered(displayId)) {
register(displayId);
}
return mController.getFullScreenMagnificationController().setScaleAndCenter(displayId,
return mController.getFullScreenMagnificationController().setScaleAndCenter(
displayId,
scale,
centerX, centerY, animate, id);
}
/**
* {@link FullScreenMagnificationController#reset(int, boolean)}
* Resets the magnification on the given display. The reset mode could be full-screen or
* window if it is activated.
*
* @param displayId The logical display id.
* @param animate {@code true} to animate the transition, {@code false}
* to transition immediately
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
public boolean reset(int displayId, boolean animate) {
return mController.getFullScreenMagnificationController().reset(displayId, animate);
int mode = getControllingMode(displayId);
if (mode == FULLSCREEN_MODE) {
return mController.getFullScreenMagnificationController().reset(displayId, animate);
} else if (mode == WINDOW_MODE) {
return mController.getWindowMagnificationMgr().reset(displayId);
}
return false;
}
/**
* {@link FullScreenMagnificationController#resetIfNeeded(int, boolean)}
*/
// TODO: support window magnification
public void resetAllIfNeeded(int connectionId) {
mController.getFullScreenMagnificationController().resetAllIfNeeded(connectionId);
}
/**
* {@link FullScreenMagnificationController#register(int)}
*/
public void register(int displayId) {
mController.getFullScreenMagnificationController().register(displayId);
}
/**
* {@link FullScreenMagnificationController#unregister(int)} (int)}
*/
public void unregister(int displayId) {
mController.getFullScreenMagnificationController().unregister(displayId);
}
/**
* {@link FullScreenMagnificationController#isMagnifying(int)}
* {@link WindowMagnificationManager#isWindowMagnifierEnabled(int)}
*/
public boolean isMagnifying(int displayId) {
return mController.getFullScreenMagnificationController().isMagnifying(displayId);
int mode = getControllingMode(displayId);
if (mode == FULLSCREEN_MODE) {
return mController.getFullScreenMagnificationController().isMagnifying(displayId);
} else if (mode == WINDOW_MODE) {
return mController.getWindowMagnificationMgr().isWindowMagnifierEnabled(displayId);
}
return false;
}
/**
* {@link FullScreenMagnificationController#isRegistered(int)}
* Returns the current controlling magnification mode on the given display.
* If there is no magnifier activated, it fallbacks to the last activated mode.
* And the last activated mode is {@link FULLSCREEN_MODE} by default.
*
* @param displayId The logical display id
*/
public boolean isRegistered(int displayId) {
return mController.getFullScreenMagnificationController().isRegistered(displayId);
public int getControllingMode(int displayId) {
if (mController.isActivated(displayId,
ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)) {
return WINDOW_MODE;
} else if (mController.isActivated(displayId,
ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)) {
return FULLSCREEN_MODE;
} else {
return (mController.getLastActivatedMode() == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)
? WINDOW_MODE
: FULLSCREEN_MODE;
}
}
private boolean registerMagnificationIfNeeded(int displayId, boolean canControlMagnification) {
private boolean registerDisplayMagnificationIfNeeded(int displayId,
boolean canControlMagnification) {
if (!isRegistered(displayId) && canControlMagnification) {
register(displayId);
return true;
}
return false;
}
private boolean isRegistered(int displayId) {
return mController.getFullScreenMagnificationController().isRegistered(displayId);
}
/**
* {@link FullScreenMagnificationController#register(int)}
*/
private void register(int displayId) {
mController.getFullScreenMagnificationController().register(displayId);
}
/**
* {@link FullScreenMagnificationController#unregister(int)} (int)}
*/
private void unregister(int displayId) {
mController.getFullScreenMagnificationController().unregister(displayId);
}
}

View File

@@ -27,6 +27,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -271,9 +272,12 @@ public class WindowMagnificationManager implements
* or {@link Float#NaN} to leave unchanged.
* @param centerY The screen-relative Y coordinate around which to center,
* or {@link Float#NaN} to leave unchanged.
* @return {@code true} if the magnification is enabled successfully.
*/
void enableWindowMagnification(int displayId, float scale, float centerX, float centerY) {
enableWindowMagnification(displayId, scale, centerX, centerY, STUB_ANIMATION_CALLBACK);
public boolean enableWindowMagnification(int displayId, float scale, float centerX,
float centerY) {
return enableWindowMagnification(displayId, scale, centerX, centerY,
STUB_ANIMATION_CALLBACK);
}
/**
@@ -287,25 +291,29 @@ public class WindowMagnificationManager implements
* @param centerY The screen-relative Y coordinate around which to center,
* or {@link Float#NaN} to leave unchanged.
* @param animationCallback Called when the animation result is valid.
* @return {@code true} if the magnification is enabled successfully.
*/
void enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
@Nullable MagnificationAnimationCallback animationCallback) {
public boolean enableWindowMagnification(int displayId, float scale, float centerX,
float centerY, @Nullable MagnificationAnimationCallback animationCallback) {
final boolean enabled;
boolean previousEnabled;
synchronized (mLock) {
if (mConnectionWrapper == null) {
return;
return false;
}
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
magnifier = createWindowMagnifier(displayId);
}
previousEnabled = magnifier.mEnabled;
enabled = magnifier.enableWindowMagnificationInternal(scale, centerX, centerY,
animationCallback);
}
if (enabled) {
if (enabled && !previousEnabled) {
mCallback.onWindowMagnificationActivationState(displayId, true);
}
return enabled;
}
/**
@@ -464,7 +472,7 @@ public class WindowMagnificationManager implements
* @param displayId The logical display id
* @return the X coordinate. {@link Float#NaN} if the window magnification is not enabled.
*/
float getCenterX(int displayId) {
public float getCenterX(int displayId) {
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
@@ -480,7 +488,7 @@ public class WindowMagnificationManager implements
* @param displayId The logical display id
* @return the Y coordinate. {@link Float#NaN} if the window magnification is not enabled.
*/
float getCenterY(int displayId) {
public float getCenterY(int displayId) {
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
@@ -490,6 +498,42 @@ public class WindowMagnificationManager implements
}
}
/**
* Populates magnified bounds on the screen. And the populated magnified bounds would be
* empty If window magnifier is not activated.
*
* @param displayId The logical display id.
* @param outRegion the region to populate
*/
public void getMagnificationSourceBounds(int displayId, @NonNull Region outRegion) {
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
outRegion.setEmpty();
} else {
outRegion.set(magnifier.mSourceBounds);
}
}
}
/**
* Resets the magnification scale and center.
*
* @param displayId The logical display id.
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
public boolean reset(int displayId) {
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
return false;
}
magnifier.reset();
return true;
}
}
/**
* Creates the windowMagnifier based on the specified display and stores it.
*
@@ -626,8 +670,9 @@ public class WindowMagnificationManager implements
@GuardedBy("mLock")
boolean enableWindowMagnificationInternal(float scale, float centerX, float centerY,
@Nullable MagnificationAnimationCallback animationCallback) {
if (mEnabled) {
return false;
// Handle defaults. The scale may be NAN when just updating magnification center.
if (Float.isNaN(scale)) {
scale = getScale();
}
final float normScale = MagnificationScaleProvider.constrainScale(scale);
if (mWindowMagnificationManager.enableWindowMagnificationInternal(mDisplayId, normScale,

View File

@@ -68,6 +68,7 @@ import static org.mockito.Mockito.when;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.MagnificationConfig;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -650,8 +651,12 @@ public class AbstractAccessibilityServiceConnectionTest {
final float scale = 1.8f;
final float centerX = 50.5f;
final float centerY = 100.5f;
when(mMockMagnificationProcessor.setScaleAndCenter(displayId,
scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
MagnificationConfig config = new MagnificationConfig.Builder()
.setScale(scale)
.setCenterX(centerX)
.setCenterY(centerY).build();
when(mMockMagnificationProcessor.setMagnificationConfig(displayId, config, true,
SERVICE_ID)).thenReturn(true);
when(mMockSecurityPolicy.canControlMagnification(mServiceConnection)).thenReturn(false);
final boolean result = mServiceConnection.setMagnificationScaleAndCenter(
@@ -665,8 +670,12 @@ public class AbstractAccessibilityServiceConnectionTest {
final float scale = 1.8f;
final float centerX = 50.5f;
final float centerY = 100.5f;
when(mMockMagnificationProcessor.setScaleAndCenter(displayId,
scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
MagnificationConfig config = new MagnificationConfig.Builder()
.setScale(scale)
.setCenterX(centerX)
.setCenterY(centerY).build();
when(mMockMagnificationProcessor.setMagnificationConfig(displayId, config, true,
SERVICE_ID)).thenReturn(true);
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final boolean result = mServiceConnection.setMagnificationScaleAndCenter(

View File

@@ -16,25 +16,32 @@
package com.android.server.accessibility;
import static android.accessibilityservice.MagnificationConfig.FULLSCREEN_MODE;
import static android.accessibilityservice.MagnificationConfig.WINDOW_MODE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.accessibilityservice.MagnificationConfig;
import android.graphics.Region;
import com.android.server.accessibility.magnification.FullScreenMagnificationController;
import com.android.server.accessibility.magnification.MagnificationController;
import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.accessibility.magnification.WindowMagnificationManager;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
/**
* Tests for the {@link MagnificationProcessor}
@@ -42,57 +49,115 @@ import org.mockito.MockitoAnnotations;
public class MagnificationProcessorTest {
private static final int TEST_DISPLAY = 0;
private static final int SERVICE_ID = 42;
private static final float TEST_SCALE = 1.8f;
private static final float TEST_CENTER_X = 50.5f;
private static final float TEST_CENTER_Y = 100.5f;
private MagnificationProcessor mMagnificationProcessor;
@Mock
private MagnificationController mMockMagnificationController;
@Mock
private FullScreenMagnificationController mMockFullScreenMagnificationController;
@Mock
private WindowMagnificationManager mMockWindowMagnificationManager;
FullScreenMagnificationControllerStub mFullScreenMagnificationControllerStub;
WindowMagnificationManagerStub mWindowMagnificationManagerStub;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mFullScreenMagnificationControllerStub = new FullScreenMagnificationControllerStub(
mMockFullScreenMagnificationController);
mWindowMagnificationManagerStub = new WindowMagnificationManagerStub(
mMockWindowMagnificationManager);
when(mMockMagnificationController.getFullScreenMagnificationController()).thenReturn(
mMockFullScreenMagnificationController);
when(mMockMagnificationController.getWindowMagnificationMgr()).thenReturn(
mMockWindowMagnificationManager);
mMagnificationProcessor = new MagnificationProcessor(mMockMagnificationController);
}
@Test
public void getScale() {
final float result = 2;
when(mMockFullScreenMagnificationController.getScale(TEST_DISPLAY)).thenReturn(result);
public void getScale_fullscreenMode_expectedValue() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(FULLSCREEN_MODE)
.setScale(TEST_SCALE).build();
setMagnificationActivated(TEST_DISPLAY, config);
float scale = mMagnificationProcessor.getScale(TEST_DISPLAY);
assertEquals(scale, result, 0);
assertEquals(scale, TEST_SCALE, 0);
}
@Test
public void getCenterX_canControlMagnification_returnCenterX() {
final float result = 200;
when(mMockFullScreenMagnificationController.getCenterX(TEST_DISPLAY)).thenReturn(result);
public void getScale_windowMode_expectedValue() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(WINDOW_MODE)
.setScale(TEST_SCALE).build();
setMagnificationActivated(TEST_DISPLAY, config);
float scale = mMagnificationProcessor.getScale(TEST_DISPLAY);
assertEquals(scale, TEST_SCALE, 0);
}
@Test
public void getCenterX_canControlFullscreenMagnification_returnCenterX() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(FULLSCREEN_MODE)
.setCenterX(TEST_CENTER_X).build();
setMagnificationActivated(TEST_DISPLAY, config);
float centerX = mMagnificationProcessor.getCenterX(
TEST_DISPLAY, /* canControlMagnification= */true);
assertEquals(centerX, result, 0);
assertEquals(centerX, TEST_CENTER_X, 0);
}
@Test
public void getCenterY_canControlMagnification_returnCenterY() {
final float result = 300;
when(mMockFullScreenMagnificationController.getCenterY(TEST_DISPLAY)).thenReturn(result);
public void getCenterX_canControlWindowMagnification_returnCenterX() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(WINDOW_MODE)
.setCenterX(TEST_CENTER_X).build();
setMagnificationActivated(TEST_DISPLAY, config);
float centerX = mMagnificationProcessor.getCenterX(
TEST_DISPLAY, /* canControlMagnification= */true);
assertEquals(centerX, TEST_CENTER_X, 0);
}
@Test
public void getCenterY_canControlFullscreenMagnification_returnCenterY() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(FULLSCREEN_MODE)
.setCenterY(TEST_CENTER_Y).build();
setMagnificationActivated(TEST_DISPLAY, config);
float centerY = mMagnificationProcessor.getCenterY(
TEST_DISPLAY, /* canControlMagnification= */false);
assertEquals(centerY, result, 0);
assertEquals(centerY, TEST_CENTER_Y, 0);
}
@Test
public void getMagnificationRegion_canControlMagnification_returnRegion() {
public void getCenterY_canControlWindowMagnification_returnCenterY() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(WINDOW_MODE)
.setCenterY(TEST_CENTER_Y).build();
setMagnificationActivated(TEST_DISPLAY, config);
float centerY = mMagnificationProcessor.getCenterY(
TEST_DISPLAY, /* canControlMagnification= */false);
assertEquals(centerY, TEST_CENTER_Y, 0);
}
@Test
public void getMagnificationRegion_canControlFullscreenMagnification_returnRegion() {
final Region region = new Region(10, 20, 100, 200);
setMagnificationActivated(TEST_DISPLAY, FULLSCREEN_MODE);
mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
region, /* canControlMagnification= */true);
@@ -101,14 +166,25 @@ public class MagnificationProcessorTest {
}
@Test
public void getMagnificationRegion_notRegistered_shouldRegisterThenUnregister() {
public void getMagnificationRegion_canControlWindowMagnification_returnRegion() {
final Region region = new Region(10, 20, 100, 200);
setMagnificationActivated(TEST_DISPLAY, WINDOW_MODE);
mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
region, /* canControlMagnification= */true);
verify(mMockWindowMagnificationManager).getMagnificationSourceBounds(eq(TEST_DISPLAY),
eq(region));
}
@Test
public void getMagnificationRegion_fullscreenModeNotRegistered_shouldRegisterThenUnregister() {
final Region region = new Region(10, 20, 100, 200);
setMagnificationActivated(TEST_DISPLAY, FULLSCREEN_MODE);
doAnswer((invocation) -> {
((Region) invocation.getArguments()[1]).set(region);
return null;
}).when(mMockFullScreenMagnificationController).getMagnificationRegion(eq(TEST_DISPLAY),
any());
when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
final Region result = new Region();
mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
@@ -119,44 +195,242 @@ public class MagnificationProcessorTest {
}
@Test
public void getMagnificationCenterX_notRegistered_shouldRegisterThenUnregister() {
final float centerX = 480.0f;
when(mMockFullScreenMagnificationController.getCenterX(TEST_DISPLAY)).thenReturn(centerX);
when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
public void getMagnificationCenterX_fullscreenModeNotRegistered_shouldRegisterThenUnregister() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(FULLSCREEN_MODE)
.setCenterX(TEST_CENTER_X).build();
setMagnificationActivated(TEST_DISPLAY, config);
final float result = mMagnificationProcessor.getCenterX(
TEST_DISPLAY, /* canControlMagnification= */ true);
assertEquals(centerX, result, 0);
assertEquals(TEST_CENTER_X, result, 0);
verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
}
@Test
public void getMagnificationCenterY_notRegistered_shouldRegisterThenUnregister() {
final float centerY = 640.0f;
when(mMockFullScreenMagnificationController.getCenterY(TEST_DISPLAY)).thenReturn(centerY);
when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
public void getMagnificationCenterY_fullscreenModeNotRegistered_shouldRegisterThenUnregister() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(FULLSCREEN_MODE)
.setCenterY(TEST_CENTER_Y).build();
setMagnificationActivated(TEST_DISPLAY, config);
final float result = mMagnificationProcessor.getCenterY(
TEST_DISPLAY, /* canControlMagnification= */ true);
assertEquals(centerY, result, 0);
assertEquals(TEST_CENTER_Y, result, 0);
verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
}
@Test
public void setMagnificationScaleAndCenter_notRegistered_shouldRegister() {
final int serviceId = 42;
final float scale = 1.8f;
final float centerX = 50.5f;
final float centerY = 100.5f;
when(mMockFullScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY,
scale, centerX, centerY, true, serviceId)).thenReturn(true);
when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
public void getCurrentMode_configDefaultMode_returnActivatedMode() {
final int targetMode = WINDOW_MODE;
setMagnificationActivated(TEST_DISPLAY, targetMode);
final boolean result = mMagnificationProcessor.setScaleAndCenter(
TEST_DISPLAY, scale, centerX, centerY, true, serviceId);
int currentMode = mMagnificationProcessor.getControllingMode(TEST_DISPLAY);
assertEquals(WINDOW_MODE, currentMode);
}
@Test
public void reset_fullscreenMagnificationActivated() {
setMagnificationActivated(TEST_DISPLAY, FULLSCREEN_MODE);
mMagnificationProcessor.reset(TEST_DISPLAY, /* animate= */false);
verify(mMockFullScreenMagnificationController).reset(TEST_DISPLAY, false);
}
@Test
public void reset_windowMagnificationActivated() {
setMagnificationActivated(TEST_DISPLAY, WINDOW_MODE);
mMagnificationProcessor.reset(TEST_DISPLAY, /* animate= */false);
verify(mMockWindowMagnificationManager).reset(TEST_DISPLAY);
}
@Test
public void setMagnificationConfig_fullscreenModeNotRegistered_shouldRegister() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(FULLSCREEN_MODE)
.setScale(TEST_SCALE)
.setCenterX(TEST_CENTER_X)
.setCenterY(TEST_CENTER_Y).build();
setMagnificationActivated(TEST_DISPLAY, config);
final boolean result = mMagnificationProcessor.setMagnificationConfig(
TEST_DISPLAY, config, true, SERVICE_ID);
assertTrue(result);
verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
}
@Test
public void setMagnificationConfig_windowMode_enableMagnification() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(WINDOW_MODE)
.setScale(TEST_SCALE)
.setCenterX(TEST_CENTER_X)
.setCenterY(TEST_CENTER_Y).build();
setMagnificationActivated(TEST_DISPLAY, config);
final boolean result = mMagnificationProcessor.setMagnificationConfig(
TEST_DISPLAY, config, true, SERVICE_ID);
assertTrue(result);
}
@Test
public void setMagnificationConfig_fullscreenEnabled_expectedConfigValues() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(FULLSCREEN_MODE)
.setScale(TEST_SCALE)
.setCenterX(TEST_CENTER_X)
.setCenterY(TEST_CENTER_Y).build();
setMagnificationActivated(TEST_DISPLAY, config);
// mMockFullScreenMagnificationController.unregister(TEST_DISPLAY);
mMagnificationProcessor.setMagnificationConfig(
TEST_DISPLAY, config, true, SERVICE_ID);
final MagnificationConfig result = mMagnificationProcessor.getMagnificationConfig(
TEST_DISPLAY);
assertConfigEquals(config, result);
}
@Test
public void setMagnificationConfig_windowEnabled_expectedConfigValues() {
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(WINDOW_MODE)
.setScale(TEST_SCALE)
.setCenterX(TEST_CENTER_X)
.setCenterY(TEST_CENTER_Y).build();
setMagnificationActivated(TEST_DISPLAY, config);
mMagnificationProcessor.setMagnificationConfig(
TEST_DISPLAY, config, true, SERVICE_ID);
final MagnificationConfig result = mMagnificationProcessor.getMagnificationConfig(
TEST_DISPLAY);
assertConfigEquals(config, result);
}
private void setMagnificationActivated(int displayId, int configMode) {
setMagnificationActivated(displayId,
new MagnificationConfig.Builder().setMode(configMode).build());
}
private void setMagnificationActivated(int displayId, MagnificationConfig config) {
when(mMockMagnificationController.isActivated(displayId, config.getMode())).thenReturn(
true);
mMagnificationProcessor.setMagnificationConfig(displayId, config, false, SERVICE_ID);
if (config.getMode() == FULLSCREEN_MODE) {
when(mMockMagnificationController.isActivated(displayId, WINDOW_MODE)).thenReturn(
false);
mFullScreenMagnificationControllerStub.resetAndStubMethods();
mMockFullScreenMagnificationController.setScaleAndCenter(displayId, config.getScale(),
config.getCenterX(), config.getCenterY(), true, SERVICE_ID);
} else if (config.getMode() == WINDOW_MODE) {
when(mMockMagnificationController.isActivated(displayId, FULLSCREEN_MODE)).thenReturn(
false);
mWindowMagnificationManagerStub.resetAndStubMethods();
mMockWindowMagnificationManager.enableWindowMagnification(displayId, config.getScale(),
config.getCenterX(), config.getCenterY());
}
}
private void assertConfigEquals(MagnificationConfig expected, MagnificationConfig actual) {
assertEquals(expected.getMode(), actual.getMode());
assertEquals(expected.getScale(), actual.getScale(), 0);
assertEquals(expected.getCenterX(), actual.getCenterX(), 0);
assertEquals(expected.getCenterY(), actual.getCenterY(), 0);
}
private static class FullScreenMagnificationControllerStub {
private final FullScreenMagnificationController mScreenMagnificationController;
private float mScale = 1.0f;
private float mCenterX = 0;
private float mCenterY = 0;
private boolean mIsRegistered = false;
FullScreenMagnificationControllerStub(
FullScreenMagnificationController screenMagnificationController) {
mScreenMagnificationController = screenMagnificationController;
}
private void stubMethods() {
doAnswer(invocation -> mScale).when(mScreenMagnificationController).getScale(
TEST_DISPLAY);
doAnswer(invocation -> mCenterX).when(mScreenMagnificationController).getCenterX(
TEST_DISPLAY);
doAnswer(invocation -> mCenterY).when(mScreenMagnificationController).getCenterY(
TEST_DISPLAY);
doAnswer(invocation -> mIsRegistered).when(mScreenMagnificationController).isRegistered(
TEST_DISPLAY);
Answer enableMagnificationStubAnswer = invocation -> {
mScale = invocation.getArgument(1);
mCenterX = invocation.getArgument(2);
mCenterY = invocation.getArgument(3);
return true;
};
doAnswer(enableMagnificationStubAnswer).when(
mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), anyFloat(),
anyFloat(), anyFloat(), eq(true), eq(SERVICE_ID));
Answer registerStubAnswer = invocation -> {
mIsRegistered = true;
return true;
};
doAnswer(registerStubAnswer).when(
mScreenMagnificationController).register(eq(TEST_DISPLAY));
Answer unregisterStubAnswer = invocation -> {
mIsRegistered = false;
return true;
};
doAnswer(unregisterStubAnswer).when(
mScreenMagnificationController).unregister(eq(TEST_DISPLAY));
}
public void resetAndStubMethods() {
Mockito.reset(mScreenMagnificationController);
stubMethods();
}
}
private static class WindowMagnificationManagerStub {
private final WindowMagnificationManager mWindowMagnificationManager;
private float mScale = 1.0f;
private float mCenterX = 0;
private float mCenterY = 0;
WindowMagnificationManagerStub(
WindowMagnificationManager windowMagnificationManager) {
mWindowMagnificationManager = windowMagnificationManager;
}
private void stubMethods() {
doAnswer(invocation -> mScale).when(mWindowMagnificationManager).getScale(
TEST_DISPLAY);
doAnswer(invocation -> mCenterX).when(mWindowMagnificationManager).getCenterX(
TEST_DISPLAY);
doAnswer(invocation -> mCenterY).when(mWindowMagnificationManager).getCenterY(
TEST_DISPLAY);
Answer enableWindowMagnificationStubAnswer = invocation -> {
mScale = invocation.getArgument(1);
mCenterX = invocation.getArgument(2);
mCenterY = invocation.getArgument(3);
return true;
};
doAnswer(enableWindowMagnificationStubAnswer).when(
mWindowMagnificationManager).enableWindowMagnification(eq(TEST_DISPLAY),
anyFloat(), anyFloat(), anyFloat());
}
public void resetAndStubMethods() {
Mockito.reset(mWindowMagnificationManager);
stubMethods();
}
}
}

View File

@@ -376,6 +376,17 @@ public class WindowMagnificationManagerTest {
verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
}
@Test
public void resetMagnification_enabled_windowMagnifierDisabled() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN);
assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY));
mWindowMagnificationManager.reset(TEST_DISPLAY);
assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY));
}
@Test
public void onScreenOff_windowMagnifierIsEnabled_removeButtonAndDisableWindowMagnification()
throws RemoteException {