Merge "Adds new magnificationController API: getCurrentMagnificationRegion, resetCurrentMagnification"

This commit is contained in:
Minche Li
2022-01-07 01:05:32 +00:00
committed by Android (Google) Code Review
8 changed files with 223 additions and 4 deletions

View File

@@ -3131,11 +3131,13 @@ package android.accessibilityservice {
method public void addListener(@NonNull android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener, @Nullable android.os.Handler);
method public float getCenterX();
method public float getCenterY();
method @NonNull public android.graphics.Region getCurrentMagnificationRegion();
method @Nullable public android.accessibilityservice.MagnificationConfig getMagnificationConfig();
method @NonNull public android.graphics.Region getMagnificationRegion();
method public float getScale();
method public boolean removeListener(@NonNull android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener);
method public boolean reset(boolean);
method public boolean resetCurrentMagnification(boolean);
method public boolean setCenter(float, float, boolean);
method public boolean setMagnificationConfig(@NonNull android.accessibilityservice.MagnificationConfig, boolean);
method public boolean setScale(float, boolean);

View File

@@ -1500,6 +1500,12 @@ public abstract class AccessibilityService extends Service {
* {@link AccessibilityService#onServiceConnected()} has not yet been
* called) or the service has been disconnected, this method will
* return an empty region.
* </p>
* <p>
* <strong>Note:</strong> This legacy API gets the magnification region of full-screen
* magnification. To get the magnification region of the current controlling magnifier,
* use {@link #getCurrentMagnificationRegion()} instead.
* </p>
*
* @return the region of the screen currently active for magnification, or an empty region
* if magnification is not active.
@@ -1520,6 +1526,45 @@ public abstract class AccessibilityService extends Service {
return Region.obtain();
}
/**
* Returns the region of the screen currently active for magnification if the
* controlling magnification is {@link MagnificationConfig#MAGNIFICATION_MODE_FULLSCREEN}.
* Returns the region of screen projected on the magnification window if the
* controlling magnification is {@link MagnificationConfig#MAGNIFICATION_MODE_WINDOW}.
*
* <p>
* If the controlling mode is {@link MagnificationConfig#MAGNIFICATION_MODE_FULLSCREEN},
* the returned region will be empty if the magnification is
* not active. And the magnification is active if magnification gestures are enabled
* or if a service is running that can control magnification.
* </p><p>
* If the controlling mode is {@link MagnificationConfig#MAGNIFICATION_MODE_WINDOW},
* the returned region will be empty if the magnification is not activated.
* </p><p>
* <strong>Note:</strong> If the service is not yet connected (e.g.
* {@link AccessibilityService#onServiceConnected()} has not yet been
* called) or the service has been disconnected, this method will
* return an empty region.
* </p>
*
* @return the magnification region of the currently controlling magnification
*/
@NonNull
public Region getCurrentMagnificationRegion() {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
return connection.getCurrentMagnificationRegion(mDisplayId);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to obtain the current magnified region", re);
re.rethrowFromSystemServer();
}
}
return Region.obtain();
}
/**
* Resets magnification scale and center to their default (e.g. no
* magnification) values.
@@ -1528,6 +1573,11 @@ public abstract class AccessibilityService extends Service {
* {@link AccessibilityService#onServiceConnected()} has not yet been
* called) or the service has been disconnected, this method will have
* no effect and return {@code false}.
* <p>
* <strong>Note:</strong> This legacy API reset full-screen magnification.
* To reset the current controlling magnifier, use
* {@link #resetCurrentMagnification(boolean)} ()} instead.
* </p>
*
* @param animate {@code true} to animate from the current scale and
* center or {@code false} to reset the scale and center
@@ -1549,6 +1599,36 @@ public abstract class AccessibilityService extends Service {
return false;
}
/**
* Resets magnification scale and center of the controlling magnification
* to their default (e.g. no magnification) values.
* <p>
* <strong>Note:</strong> If the service is not yet connected (e.g.
* {@link AccessibilityService#onServiceConnected()} has not yet been
* called) or the service has been disconnected, this method will have
* no effect and return {@code false}.
* </p>
*
* @param animate {@code true} to animate from the current scale and
* center or {@code false} to reset the scale and center
* immediately
* @return {@code true} on success, {@code false} on failure
*/
public boolean resetCurrentMagnification(boolean animate) {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance(mService).getConnection(
mService.mConnectionId);
if (connection != null) {
try {
return connection.resetCurrentMagnification(mDisplayId, animate);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to reset", re);
re.rethrowFromSystemServer();
}
}
return false;
}
/**
* Sets the {@link MagnificationConfig}. The service controls the magnification by
* setting the config.

View File

@@ -88,8 +88,12 @@ interface IAccessibilityServiceConnection {
Region getMagnificationRegion(int displayId);
Region getCurrentMagnificationRegion(int displayId);
boolean resetMagnification(int displayId, boolean animate);
boolean resetCurrentMagnification(int displayId, boolean animate);
boolean setMagnificationConfig(int displayId, in MagnificationConfig config, boolean animate);
void setMagnificationCallbackEnabled(int displayId, boolean enabled);

View File

@@ -120,10 +120,18 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
return null;
}
public Region getCurrentMagnificationRegion(int displayId) {
return null;
}
public boolean resetMagnification(int displayId, boolean animate) {
return false;
}
public boolean resetCurrentMagnification(int displayId, boolean animate) {
return false;
}
public boolean setMagnificationConfig(int displayId,
@NonNull MagnificationConfig config, boolean animate) {
return false;

View File

@@ -1036,6 +1036,30 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
}
}
@Override
public Region getCurrentMagnificationRegion(int displayId) {
if (svcConnTracingEnabled()) {
logTraceSvcConn("getCurrentMagnificationRegion", "displayId=" + displayId);
}
synchronized (mLock) {
final Region region = Region.obtain();
if (!hasRightsToCurrentUserLocked()) {
return region;
}
MagnificationProcessor magnificationProcessor =
mSystemSupport.getMagnificationProcessor();
final long identity = Binder.clearCallingIdentity();
try {
magnificationProcessor.getCurrentMagnificationRegion(displayId,
region, mSecurityPolicy.canControlMagnification(this));
return region;
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
@Override
public float getMagnificationCenterX(int displayId) {
if (svcConnTracingEnabled()) {
@@ -1102,6 +1126,31 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
}
}
@Override
public boolean resetCurrentMagnification(int displayId, boolean animate) {
if (svcConnTracingEnabled()) {
logTraceSvcConn("resetCurrentMagnification",
"displayId=" + displayId + ";animate=" + animate);
}
synchronized (mLock) {
if (!hasRightsToCurrentUserLocked()) {
return false;
}
if (!mSecurityPolicy.canControlMagnification(this)) {
return false;
}
}
final long identity = Binder.clearCallingIdentity();
try {
MagnificationProcessor magnificationProcessor =
mSystemSupport.getMagnificationProcessor();
return (magnificationProcessor.resetCurrentMagnification(displayId, animate)
|| !magnificationProcessor.isMagnifying(displayId));
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public boolean setMagnificationConfig(int displayId,
@NonNull MagnificationConfig config, boolean animate) {

View File

@@ -202,6 +202,36 @@ public class MagnificationProcessor {
}
}
/**
* Returns the region of the screen currently active for magnification if the
* controlling magnification is {@link MagnificationConfig#MAGNIFICATION_MODE_FULLSCREEN}.
* Returns the region of screen projected on the magnification window if the controlling
* magnification is {@link MagnificationConfig#MAGNIFICATION_MODE_WINDOW}.
* <p>
* If the controlling mode is {@link MagnificationConfig#MAGNIFICATION_MODE_FULLSCREEN},
* the returned region will be empty if the magnification is
* not active. And the magnification is active if magnification gestures are enabled
* or if a service is running that can control magnification.
* </p><p>
* If the controlling mode is {@link MagnificationConfig#MAGNIFICATION_MODE_WINDOW},
* the returned region will be empty if the magnification is not activated.
* </p>
*
* @param displayId The logical display id
* @param outRegion the region to populate
* @param canControlMagnification Whether the service can control magnification
*/
public void getCurrentMagnificationRegion(int displayId, @NonNull Region outRegion,
boolean canControlMagnification) {
int currentMode = getControllingMode(displayId);
if (currentMode == MAGNIFICATION_MODE_FULLSCREEN) {
getFullscreenMagnificationRegion(displayId, outRegion, canControlMagnification);
} else if (currentMode == MAGNIFICATION_MODE_WINDOW) {
mController.getWindowMagnificationMgr().getMagnificationSourceBounds(displayId,
outRegion);
}
}
/**
* Returns the magnification bounds of full-screen magnification on the given display.
*
@@ -224,8 +254,8 @@ public class MagnificationProcessor {
}
/**
* Resets the current magnification on the given display. The reset mode could be
* full-screen or window if it is activated.
* Resets the controlling magnifier on the given display.
* For resetting window magnifier, it disables the magnifier by setting the scale to 1.
*
* @param displayId The logical display id.
* @param animate {@code true} to animate the transition, {@code false}

View File

@@ -594,6 +594,20 @@ public class AbstractAccessibilityServiceConnectionTest {
assertThat(result.isEmpty(), is(true));
}
@Test
public void getCurrentMagnificationRegion_returnRegion() {
final int displayId = 1;
final Region region = new Region(10, 20, 100, 200);
doAnswer((invocation) -> {
((Region) invocation.getArguments()[1]).set(region);
return null;
}).when(mMockMagnificationProcessor).getCurrentMagnificationRegion(eq(displayId), any(),
anyBoolean());
final Region result = mServiceConnection.getCurrentMagnificationRegion(displayId);
assertEquals(result, region);
}
@Test
public void getMagnificationCenterX_serviceNotBelongCurrentUser_returnZero() {
final int displayId = 1;

View File

@@ -183,6 +183,38 @@ public class MagnificationProcessorTest {
verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
}
@Test
public void getCurrentMagnificationRegion_windowModeActivated_returnRegion() {
final Region region = new Region(10, 20, 100, 200);
setMagnificationActivated(TEST_DISPLAY, MAGNIFICATION_MODE_WINDOW);
doAnswer((invocation) -> {
((Region) invocation.getArguments()[1]).set(region);
return null;
}).when(mMockWindowMagnificationManager).getMagnificationSourceBounds(eq(TEST_DISPLAY),
any());
final Region result = new Region();
mMagnificationProcessor.getCurrentMagnificationRegion(TEST_DISPLAY,
result, /* canControlMagnification= */true);
assertEquals(region, result);
}
@Test
public void getCurrentMagnificationRegion_fullscreenModeActivated_returnRegion() {
final Region region = new Region(10, 20, 100, 200);
setMagnificationActivated(TEST_DISPLAY, MAGNIFICATION_MODE_FULLSCREEN);
doAnswer((invocation) -> {
((Region) invocation.getArguments()[1]).set(region);
return null;
}).when(mMockFullScreenMagnificationController).getMagnificationRegion(eq(TEST_DISPLAY),
any());
final Region result = new Region();
mMagnificationProcessor.getCurrentMagnificationRegion(TEST_DISPLAY,
result, /* canControlMagnification= */true);
assertEquals(region, result);
}
@Test
public void getMagnificationCenterX_fullscreenModeNotRegistered_shouldRegisterThenUnregister() {
final MagnificationConfig config = new MagnificationConfig.Builder()
@@ -222,7 +254,7 @@ public class MagnificationProcessorTest {
}
@Test
public void reset_fullscreenMagnificationActivated() {
public void resetFullscreenMagnification_fullscreenMagnificationActivated() {
setMagnificationActivated(TEST_DISPLAY, MAGNIFICATION_MODE_FULLSCREEN);
mMagnificationProcessor.resetFullscreenMagnification(TEST_DISPLAY, /* animate= */false);
@@ -231,7 +263,7 @@ public class MagnificationProcessorTest {
}
@Test
public void reset_windowMagnificationActivated() {
public void resetCurrentMagnification_windowMagnificationActivated() {
setMagnificationActivated(TEST_DISPLAY, MAGNIFICATION_MODE_WINDOW);
mMagnificationProcessor.resetCurrentMagnification(TEST_DISPLAY, /* animate= */false);