Merge "Notifies window magnifcation changes for AccessibilityService (1/n)"
This commit is contained in:
@@ -3143,6 +3143,7 @@ package android.accessibilityservice {
|
||||
|
||||
public static interface AccessibilityService.MagnificationController.OnMagnificationChangedListener {
|
||||
method public void onMagnificationChanged(@NonNull android.accessibilityservice.AccessibilityService.MagnificationController, @NonNull android.graphics.Region, float, float, float);
|
||||
method public default void onMagnificationChanged(@NonNull android.accessibilityservice.AccessibilityService.MagnificationController, @NonNull android.graphics.Region, @NonNull android.accessibilityservice.MagnificationConfig);
|
||||
}
|
||||
|
||||
public static final class AccessibilityService.ScreenshotResult {
|
||||
|
||||
@@ -588,7 +588,7 @@ public abstract class AccessibilityService extends Service {
|
||||
boolean onKeyEvent(KeyEvent event);
|
||||
/** Magnification changed callbacks for different displays */
|
||||
void onMagnificationChanged(int displayId, @NonNull Region region,
|
||||
float scale, float centerX, float centerY);
|
||||
MagnificationConfig config);
|
||||
/** Callbacks for receiving motion events. */
|
||||
void onMotionEvent(MotionEvent event);
|
||||
/** Callback for tuch state changes. */
|
||||
@@ -1183,14 +1183,14 @@ public abstract class AccessibilityService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
private void onMagnificationChanged(int displayId, @NonNull Region region, float scale,
|
||||
float centerX, float centerY) {
|
||||
private void onMagnificationChanged(int displayId, @NonNull Region region,
|
||||
MagnificationConfig config) {
|
||||
MagnificationController controller;
|
||||
synchronized (mLock) {
|
||||
controller = mMagnificationControllers.get(displayId);
|
||||
}
|
||||
if (controller != null) {
|
||||
controller.dispatchMagnificationChanged(region, scale, centerX, centerY);
|
||||
controller.dispatchMagnificationChanged(region, config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1328,8 +1328,8 @@ public abstract class AccessibilityService extends Service {
|
||||
* Dispatches magnification changes to any registered listeners. This
|
||||
* should be called on the service's main thread.
|
||||
*/
|
||||
void dispatchMagnificationChanged(final @NonNull Region region, final float scale,
|
||||
final float centerX, final float centerY) {
|
||||
void dispatchMagnificationChanged(final @NonNull Region region,
|
||||
final MagnificationConfig config) {
|
||||
final ArrayMap<OnMagnificationChangedListener, Handler> entries;
|
||||
synchronized (mLock) {
|
||||
if (mListeners == null || mListeners.isEmpty()) {
|
||||
@@ -1348,16 +1348,13 @@ public abstract class AccessibilityService extends Service {
|
||||
final OnMagnificationChangedListener listener = entries.keyAt(i);
|
||||
final Handler handler = entries.valueAt(i);
|
||||
if (handler != null) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onMagnificationChanged(MagnificationController.this,
|
||||
region, scale, centerX, centerY);
|
||||
}
|
||||
handler.post(() -> {
|
||||
listener.onMagnificationChanged(MagnificationController.this,
|
||||
region, config);
|
||||
});
|
||||
} else {
|
||||
// We're already on the main thread, just run the listener.
|
||||
listener.onMagnificationChanged(this, region, scale, centerX, centerY);
|
||||
listener.onMagnificationChanged(this, region, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1665,6 +1662,10 @@ public abstract class AccessibilityService extends Service {
|
||||
public interface OnMagnificationChangedListener {
|
||||
/**
|
||||
* Called when the magnified region, scale, or center changes.
|
||||
* <p>
|
||||
* <strong>Note:</strong> This legacy callback notifies only full-screen
|
||||
* magnification change.
|
||||
* </p>
|
||||
*
|
||||
* @param controller the magnification controller
|
||||
* @param region the magnification region
|
||||
@@ -1676,6 +1677,38 @@ public abstract class AccessibilityService extends Service {
|
||||
*/
|
||||
void onMagnificationChanged(@NonNull MagnificationController controller,
|
||||
@NonNull Region region, float scale, float centerX, float centerY);
|
||||
|
||||
/**
|
||||
* Called when the magnified region, mode, scale, or center changes of
|
||||
* all magnification modes.
|
||||
* <p>
|
||||
* <strong>Note:</strong> This method can be overridden to listen to the
|
||||
* magnification changes of all magnification modes then the legacy callback
|
||||
* would not receive the notifications.
|
||||
* Skipping calling super when overriding this method results in
|
||||
* {@link #onMagnificationChanged(MagnificationController, Region, float, float, float)}
|
||||
* not getting called.
|
||||
* </p>
|
||||
*
|
||||
* @param controller the magnification controller
|
||||
* @param region the magnification region
|
||||
* If the config mode is
|
||||
* {@link MagnificationConfig#MAGNIFICATION_MODE_FULLSCREEN},
|
||||
* it is the region of the screen currently active for magnification.
|
||||
* that is the same region as {@link #getMagnificationRegion()}.
|
||||
* If the config mode is
|
||||
* {@link MagnificationConfig#MAGNIFICATION_MODE_WINDOW},
|
||||
* it is the region of screen projected on the magnification window.
|
||||
* @param config The magnification config. That has the controlling magnification
|
||||
* mode, the new scale and the new screen-relative center position
|
||||
*/
|
||||
default void onMagnificationChanged(@NonNull MagnificationController controller,
|
||||
@NonNull Region region, @NonNull MagnificationConfig config) {
|
||||
if (config.getMode() == MAGNIFICATION_MODE_FULLSCREEN) {
|
||||
onMagnificationChanged(controller, region,
|
||||
config.getScale(), config.getCenterX(), config.getCenterY());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2449,9 +2482,8 @@ public abstract class AccessibilityService extends Service {
|
||||
|
||||
@Override
|
||||
public void onMagnificationChanged(int displayId, @NonNull Region region,
|
||||
float scale, float centerX, float centerY) {
|
||||
AccessibilityService.this.onMagnificationChanged(displayId, region, scale,
|
||||
centerX, centerY);
|
||||
MagnificationConfig config) {
|
||||
AccessibilityService.this.onMagnificationChanged(displayId, region, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2575,12 +2607,10 @@ public abstract class AccessibilityService extends Service {
|
||||
|
||||
/** Magnification changed callbacks for different displays */
|
||||
public void onMagnificationChanged(int displayId, @NonNull Region region,
|
||||
float scale, float centerX, float centerY) {
|
||||
MagnificationConfig config) {
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = region;
|
||||
args.arg2 = scale;
|
||||
args.arg3 = centerX;
|
||||
args.arg4 = centerY;
|
||||
args.arg2 = config;
|
||||
args.argi1 = displayId;
|
||||
|
||||
final Message message = mCaller.obtainMessageO(DO_ON_MAGNIFICATION_CHANGED, args);
|
||||
@@ -2739,13 +2769,10 @@ public abstract class AccessibilityService extends Service {
|
||||
if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
|
||||
final SomeArgs args = (SomeArgs) message.obj;
|
||||
final Region region = (Region) args.arg1;
|
||||
final float scale = (float) args.arg2;
|
||||
final float centerX = (float) args.arg3;
|
||||
final float centerY = (float) args.arg4;
|
||||
final MagnificationConfig config = (MagnificationConfig) args.arg2;
|
||||
final int displayId = args.argi1;
|
||||
args.recycle();
|
||||
mCallback.onMagnificationChanged(displayId, region, scale,
|
||||
centerX, centerY);
|
||||
mCallback.onMagnificationChanged(displayId, region, config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.graphics.Region;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityWindowInfo;
|
||||
import android.accessibilityservice.AccessibilityGestureEvent;
|
||||
import android.accessibilityservice.MagnificationConfig;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
@@ -43,7 +44,7 @@ import android.view.MotionEvent;
|
||||
|
||||
void onKeyEvent(in KeyEvent event, int sequence);
|
||||
|
||||
void onMagnificationChanged(int displayId, in Region region, float scale, float centerX, float centerY);
|
||||
void onMagnificationChanged(int displayId, in Region region, in MagnificationConfig config);
|
||||
|
||||
void onMotionEvent(in MotionEvent event);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.accessibilityservice.AccessibilityService.IAccessibilityServiceCl
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.accessibilityservice.IAccessibilityServiceClient;
|
||||
import android.accessibilityservice.IAccessibilityServiceConnection;
|
||||
import android.accessibilityservice.MagnificationConfig;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -1581,7 +1582,7 @@ public final class UiAutomation {
|
||||
|
||||
@Override
|
||||
public void onMagnificationChanged(int displayId, @NonNull Region region,
|
||||
float scale, float centerX, float centerY) {
|
||||
MagnificationConfig config) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
|
||||
@@ -252,7 +252,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
mMagnificationFrame.height());
|
||||
mTransaction.setGeometry(mMirrorSurface, mSourceBounds, mTmpRect,
|
||||
Surface.ROTATION_0).apply();
|
||||
mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, mSourceBounds);
|
||||
|
||||
// Notify source bounds change when the magnifier is not animating.
|
||||
if (!mAnimationController.isAnimating()) {
|
||||
mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId,
|
||||
mSourceBounds);
|
||||
}
|
||||
}
|
||||
};
|
||||
mUpdateStateDescriptionRunnable = () -> {
|
||||
@@ -596,7 +601,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
private void modifyWindowMagnification(SurfaceControl.Transaction t) {
|
||||
mSfVsyncFrameProvider.postFrameCallback(mMirrorViewGeometryVsyncCallback);
|
||||
updateMirrorViewLayout();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -800,7 +804,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
* are as same as current values, or the transition is interrupted
|
||||
* due to the new transition request.
|
||||
*/
|
||||
void enableWindowMagnification(float scale, float centerX, float centerY,
|
||||
public void enableWindowMagnification(float scale, float centerX, float centerY,
|
||||
float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
|
||||
@Nullable IRemoteMagnificationAnimationCallback animationCallback) {
|
||||
mAnimationController.enableWindowMagnification(scale, centerX, centerY,
|
||||
|
||||
@@ -34,6 +34,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -60,6 +61,7 @@ import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.accessibility.IRemoteMagnificationAnimationCallback;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.LargeTest;
|
||||
@@ -75,6 +77,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
@@ -89,8 +92,6 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private Handler mHandler;
|
||||
@Mock
|
||||
private WindowMagnificationAnimationController mWindowMagnificationAnimationController;
|
||||
@Mock
|
||||
private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
|
||||
@Mock
|
||||
private MirrorWindowControl mMirrorWindowControl;
|
||||
@@ -101,6 +102,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
private TestableWindowManager mWindowManager;
|
||||
private SysUiState mSysUiState = new SysUiState();
|
||||
private Resources mResources;
|
||||
private WindowMagnificationAnimationController mWindowMagnificationAnimationController;
|
||||
private WindowMagnificationController mWindowMagnificationController;
|
||||
private Instrumentation mInstrumentation;
|
||||
|
||||
@@ -125,10 +127,11 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
return null;
|
||||
}).when(mHandler).post(
|
||||
any(Runnable.class));
|
||||
|
||||
mSysUiState.addCallback(Mockito.mock(SysUiState.SysUiStateCallback.class));
|
||||
|
||||
mResources = getContext().getOrCreateTestableResources().getResources();
|
||||
mWindowMagnificationAnimationController = new WindowMagnificationAnimationController(
|
||||
mContext);
|
||||
mWindowMagnificationController = new WindowMagnificationController(mContext,
|
||||
mHandler, mWindowMagnificationAnimationController, mSfVsyncFrameProvider,
|
||||
mMirrorWindowControl, mTransaction, mWindowMagnifierCallback, mSysUiState);
|
||||
@@ -156,6 +159,52 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
eq(mContext.getDisplayId()), any(Rect.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableWindowMagnification_notifySourceBoundsChanged() {
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
|
||||
Float.NaN, /* magnificationFrameOffsetRatioX= */ 0,
|
||||
/* magnificationFrameOffsetRatioY= */ 0, null);
|
||||
});
|
||||
|
||||
// Waits for the surface created
|
||||
verify(mWindowMagnifierCallback, timeout(LAYOUT_CHANGE_TIMEOUT_MS)).onSourceBoundsChanged(
|
||||
(eq(mContext.getDisplayId())), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableWindowMagnification_withAnimation_schedulesFrame() {
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.enableWindowMagnification(2.0f, 10,
|
||||
10, /* magnificationFrameOffsetRatioX= */ 0,
|
||||
/* magnificationFrameOffsetRatioY= */ 0,
|
||||
Mockito.mock(IRemoteMagnificationAnimationCallback.class));
|
||||
});
|
||||
|
||||
verify(mSfVsyncFrameProvider,
|
||||
timeout(LAYOUT_CHANGE_TIMEOUT_MS).atLeast(2)).postFrameCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveWindowMagnifier_enabled_notifySourceBoundsChanged() {
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
|
||||
Float.NaN, 0, 0, null);
|
||||
});
|
||||
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.moveWindowMagnifier(10, 10);
|
||||
});
|
||||
|
||||
final ArgumentCaptor<Rect> sourceBoundsCaptor = ArgumentCaptor.forClass(Rect.class);
|
||||
verify(mWindowMagnifierCallback, atLeast(2)).onSourceBoundsChanged(
|
||||
(eq(mContext.getDisplayId())), sourceBoundsCaptor.capture());
|
||||
assertEquals(mWindowMagnificationController.getCenterX(),
|
||||
sourceBoundsCaptor.getValue().exactCenterX(), 0);
|
||||
assertEquals(mWindowMagnificationController.getCenterY(),
|
||||
sourceBoundsCaptor.getValue().exactCenterY(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableWindowMagnification_systemGestureExclusionRectsIsSet() {
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
|
||||
@@ -1542,9 +1542,9 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
}
|
||||
|
||||
public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
|
||||
float scale, float centerX, float centerY) {
|
||||
@NonNull MagnificationConfig config) {
|
||||
mInvocationHandler
|
||||
.notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
|
||||
.notifyMagnificationChangedLocked(displayId, region, config);
|
||||
}
|
||||
|
||||
public void notifySoftKeyboardShowModeChangedLocked(int showState) {
|
||||
@@ -1564,15 +1564,15 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
* state of magnification has changed.
|
||||
*/
|
||||
private void notifyMagnificationChangedInternal(int displayId, @NonNull Region region,
|
||||
float scale, float centerX, float centerY) {
|
||||
@NonNull MagnificationConfig config) {
|
||||
final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
|
||||
if (listener != null) {
|
||||
try {
|
||||
if (svcClientTracingEnabled()) {
|
||||
logTraceSvcClient("onMagnificationChanged", displayId + ", " + region + ", "
|
||||
+ scale + ", " + centerX + ", " + centerY);
|
||||
+ config.toString());
|
||||
}
|
||||
listener.onMagnificationChanged(displayId, region, scale, centerX, centerY);
|
||||
listener.onMagnificationChanged(displayId, region, config);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re);
|
||||
}
|
||||
@@ -1899,11 +1899,9 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
case MSG_ON_MAGNIFICATION_CHANGED: {
|
||||
final SomeArgs args = (SomeArgs) message.obj;
|
||||
final Region region = (Region) args.arg1;
|
||||
final float scale = (float) args.arg2;
|
||||
final float centerX = (float) args.arg3;
|
||||
final float centerY = (float) args.arg4;
|
||||
final MagnificationConfig config = (MagnificationConfig) args.arg2;
|
||||
final int displayId = args.argi1;
|
||||
notifyMagnificationChangedInternal(displayId, region, scale, centerX, centerY);
|
||||
notifyMagnificationChangedInternal(displayId, region, config);
|
||||
args.recycle();
|
||||
} break;
|
||||
|
||||
@@ -1932,7 +1930,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
}
|
||||
|
||||
public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
|
||||
float scale, float centerX, float centerY) {
|
||||
@NonNull MagnificationConfig config) {
|
||||
synchronized (mLock) {
|
||||
if (mMagnificationCallbackState.get(displayId) == null) {
|
||||
return;
|
||||
@@ -1941,9 +1939,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = region;
|
||||
args.arg2 = scale;
|
||||
args.arg3 = centerX;
|
||||
args.arg4 = centerY;
|
||||
args.arg2 = config;
|
||||
args.argi1 = displayId;
|
||||
|
||||
final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args);
|
||||
|
||||
@@ -44,6 +44,7 @@ import android.accessibilityservice.AccessibilityService;
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.accessibilityservice.AccessibilityShortcutInfo;
|
||||
import android.accessibilityservice.IAccessibilityServiceClient;
|
||||
import android.accessibilityservice.MagnificationConfig;
|
||||
import android.accessibilityservice.TouchInteractionController;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -1301,18 +1302,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
* Called by the MagnificationController when the state of display
|
||||
* magnification changes.
|
||||
*
|
||||
* @param displayId The logical display id.
|
||||
* <p>
|
||||
* It can notify window magnification change if the service supports controlling all the
|
||||
* magnification mode.
|
||||
* </p>
|
||||
*
|
||||
* @param displayId The logical display id
|
||||
* @param region the new magnified region, may be empty if
|
||||
* magnification is not enabled (e.g. scale is 1)
|
||||
* @param scale the new scale
|
||||
* @param centerX the new screen-relative center X coordinate
|
||||
* @param centerY the new screen-relative center Y coordinate
|
||||
* @param config The magnification config. That has magnification mode, the new scale and the
|
||||
* new screen-relative center position
|
||||
*/
|
||||
public void notifyMagnificationChanged(int displayId, @NonNull Region region,
|
||||
float scale, float centerX, float centerY) {
|
||||
@NonNull MagnificationConfig config) {
|
||||
synchronized (mLock) {
|
||||
notifyClearAccessibilityCacheLocked();
|
||||
notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
|
||||
notifyMagnificationChangedLocked(displayId, region, config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1613,11 +1618,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
}
|
||||
|
||||
private void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
|
||||
float scale, float centerX, float centerY) {
|
||||
@NonNull MagnificationConfig config) {
|
||||
final AccessibilityUserState state = getCurrentUserStateLocked();
|
||||
for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
|
||||
final AccessibilityServiceConnection service = state.mBoundServices.get(i);
|
||||
service.notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
|
||||
service.notifyMagnificationChangedLocked(displayId, region, config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
package com.android.server.accessibility.magnification;
|
||||
|
||||
import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL;
|
||||
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
|
||||
import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;
|
||||
|
||||
import static com.android.server.accessibility.AccessibilityManagerService.INVALID_SERVICE_ID;
|
||||
|
||||
import android.accessibilityservice.MagnificationConfig;
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.NonNull;
|
||||
@@ -363,9 +365,16 @@ public class FullScreenMagnificationController implements
|
||||
return mIdOfLastServiceToMagnify;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
void onMagnificationChangedLocked() {
|
||||
mControllerCtx.getAms().notifyMagnificationChanged(mDisplayId, mMagnificationRegion,
|
||||
getScale(), getCenterX(), getCenterY());
|
||||
final MagnificationConfig config = new MagnificationConfig.Builder()
|
||||
.setMode(MAGNIFICATION_MODE_FULLSCREEN)
|
||||
.setScale(getScale())
|
||||
.setCenterX(getCenterX())
|
||||
.setCenterY(getCenterY()).build();
|
||||
mControllerCtx.getAms().notifyMagnificationChanged(mDisplayId,
|
||||
mMagnificationRegion,
|
||||
config);
|
||||
if (mUnregisterPending && !isMagnifying()) {
|
||||
unregister(mDeleteAfterUnregister);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.accessibility.magnification;
|
||||
|
||||
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_WINDOW;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
|
||||
@@ -379,6 +380,16 @@ public class MagnificationController implements WindowMagnificationManager.Callb
|
||||
mAms.changeMagnificationMode(displayId, magnificationMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSourceBoundsChanged(int displayId, Rect bounds) {
|
||||
final MagnificationConfig config = new MagnificationConfig.Builder()
|
||||
.setMode(MAGNIFICATION_MODE_WINDOW)
|
||||
.setScale(mScaleProvider.getScale(displayId))
|
||||
.setCenterX(bounds.exactCenterX())
|
||||
.setCenterY(bounds.exactCenterY()).build();
|
||||
mAms.notifyMagnificationChanged(displayId, new Region(bounds), config);
|
||||
}
|
||||
|
||||
private void disableFullScreenMagnificationIfNeeded(int displayId) {
|
||||
final FullScreenMagnificationController fullScreenMagnificationController =
|
||||
getFullScreenMagnificationController();
|
||||
|
||||
@@ -138,6 +138,14 @@ public class WindowMagnificationManager implements
|
||||
*/
|
||||
void onWindowMagnificationActivationState(int displayId, boolean activated);
|
||||
|
||||
/**
|
||||
* Called when the magnification source bounds are changed.
|
||||
*
|
||||
* @param displayId The logical display id.
|
||||
* @param bounds The magnified source bounds on the display.
|
||||
*/
|
||||
void onSourceBoundsChanged(int displayId, Rect bounds);
|
||||
|
||||
/**
|
||||
* Called from {@link IWindowMagnificationConnection} to request changing the magnification
|
||||
* mode on the given display.
|
||||
@@ -689,6 +697,7 @@ public class WindowMagnificationManager implements
|
||||
}
|
||||
magnifier.onSourceBoundsChanged(sourceBounds);
|
||||
}
|
||||
mCallback.onSourceBoundsChanged(displayId, sourceBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.accessibility.magnification;
|
||||
|
||||
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
|
||||
|
||||
import static com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -23,10 +25,8 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -37,6 +37,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
|
||||
|
||||
import android.accessibilityservice.MagnificationConfig;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -105,6 +106,8 @@ public class FullScreenMagnificationControllerTest {
|
||||
private final MagnificationScaleProvider mScaleProvider = mock(
|
||||
MagnificationScaleProvider.class);
|
||||
|
||||
private final ArgumentCaptor<MagnificationConfig> mConfigCaptor = ArgumentCaptor.forClass(
|
||||
MagnificationConfig.class);
|
||||
|
||||
ValueAnimator mMockValueAnimator;
|
||||
ValueAnimator.AnimatorUpdateListener mTargetAnimationListener;
|
||||
@@ -142,13 +145,13 @@ public class FullScreenMagnificationControllerTest {
|
||||
register(DISPLAY_1);
|
||||
register(INVALID_DISPLAY);
|
||||
verify(mMockContext).registerReceiver(
|
||||
(BroadcastReceiver) anyObject(), (IntentFilter) anyObject());
|
||||
any(BroadcastReceiver.class), any(IntentFilter.class));
|
||||
verify(mMockWindowManager).setMagnificationCallbacks(
|
||||
eq(DISPLAY_0), (MagnificationCallbacks) anyObject());
|
||||
eq(DISPLAY_0), any(MagnificationCallbacks.class));
|
||||
verify(mMockWindowManager).setMagnificationCallbacks(
|
||||
eq(DISPLAY_1), (MagnificationCallbacks) anyObject());
|
||||
eq(DISPLAY_1), any(MagnificationCallbacks.class));
|
||||
verify(mMockWindowManager).setMagnificationCallbacks(
|
||||
eq(INVALID_DISPLAY), (MagnificationCallbacks) anyObject());
|
||||
eq(INVALID_DISPLAY), any(MagnificationCallbacks.class));
|
||||
assertTrue(mFullScreenMagnificationController.isRegistered(DISPLAY_0));
|
||||
assertTrue(mFullScreenMagnificationController.isRegistered(DISPLAY_1));
|
||||
assertFalse(mFullScreenMagnificationController.isRegistered(INVALID_DISPLAY));
|
||||
@@ -159,9 +162,9 @@ public class FullScreenMagnificationControllerTest {
|
||||
register(DISPLAY_0);
|
||||
register(DISPLAY_1);
|
||||
mFullScreenMagnificationController.unregister(DISPLAY_0);
|
||||
verify(mMockContext, times(0)).unregisterReceiver((BroadcastReceiver) anyObject());
|
||||
verify(mMockContext, times(0)).unregisterReceiver(any(BroadcastReceiver.class));
|
||||
mFullScreenMagnificationController.unregister(DISPLAY_1);
|
||||
verify(mMockContext).unregisterReceiver((BroadcastReceiver) anyObject());
|
||||
verify(mMockContext).unregisterReceiver(any(BroadcastReceiver.class));
|
||||
verify(mMockWindowManager).setMagnificationCallbacks(eq(DISPLAY_0), eq(null));
|
||||
verify(mMockWindowManager).setMagnificationCallbacks(eq(DISPLAY_1), eq(null));
|
||||
assertFalse(mFullScreenMagnificationController.isRegistered(DISPLAY_0));
|
||||
@@ -343,6 +346,7 @@ public class FullScreenMagnificationControllerTest {
|
||||
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
|
||||
float scale = 2.5f;
|
||||
PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
|
||||
final MagnificationConfig config = buildConfig(scale, newCenter.x, newCenter.y);
|
||||
PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
|
||||
MagnificationSpec endSpec = getMagnificationSpec(scale, offsets);
|
||||
|
||||
@@ -353,8 +357,9 @@ public class FullScreenMagnificationControllerTest {
|
||||
assertEquals(newCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5);
|
||||
assertEquals(newCenter.y, mFullScreenMagnificationController.getCenterY(displayId), 0.5);
|
||||
assertThat(getCurrentMagnificationSpec(displayId), closeTo(endSpec));
|
||||
verify(mMockAms).notifyMagnificationChanged(displayId,
|
||||
INITIAL_MAGNIFICATION_REGION, scale, newCenter.x, newCenter.y);
|
||||
verify(mMockAms).notifyMagnificationChanged(eq(displayId), eq(INITIAL_MAGNIFICATION_REGION),
|
||||
mConfigCaptor.capture());
|
||||
assertConfigEquals(config, mConfigCaptor.getValue());
|
||||
verify(mMockValueAnimator).start();
|
||||
verify(mRequestObserver).onRequestMagnificationSpec(displayId, SERVICE_ID_1);
|
||||
|
||||
@@ -494,8 +499,11 @@ public class FullScreenMagnificationControllerTest {
|
||||
MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
|
||||
callbacks.onMagnificationRegionChanged(OTHER_REGION);
|
||||
mMessageCapturingHandler.sendAllMessages();
|
||||
verify(mMockAms).notifyMagnificationChanged(displayId, OTHER_REGION, 1.0f,
|
||||
OTHER_MAGNIFICATION_BOUNDS.centerX(), OTHER_MAGNIFICATION_BOUNDS.centerY());
|
||||
MagnificationConfig config = buildConfig(1.0f, OTHER_MAGNIFICATION_BOUNDS.centerX(),
|
||||
OTHER_MAGNIFICATION_BOUNDS.centerY());
|
||||
verify(mMockAms).notifyMagnificationChanged(eq(displayId), eq(OTHER_REGION),
|
||||
mConfigCaptor.capture());
|
||||
assertConfigEquals(config, mConfigCaptor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -650,7 +658,7 @@ public class FullScreenMagnificationControllerTest {
|
||||
reset(mMockAms);
|
||||
assertTrue(mFullScreenMagnificationController.resetIfNeeded(displayId, false));
|
||||
verify(mMockAms).notifyMagnificationChanged(eq(displayId),
|
||||
eq(INITIAL_MAGNIFICATION_REGION), eq(1.0f), anyFloat(), anyFloat());
|
||||
eq(INITIAL_MAGNIFICATION_REGION), any(MagnificationConfig.class));
|
||||
assertFalse(mFullScreenMagnificationController.isMagnifying(displayId));
|
||||
assertFalse(mFullScreenMagnificationController.resetIfNeeded(displayId, false));
|
||||
}
|
||||
@@ -668,8 +676,8 @@ public class FullScreenMagnificationControllerTest {
|
||||
assertFalse(mFullScreenMagnificationController.reset(displayId, mAnimationCallback));
|
||||
mMessageCapturingHandler.sendAllMessages();
|
||||
|
||||
verify(mMockAms, never()).notifyMagnificationChanged(eq(displayId),
|
||||
any(Region.class), anyFloat(), anyFloat(), anyFloat());
|
||||
verify(mMockAms, never()).notifyMagnificationChanged(eq(displayId), any(Region.class),
|
||||
any(MagnificationConfig.class));
|
||||
verify(mAnimationCallback).onResult(true);
|
||||
}
|
||||
|
||||
@@ -726,7 +734,7 @@ public class FullScreenMagnificationControllerTest {
|
||||
ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
|
||||
ArgumentCaptor.forClass(BroadcastReceiver.class);
|
||||
verify(mMockContext).registerReceiver(
|
||||
broadcastReceiverCaptor.capture(), (IntentFilter) anyObject());
|
||||
broadcastReceiverCaptor.capture(), any(IntentFilter.class));
|
||||
BroadcastReceiver br = broadcastReceiverCaptor.getValue();
|
||||
zoomIn2xToMiddle(DISPLAY_0);
|
||||
zoomIn2xToMiddle(DISPLAY_1);
|
||||
@@ -1031,6 +1039,7 @@ public class FullScreenMagnificationControllerTest {
|
||||
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
|
||||
float scale = 2.5f;
|
||||
PointF firstCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
|
||||
final MagnificationConfig config = buildConfig(scale, firstCenter.x, firstCenter.y);
|
||||
MagnificationSpec firstEndSpec = getMagnificationSpec(
|
||||
scale, computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, firstCenter, scale));
|
||||
|
||||
@@ -1047,8 +1056,9 @@ public class FullScreenMagnificationControllerTest {
|
||||
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
|
||||
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
|
||||
verify(mMockWindowManager).setMagnificationSpec(eq(displayId), eq(startSpec));
|
||||
verify(mMockAms).notifyMagnificationChanged(displayId,
|
||||
INITIAL_MAGNIFICATION_REGION, scale, firstCenter.x, firstCenter.y);
|
||||
verify(mMockAms).notifyMagnificationChanged(eq(displayId), eq(INITIAL_MAGNIFICATION_REGION),
|
||||
mConfigCaptor.capture());
|
||||
assertConfigEquals(config, mConfigCaptor.getValue());
|
||||
Mockito.reset(mMockWindowManager);
|
||||
|
||||
// Intermediate point
|
||||
@@ -1062,6 +1072,7 @@ public class FullScreenMagnificationControllerTest {
|
||||
Mockito.reset(mMockWindowManager);
|
||||
|
||||
PointF newCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
|
||||
final MagnificationConfig newConfig = buildConfig(scale, newCenter.x, newCenter.y);
|
||||
MagnificationSpec newEndSpec = getMagnificationSpec(
|
||||
scale, computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale));
|
||||
assertTrue(mFullScreenMagnificationController.setCenter(displayId,
|
||||
@@ -1070,8 +1081,9 @@ public class FullScreenMagnificationControllerTest {
|
||||
|
||||
// Animation should have been restarted
|
||||
verify(mMockValueAnimator, times(2)).start();
|
||||
verify(mMockAms).notifyMagnificationChanged(displayId,
|
||||
INITIAL_MAGNIFICATION_REGION, scale, newCenter.x, newCenter.y);
|
||||
verify(mMockAms, times(2)).notifyMagnificationChanged(eq(displayId),
|
||||
eq(INITIAL_MAGNIFICATION_REGION), mConfigCaptor.capture());
|
||||
assertConfigEquals(newConfig, mConfigCaptor.getValue());
|
||||
|
||||
// New starting point should be where we left off
|
||||
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
|
||||
@@ -1155,7 +1167,7 @@ public class FullScreenMagnificationControllerTest {
|
||||
Region regionArg = (Region) args[1];
|
||||
regionArg.set(INITIAL_MAGNIFICATION_REGION);
|
||||
return null;
|
||||
}).when(mMockWindowManager).getMagnificationRegion(anyInt(), (Region) anyObject());
|
||||
}).when(mMockWindowManager).getMagnificationRegion(anyInt(), any(Region.class));
|
||||
}
|
||||
|
||||
private void resetMockWindowManager() {
|
||||
@@ -1201,6 +1213,19 @@ public class FullScreenMagnificationControllerTest {
|
||||
magnifiedBounds.centerY() - scale * center.y);
|
||||
}
|
||||
|
||||
private MagnificationConfig buildConfig(float scale, float centerX, float centerY) {
|
||||
return new MagnificationConfig.Builder().setMode(
|
||||
MAGNIFICATION_MODE_FULLSCREEN).setScale(scale).setCenterX(centerX).setCenterY(
|
||||
centerY).build();
|
||||
}
|
||||
|
||||
private void assertConfigEquals(MagnificationConfig expected, MagnificationConfig result) {
|
||||
assertEquals(expected.getMode(), result.getMode());
|
||||
assertEquals(expected.getScale(), result.getScale(), 0f);
|
||||
assertEquals(expected.getCenterX(), result.getCenterX(), 0f);
|
||||
assertEquals(expected.getCenterY(), result.getCenterY(), 0f);
|
||||
}
|
||||
|
||||
private MagnificationSpec getInterpolatedMagSpec(MagnificationSpec start, MagnificationSpec end,
|
||||
float fraction) {
|
||||
MagnificationSpec interpolatedSpec = new MagnificationSpec();
|
||||
|
||||
@@ -429,6 +429,21 @@ public class MagnificationControllerTest {
|
||||
verify(mWindowMagnificationManager).persistScale(eq(TEST_DISPLAY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onSourceBoundsChanged_notifyMagnificationChanged() {
|
||||
Rect rect = new Rect(0, 0, 100, 120);
|
||||
Region region = new Region(rect);
|
||||
|
||||
mMagnificationController.onSourceBoundsChanged(TEST_DISPLAY, rect);
|
||||
|
||||
final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass(
|
||||
MagnificationConfig.class);
|
||||
verify(mService).notifyMagnificationChanged(eq(TEST_DISPLAY), eq(region),
|
||||
configCaptor.capture());
|
||||
assertEquals(rect.exactCenterX(), configCaptor.getValue().getCenterX(), 0);
|
||||
assertEquals(rect.exactCenterY(), configCaptor.getValue().getCenterY(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAccessibilityActionPerformed_magnifierEnabled_showMagnificationButton()
|
||||
throws RemoteException {
|
||||
|
||||
Reference in New Issue
Block a user