Adds public APIs for AccessibilityService to control magnifier by setting MagnificationConfig
See go/b200769372
AccessibilityService adds new magnificationController APIs,
setMagnificationConfig and getMagnificationConfig, to control
magnification on demand.
The service can set the magnification mode, scale, center postion
of the magnifier on the display to control magnification.
And the service controls the least recently activated magnifier
on the display if the config mode is not specified.
Bug: 199732498
Test: atest MagnificationProcessorTest,
atest AbstractAccessibilityServiceConnectionTest,
atest AccessibilityMagnificationTest,
Change-Id: I51be2bbf96411c6c54c9da30873556d09533bb65
This commit is contained in:
@@ -3121,11 +3121,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 @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 setCenter(float, float, boolean);
|
||||
method public boolean setMagnificationConfig(@NonNull android.accessibilityservice.MagnificationConfig, boolean);
|
||||
method public boolean setScale(float, boolean);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.accessibilityservice;
|
||||
|
||||
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
|
||||
|
||||
import android.accessibilityservice.GestureDescription.MotionEventGenerator;
|
||||
@@ -1358,6 +1359,32 @@ public abstract class AccessibilityService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link MagnificationConfig} of the controlling magnifier on the display.
|
||||
* <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 null.
|
||||
* </p>
|
||||
*
|
||||
* @return the magnification config that the service controls
|
||||
*/
|
||||
public @Nullable MagnificationConfig getMagnificationConfig() {
|
||||
final IAccessibilityServiceConnection connection =
|
||||
AccessibilityInteractionClient.getInstance(mService).getConnection(
|
||||
mService.mConnectionId);
|
||||
if (connection != null) {
|
||||
try {
|
||||
return connection.getMagnificationConfig(mDisplayId);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(LOG_TAG, "Failed to obtain magnification config", re);
|
||||
re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current magnification scale.
|
||||
* <p>
|
||||
@@ -1504,6 +1531,37 @@ public abstract class AccessibilityService extends Service {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link MagnificationConfig}. The service controls the magnification by
|
||||
* setting the config.
|
||||
* <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 config the magnification config
|
||||
* @param animate {@code true} to animate from the current spec or
|
||||
* {@code false} to set the spec immediately
|
||||
* @return {@code true} on success, {@code false} on failure
|
||||
*/
|
||||
public boolean setMagnificationConfig(@NonNull MagnificationConfig config,
|
||||
boolean animate) {
|
||||
final IAccessibilityServiceConnection connection =
|
||||
AccessibilityInteractionClient.getInstance(mService).getConnection(
|
||||
mService.mConnectionId);
|
||||
if (connection != null) {
|
||||
try {
|
||||
return connection.setMagnificationConfig(mDisplayId, config, animate);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(LOG_TAG, "Failed to set magnification config", re);
|
||||
re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the magnification scale.
|
||||
* <p>
|
||||
@@ -1523,8 +1581,10 @@ public abstract class AccessibilityService extends Service {
|
||||
mService.mConnectionId);
|
||||
if (connection != null) {
|
||||
try {
|
||||
return connection.setMagnificationScaleAndCenter(mDisplayId,
|
||||
scale, Float.NaN, Float.NaN, animate);
|
||||
final MagnificationConfig config = new MagnificationConfig.Builder()
|
||||
.setMode(MAGNIFICATION_MODE_FULLSCREEN)
|
||||
.setScale(scale).build();
|
||||
return connection.setMagnificationConfig(mDisplayId, config, animate);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(LOG_TAG, "Failed to set scale", re);
|
||||
re.rethrowFromSystemServer();
|
||||
@@ -1555,8 +1615,10 @@ public abstract class AccessibilityService extends Service {
|
||||
mService.mConnectionId);
|
||||
if (connection != null) {
|
||||
try {
|
||||
return connection.setMagnificationScaleAndCenter(mDisplayId,
|
||||
Float.NaN, centerX, centerY, animate);
|
||||
final MagnificationConfig config = new MagnificationConfig.Builder()
|
||||
.setMode(MAGNIFICATION_MODE_FULLSCREEN)
|
||||
.setCenterX(centerX).setCenterY(centerY).build();
|
||||
return connection.setMagnificationConfig(mDisplayId, config, animate);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(LOG_TAG, "Failed to set center", re);
|
||||
re.rethrowFromSystemServer();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.accessibilityservice;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.accessibilityservice.MagnificationConfig;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Region;
|
||||
@@ -77,6 +78,8 @@ interface IAccessibilityServiceConnection {
|
||||
|
||||
oneway void setOnKeyEventResult(boolean handled, int sequence);
|
||||
|
||||
MagnificationConfig getMagnificationConfig(int displayId);
|
||||
|
||||
float getMagnificationScale(int displayId);
|
||||
|
||||
float getMagnificationCenterX(int displayId);
|
||||
@@ -87,8 +90,7 @@ interface IAccessibilityServiceConnection {
|
||||
|
||||
boolean resetMagnification(int displayId, boolean animate);
|
||||
|
||||
boolean setMagnificationScaleAndCenter(int displayId, float scale, float centerX, float centerY,
|
||||
boolean animate);
|
||||
boolean setMagnificationConfig(int displayId, in MagnificationConfig config, boolean animate);
|
||||
|
||||
void setMagnificationCallbackEnabled(int displayId, boolean enabled);
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package android.view.accessibility;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.accessibilityservice.IAccessibilityServiceConnection;
|
||||
import android.accessibilityservice.MagnificationConfig;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.graphics.Region;
|
||||
import android.os.Bundle;
|
||||
@@ -97,6 +99,10 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
|
||||
|
||||
public void setOnKeyEventResult(boolean handled, int sequence) {}
|
||||
|
||||
public MagnificationConfig getMagnificationConfig(int displayId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public float getMagnificationScale(int displayId) {
|
||||
return 0.0f;
|
||||
}
|
||||
@@ -117,8 +123,8 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setMagnificationScaleAndCenter(int displayId, float scale, float centerX,
|
||||
float centerY, boolean animate) {
|
||||
public boolean setMagnificationConfig(int displayId,
|
||||
@NonNull MagnificationConfig config, boolean animate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -976,6 +976,25 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MagnificationConfig getMagnificationConfig(int displayId) {
|
||||
if (svcConnTracingEnabled()) {
|
||||
logTraceSvcConn("getMagnificationConfig", "displayId=" + displayId);
|
||||
}
|
||||
synchronized (mLock) {
|
||||
if (!hasRightsToCurrentUserLocked()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSystemSupport.getMagnificationProcessor().getMagnificationConfig(displayId);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMagnificationScale(int displayId) {
|
||||
if (svcConnTracingEnabled()) {
|
||||
@@ -1084,12 +1103,11 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMagnificationScaleAndCenter(int displayId, float scale, float centerX,
|
||||
float centerY, boolean animate) {
|
||||
public boolean setMagnificationConfig(int displayId,
|
||||
@NonNull MagnificationConfig config, boolean animate) {
|
||||
if (svcConnTracingEnabled()) {
|
||||
logTraceSvcConn("setMagnificationScaleAndCenter",
|
||||
"displayId=" + displayId + ";scale=" + scale + ";centerX=" + centerX
|
||||
+ ";centerY=" + centerY + ";animate=" + animate);
|
||||
logTraceSvcConn("setMagnificationSpec",
|
||||
"displayId=" + displayId + ", config=" + config.toString());
|
||||
}
|
||||
synchronized (mLock) {
|
||||
if (!hasRightsToCurrentUserLocked()) {
|
||||
@@ -1102,10 +1120,6 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
try {
|
||||
MagnificationProcessor magnificationProcessor =
|
||||
mSystemSupport.getMagnificationProcessor();
|
||||
final MagnificationConfig config = new MagnificationConfig.Builder()
|
||||
.setScale(scale)
|
||||
.setCenterX(centerX)
|
||||
.setCenterY(centerY).build();
|
||||
return magnificationProcessor.setMagnificationConfig(displayId, config, animate,
|
||||
mId);
|
||||
} finally {
|
||||
|
||||
@@ -681,7 +681,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
|
||||
} else {
|
||||
getWindowMagnificationMgr().enableWindowMagnification(mDisplayId,
|
||||
mCurrentScale, mCurrentCenter.x,
|
||||
mCurrentCenter.y);
|
||||
mCurrentCenter.y, mAnimate ? STUB_ANIMATION_CALLBACK : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MOD
|
||||
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_WINDOW;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
|
||||
import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;
|
||||
|
||||
import android.accessibilityservice.MagnificationConfig;
|
||||
import android.annotation.NonNull;
|
||||
@@ -112,7 +113,8 @@ public class MagnificationProcessor {
|
||||
animate, id);
|
||||
} else if (configMode == MAGNIFICATION_MODE_WINDOW) {
|
||||
return mController.getWindowMagnificationMgr().enableWindowMagnification(displayId,
|
||||
config.getScale(), config.getCenterX(), config.getCenterY());
|
||||
config.getScale(), config.getCenterX(), config.getCenterY(),
|
||||
animate ? STUB_ANIMATION_CALLBACK : null);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -646,7 +647,7 @@ public class AbstractAccessibilityServiceConnectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMagnificationScaleAndCenter_cantControlMagnification_returnFalse() {
|
||||
public void setMagnificationConfig_cantControlMagnification_returnFalse() {
|
||||
final int displayId = 1;
|
||||
final float scale = 1.8f;
|
||||
final float centerX = 50.5f;
|
||||
@@ -659,13 +660,12 @@ public class AbstractAccessibilityServiceConnectionTest {
|
||||
SERVICE_ID)).thenReturn(true);
|
||||
when(mMockSecurityPolicy.canControlMagnification(mServiceConnection)).thenReturn(false);
|
||||
|
||||
final boolean result = mServiceConnection.setMagnificationScaleAndCenter(
|
||||
displayId, scale, centerX, centerY, true);
|
||||
assertThat(result, is(false));
|
||||
final boolean result = mServiceConnection.setMagnificationConfig(displayId, config, true);
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMagnificationScaleAndCenter_serviceNotBelongCurrentUser_returnFalse() {
|
||||
public void setMagnificationConfig_serviceNotBelongCurrentUser_returnFalse() {
|
||||
final int displayId = 1;
|
||||
final float scale = 1.8f;
|
||||
final float centerX = 50.5f;
|
||||
@@ -678,9 +678,8 @@ public class AbstractAccessibilityServiceConnectionTest {
|
||||
SERVICE_ID)).thenReturn(true);
|
||||
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
|
||||
|
||||
final boolean result = mServiceConnection.setMagnificationScaleAndCenter(
|
||||
displayId, scale, centerX, centerY, true);
|
||||
assertThat(result, is(false));
|
||||
final boolean result = mServiceConnection.setMagnificationConfig(displayId, config, true);
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test (expected = SecurityException.class)
|
||||
|
||||
@@ -282,16 +282,13 @@ public class MagnificationProcessorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMagnificationConfig_fullscreenEnabled_expectedConfigValues() {
|
||||
public void getMagnificationConfig_fullscreenEnabled_expectedConfigValues() {
|
||||
final MagnificationConfig config = new MagnificationConfig.Builder()
|
||||
.setMode(MAGNIFICATION_MODE_FULLSCREEN)
|
||||
.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);
|
||||
@@ -300,7 +297,7 @@ public class MagnificationProcessorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMagnificationConfig_windowEnabled_expectedConfigValues() {
|
||||
public void getMagnificationConfig_windowEnabled_expectedConfigValues() {
|
||||
final MagnificationConfig config = new MagnificationConfig.Builder()
|
||||
.setMode(MAGNIFICATION_MODE_WINDOW)
|
||||
.setScale(TEST_SCALE)
|
||||
@@ -308,9 +305,6 @@ public class MagnificationProcessorTest {
|
||||
.setCenterY(TEST_CENTER_Y).build();
|
||||
setMagnificationActivated(TEST_DISPLAY, config);
|
||||
|
||||
mMagnificationProcessor.setMagnificationConfig(
|
||||
TEST_DISPLAY, config, true, SERVICE_ID);
|
||||
|
||||
final MagnificationConfig result = mMagnificationProcessor.getMagnificationConfig(
|
||||
TEST_DISPLAY);
|
||||
|
||||
@@ -455,6 +449,9 @@ public class MagnificationProcessorTest {
|
||||
doAnswer(enableWindowMagnificationStubAnswer).when(
|
||||
mWindowMagnificationManager).enableWindowMagnification(eq(TEST_DISPLAY),
|
||||
anyFloat(), anyFloat(), anyFloat());
|
||||
doAnswer(enableWindowMagnificationStubAnswer).when(
|
||||
mWindowMagnificationManager).enableWindowMagnification(eq(TEST_DISPLAY),
|
||||
anyFloat(), anyFloat(), anyFloat(), any());
|
||||
}
|
||||
|
||||
public void resetAndStubMethods() {
|
||||
|
||||
Reference in New Issue
Block a user