Notifies window magnifcation changes for AccessibilityService (1/n)

See Design doc:  go/b200769372
To make the behavior consistent on the new platform,
The legcay callback,
  onMagnificationChanged(MagnificationController controller,
  Region region, float scale, float centerX, float centerY)
keep notifying only full-screen magnification change as
before.

To support listening to the magnification changes of all
magnification modes, the service should overide
The new callback proposed in T,
  onMagnificationChanged(MagnificationController controller,
  Region region, MagnificationConfig config).

TODO: Notify magnifcation change when window magnifier turns off

Bug: 203013925
Test: atest AccessibilityMagnificationTest,
    atest MagnificationControllerTest,
    atest WindowMagnificationManagerTest,
    atest WindowMagnificationControllerTest,
    atest FullScreenMagnificationControllerTest,

Change-Id: Ia73195a71f55bb26ef3f2eafce0dc73d8a65583b
This commit is contained in:
mincheli
2021-09-22 15:20:33 +08:00
parent a75f5a9aed
commit be41ea676c
13 changed files with 231 additions and 78 deletions

View File

@@ -3137,6 +3137,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 {

View File

@@ -587,7 +587,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());
}
}
}
}
@@ -2370,9 +2403,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
@@ -2496,12 +2528,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);
@@ -2660,13 +2690,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;
}

View File

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

View File

@@ -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 */
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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.
@@ -688,6 +696,7 @@ public class WindowMagnificationManager implements
}
magnifier.onSourceBoundsChanged(sourceBounds);
}
mCallback.onSourceBoundsChanged(displayId, sourceBounds);
}
@Override

View File

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

View File

@@ -428,6 +428,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 {