Merge "Adds public APIs for AccessibilityService to control magnifier by setting MagnificationConfig"

This commit is contained in:
Minche Li
2021-12-06 14:45:51 +00:00
committed by Android (Google) Code Review
9 changed files with 119 additions and 35 deletions

View File

@@ -3123,11 +3123,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);
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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() {