diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java index 51e34178e80cd..38615feeba48b 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java @@ -63,7 +63,8 @@ import java.util.Locale; * magnification region. If a value is out of bounds, it will be adjusted to guarantee these * constraints. */ -public class FullScreenMagnificationController { +public class FullScreenMagnificationController implements + WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks { private static final boolean DEBUG = false; private static final String LOG_TAG = "FullScreenMagnificationController"; @@ -85,6 +86,8 @@ public class FullScreenMagnificationController { @GuardedBy("mLock") private final SparseArray mDisplays = new SparseArray<>(0); + private final Rect mTempRect = new Rect(); + /** * This class implements {@link WindowManagerInternal.MagnificationCallbacks} and holds * magnification information per display. @@ -727,6 +730,26 @@ public class FullScreenMagnificationController { } } + @Override + public void onRectangleOnScreenRequested(int displayId, int left, int top, int right, + int bottom) { + synchronized (mLock) { + final DisplayMagnification display = mDisplays.get(displayId); + if (display == null) { + return; + } + if (!display.isMagnifying()) { + return; + } + final Rect magnifiedRegionBounds = mTempRect; + display.getMagnifiedFrameInContentCoordsLocked(magnifiedRegionBounds); + if (magnifiedRegionBounds.contains(left, top, right, bottom)) { + return; + } + display.onRectangleOnScreenRequested(left, top, right, bottom); + } + } + /** * Remove the display magnification with given id. * diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java index d430f6b032c15..791da694c8117 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -40,7 +40,9 @@ import android.view.accessibility.MagnificationAnimationCallback; import com.android.internal.accessibility.util.AccessibilityStatsLogUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.LocalServices; import com.android.server.accessibility.AccessibilityManagerService; +import com.android.server.wm.WindowManagerInternal; /** * Handles all magnification controllers initialization, generic interactions, @@ -68,7 +70,8 @@ import com.android.server.accessibility.AccessibilityManagerService; */ public class MagnificationController implements WindowMagnificationManager.Callback, MagnificationGestureHandler.Callback, - FullScreenMagnificationController.MagnificationInfoChangedCallback { + FullScreenMagnificationController.MagnificationInfoChangedCallback, + WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks { private static final boolean DEBUG = false; private static final String TAG = "MagnificationController"; @@ -96,6 +99,11 @@ public class MagnificationController implements WindowMagnificationManager.Callb private long mWindowModeEnabledTime = 0; private long mFullScreenModeEnabledTime = 0; + @GuardedBy("mLock") + @Nullable + private WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks + mAccessibilityCallbacksDelegate; + /** * A callback to inform the magnification transition result on the given display. */ @@ -115,6 +123,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb mLock = lock; mContext = context; mScaleProvider = scaleProvider; + LocalServices.getService(WindowManagerInternal.class) + .getAccessibilityController().setUiChangesForAccessibilityCallbacks(this); } @VisibleForTesting @@ -292,6 +302,37 @@ public class MagnificationController implements WindowMagnificationManager.Callb return false; } + @GuardedBy("mLock") + private void setActivatedModeAndSwitchDelegate(int mode) { + mActivatedMode = mode; + assignMagnificationWindowManagerDelegateByMode(mode); + } + + private void assignMagnificationWindowManagerDelegateByMode(int mode) { + synchronized (mLock) { + if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { + mAccessibilityCallbacksDelegate = getFullScreenMagnificationController(); + } else if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { + mAccessibilityCallbacksDelegate = getWindowMagnificationMgr(); + } else { + mAccessibilityCallbacksDelegate = null; + } + } + } + + @Override + public void onRectangleOnScreenRequested(int displayId, int left, int top, int right, + int bottom) { + WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks + delegate; + synchronized (mLock) { + delegate = mAccessibilityCallbacksDelegate; + } + if (delegate != null) { + delegate.onRectangleOnScreenRequested(displayId, left, top, right, bottom); + } + } + @Override public void onRequestMagnificationSpec(int displayId, int serviceId) { final WindowMagnificationManager windowMagnificationManager; @@ -314,7 +355,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb mWindowModeEnabledTime = SystemClock.uptimeMillis(); synchronized (mLock) { - mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; + setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); mLastActivatedMode = mActivatedMode; } logMagnificationModeWithImeOnIfNeeded(); @@ -324,7 +365,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb SystemClock.uptimeMillis() - mWindowModeEnabledTime); synchronized (mLock) { - mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE; + setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_NONE); } } updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); @@ -353,7 +394,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb mFullScreenModeEnabledTime = SystemClock.uptimeMillis(); synchronized (mLock) { - mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; + setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); mLastActivatedMode = mActivatedMode; } logMagnificationModeWithImeOnIfNeeded(); @@ -363,7 +404,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb SystemClock.uptimeMillis() - mFullScreenModeEnabledTime); synchronized (mLock) { - mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE; + setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_NONE); } } updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java index 9162064780caa..3f6ff25dafe56 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java @@ -45,6 +45,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; import com.android.server.accessibility.AccessibilityTraceManager; import com.android.server.statusbar.StatusBarManagerInternal; +import com.android.server.wm.WindowManagerInternal; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -57,7 +58,8 @@ import java.lang.annotation.RetentionPolicy; * {@link MagnificationScaleProvider#constrainScale(float)} */ public class WindowMagnificationManager implements - PanningScalingHandler.MagnificationDelegate { + PanningScalingHandler.MagnificationDelegate, + WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks { private static final boolean DBG = false; @@ -263,6 +265,13 @@ public class WindowMagnificationManager implements } } + @Override + public void onRectangleOnScreenRequested(int displayId, int left, int top, int right, + int bottom) { + // TODO(b/194668976): We will implement following typing focus in window mode after + // our refactor. + } + @Override public boolean processScroll(int displayId, float distanceX, float distanceY) { moveWindowMagnification(displayId, -distanceX, -distanceY); diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index ec0b5f083a384..0396a1101c644 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -98,6 +98,7 @@ import android.view.animation.Interpolator; import com.android.internal.R; import com.android.internal.os.SomeArgs; import com.android.internal.util.TraceBuffer; +import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.WindowManagerInternal.AccessibilityControllerInternal; @@ -277,20 +278,6 @@ final class AccessibilityController { } } - void onRectangleOnScreenRequested(int displayId, Rect rectangle) { - if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { - mAccessibilityTracing.logTrace( - TAG + ".onRectangleOnScreenRequested", - FLAGS_MAGNIFICATION_CALLBACK, - "displayId=" + displayId + "; rectangle={" + rectangle + "}"); - } - final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); - if (displayMagnifier != null) { - displayMagnifier.onRectangleOnScreenRequested(rectangle); - } - // Not relevant for the window observer. - } - void onWindowLayersChanged(int displayId) { if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { @@ -634,31 +621,6 @@ final class AccessibilityController { return mForceShowMagnifiableBounds; } - void onRectangleOnScreenRequested(Rect rectangle) { - if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { - mAccessibilityTracing.logTrace(LOG_TAG + ".onRectangleOnScreenRequested", - FLAGS_MAGNIFICATION_CALLBACK, "rectangle={" + rectangle + "}"); - } - if (DEBUG_RECTANGLE_REQUESTED) { - Slog.i(LOG_TAG, "Rectangle on screen requested: " + rectangle); - } - if (!mMagnifedViewport.isMagnifying()) { - return; - } - Rect magnifiedRegionBounds = mTempRect2; - mMagnifedViewport.getMagnifiedFrameInContentCoords(magnifiedRegionBounds); - if (magnifiedRegionBounds.contains(rectangle)) { - return; - } - SomeArgs args = SomeArgs.obtain(); - args.argi1 = rectangle.left; - args.argi2 = rectangle.top; - args.argi3 = rectangle.right; - args.argi4 = rectangle.bottom; - mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED, - args).sendToTarget(); - } - void onWindowLayersChanged() { if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { mAccessibilityTracing.logTrace( @@ -1352,7 +1314,6 @@ final class AccessibilityController { private class MyHandler extends Handler { public static final int MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED = 1; - public static final int MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 2; public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3; public static final int MESSAGE_NOTIFY_DISPLAY_SIZE_CHANGED = 4; public static final int MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED = 5; @@ -1372,16 +1333,6 @@ final class AccessibilityController { magnifiedBounds.recycle(); } break; - case MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: { - SomeArgs args = (SomeArgs) message.obj; - final int left = args.argi1; - final int top = args.argi2; - final int right = args.argi3; - final int bottom = args.argi4; - mCallbacks.onRectangleOnScreenRequested(left, top, right, bottom); - args.recycle(); - } break; - case MESSAGE_NOTIFY_USER_CONTEXT_CHANGED: { mCallbacks.onUserContextChanged(); } break; @@ -1902,7 +1853,7 @@ final class AccessibilityController { } } - private static final class AccessibilityControllerInternalImpl + static final class AccessibilityControllerInternalImpl implements AccessibilityControllerInternal { private static AccessibilityControllerInternalImpl sInstance; @@ -1917,8 +1868,11 @@ final class AccessibilityController { private final AccessibilityTracing mTracing; private volatile long mEnabledTracingFlags; + private UiChangesForAccessibilityCallbacksDispatcher mCallbacksDispatcher; + private final Looper mLooper; private AccessibilityControllerInternalImpl(WindowManagerService service) { + mLooper = service.mH.getLooper(); mTracing = AccessibilityTracing.getInstance(service); mEnabledTracingFlags = 0L; } @@ -1972,6 +1926,90 @@ final class AccessibilityController { mTracing.logState(where, loggingTypes, callingParams, a11yDump, callingUid, callStack, timeStamp, processId, threadId, ignoreStackEntries); } + + @Override + public void setUiChangesForAccessibilityCallbacks( + UiChangesForAccessibilityCallbacks callbacks) { + if (isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { + logTrace( + TAG + ".setAccessibilityWindowManagerCallbacks", + FLAGS_MAGNIFICATION_CALLBACK, + "callbacks={" + callbacks + "}"); + } + if (callbacks != null) { + if (mCallbacksDispatcher != null) { + throw new IllegalStateException("Accessibility window manager callback already " + + "set!"); + } + mCallbacksDispatcher = + new UiChangesForAccessibilityCallbacksDispatcher(this, mLooper, + callbacks); + } else { + if (mCallbacksDispatcher == null) { + throw new IllegalStateException("Accessibility window manager callback already " + + "cleared!"); + } + mCallbacksDispatcher = null; + } + } + + public boolean hasWindowManagerEventDispatcher() { + if (isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK + | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { + logTrace(TAG + ".hasCallbacks", + FLAGS_MAGNIFICATION_CALLBACK | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK); + } + return mCallbacksDispatcher != null; + } + + public void onRectangleOnScreenRequested(int displayId, Rect rectangle) { + if (isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { + logTrace( + TAG + ".onRectangleOnScreenRequested", + FLAGS_MAGNIFICATION_CALLBACK, + "rectangle={" + rectangle + "}"); + } + if (mCallbacksDispatcher != null) { + mCallbacksDispatcher.onRectangleOnScreenRequested(displayId, rectangle); + } + } + + private static final class UiChangesForAccessibilityCallbacksDispatcher { + + private static final String LOG_TAG = TAG_WITH_CLASS_NAME + ? "WindowManagerEventDispatcher" : TAG_WM; + + private static final boolean DEBUG_RECTANGLE_REQUESTED = false; + + private final AccessibilityControllerInternalImpl mAccessibilityTracing; + + @NonNull + private final UiChangesForAccessibilityCallbacks mCallbacks; + + private final Handler mHandler; + + UiChangesForAccessibilityCallbacksDispatcher( + AccessibilityControllerInternalImpl accessibilityControllerInternal, + Looper looper, @NonNull UiChangesForAccessibilityCallbacks callbacks) { + mAccessibilityTracing = accessibilityControllerInternal; + mCallbacks = callbacks; + mHandler = new Handler(looper); + } + + void onRectangleOnScreenRequested(int displayId, Rect rectangle) { + if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { + mAccessibilityTracing.logTrace(LOG_TAG + ".onRectangleOnScreenRequested", + FLAGS_MAGNIFICATION_CALLBACK, "rectangle={" + rectangle + "}"); + } + if (DEBUG_RECTANGLE_REQUESTED) { + Slog.i(LOG_TAG, "Rectangle on screen requested: " + rectangle); + } + final Message m = PooledLambda.obtainMessage( + mCallbacks::onRectangleOnScreenRequested, displayId, rectangle.left, + rectangle.top, rectangle.right, rectangle.bottom); + mHandler.sendMessage(m); + } + } } private static final class AccessibilityTracing { diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index 34cb5ae032ba9..62c674b15f89a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -104,6 +104,32 @@ public abstract class WindowManagerInternal { void logTrace(String where, long loggingTypeFlags, String callingParams, byte[] a11yDump, int callingUid, StackTraceElement[] callStack, long timeStamp, int processId, long threadId, Set ignoreStackEntries); + + /** + * Set by the accessibility related modules which want to listen the event dispatched from + * window manager. Accessibility modules can use these callbacks to handle some display + * manipulations. + * @param callbacks The callbacks to invoke. + */ + void setUiChangesForAccessibilityCallbacks(UiChangesForAccessibilityCallbacks callbacks); + + /** + * This interface is used by window manager to dispatch some ui change events which may + * affect the screen accessibility features. + */ + interface UiChangesForAccessibilityCallbacks { + /** + * Called when an application requests a rectangle focus on the screen. + * + * @param displayId The logical display id + * @param left The rectangle left. + * @param top The rectangle top. + * @param right The rectangle right. + * @param bottom The rectangle bottom. + */ + void onRectangleOnScreenRequested(int displayId, int left, int top, int right, + int bottom); + } } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 58860de3dcdd0..86775f629df0b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2144,11 +2144,13 @@ public class WindowManagerService extends IWindowManager.Stub } public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { + final AccessibilityController.AccessibilityControllerInternalImpl a11yControllerInternal = + AccessibilityController.getAccessibilityControllerInternal(this); synchronized (mGlobalLock) { - if (mAccessibilityController.hasCallbacks()) { + if (a11yControllerInternal.hasWindowManagerEventDispatcher()) { WindowState window = mWindowMap.get(token); if (window != null) { - mAccessibilityController.onRectangleOnScreenRequested( + a11yControllerInternal.onRectangleOnScreenRequested( window.getDisplayId(), rectangle); } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java index ec1a0c2f1d0d7..08421de3183a2 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java @@ -55,8 +55,10 @@ import android.view.accessibility.MagnificationAnimationCallback; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.test.FakeSettingsProvider; +import com.android.server.LocalServices; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.accessibility.AccessibilityTraceManager; +import com.android.server.wm.WindowManagerInternal; import org.junit.After; import org.junit.Before; @@ -79,6 +81,7 @@ public class MagnificationControllerTest { private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; private static final int TEST_SERVICE_ID = 1; private static final Region MAGNIFICATION_REGION = new Region(0, 0, 500, 600); + private static final Rect TEST_RECT = new Rect(0, 50, 100, 51); private static final float MAGNIFIED_CENTER_X = 100; private static final float MAGNIFIED_CENTER_Y = 200; private static final float DEFAULT_SCALE = 3f; @@ -108,6 +111,11 @@ public class MagnificationControllerTest { private MagnificationController mMagnificationController; private FullScreenMagnificationControllerStubber mScreenMagnificationControllerStubber; + @Mock + private WindowManagerInternal mMockWindowManagerInternal; + @Mock + private WindowManagerInternal.AccessibilityControllerInternal mMockA11yController; + // To mock package-private class @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = @@ -117,6 +125,12 @@ public class MagnificationControllerTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); FakeSettingsProvider.clearSettingsProvider(); + + LocalServices.removeServiceForTest(WindowManagerInternal.class); + LocalServices.addService(WindowManagerInternal.class, mMockWindowManagerInternal); + when(mMockWindowManagerInternal.getAccessibilityController()).thenReturn( + mMockA11yController); + mMockResolver = new MockContentResolver(); mMockResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); when(mContext.getContentResolver()).thenReturn(mMockResolver); @@ -132,8 +146,8 @@ public class MagnificationControllerTest { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mScreenMagnificationControllerStubber = new FullScreenMagnificationControllerStubber( mScreenMagnificationController); - mMagnificationController = spy(new MagnificationController(mService, new Object(), mContext, - mScreenMagnificationController, mWindowMagnificationManager, mScaleProvider)); + mMagnificationController = new MagnificationController(mService, new Object(), mContext, + mScreenMagnificationController, mWindowMagnificationManager, mScaleProvider); mMagnificationController.setMagnificationCapabilities( Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL); @@ -439,16 +453,65 @@ public class MagnificationControllerTest { @Test public void onWindowMagnificationActivationState_windowActivated_logWindowDuration() { - mMagnificationController.onWindowMagnificationActivationState(TEST_DISPLAY, true); + MagnificationController spyController = spy(mMagnificationController); + spyController.onWindowMagnificationActivationState(TEST_DISPLAY, true); - mMagnificationController.onWindowMagnificationActivationState(TEST_DISPLAY, false); + spyController.onWindowMagnificationActivationState(TEST_DISPLAY, false); - verify(mMagnificationController).logMagnificationUsageState( + verify(spyController).logMagnificationUsageState( eq(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW), anyLong()); } @Test - public void onWinodwModeActivated_fullScreenIsActivatedByExternal_fullScreenIsDisabled() { + public void onRectangleOnScreenRequested_fullScreenIsActivated_fullScreenDispatchEvent() { + mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, + true); + WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks + callbacks = getUiChangesForAccessibilityCallbacks(); + + callbacks.onRectangleOnScreenRequested(TEST_DISPLAY, + TEST_RECT.left, TEST_RECT.top, TEST_RECT.right, TEST_RECT.bottom); + + verify(mScreenMagnificationController).onRectangleOnScreenRequested(eq(TEST_DISPLAY), + eq(TEST_RECT.left), eq(TEST_RECT.top), eq(TEST_RECT.right), eq(TEST_RECT.bottom)); + verify(mWindowMagnificationManager, never()).onRectangleOnScreenRequested(anyInt(), + anyInt(), anyInt(), anyInt(), anyInt()); + } + + @Test + public void onRectangleOnScreenRequested_fullScreenIsInactivated_noneDispatchEvent() { + mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, + true); + mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, + false); + WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks + callbacks = getUiChangesForAccessibilityCallbacks(); + + callbacks.onRectangleOnScreenRequested(TEST_DISPLAY, + TEST_RECT.left, TEST_RECT.top, TEST_RECT.right, TEST_RECT.bottom); + + verify(mScreenMagnificationController, never()).onRectangleOnScreenRequested(anyInt(), + anyInt(), anyInt(), anyInt(), anyInt()); + verify(mWindowMagnificationManager, never()).onRectangleOnScreenRequested(anyInt(), + anyInt(), anyInt(), anyInt(), anyInt()); + } + + @Test + public void onRectangleOnScreenRequested_NoneIsActivated_noneDispatchEvent() { + WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks + callbacks = getUiChangesForAccessibilityCallbacks(); + + callbacks.onRectangleOnScreenRequested(TEST_DISPLAY, + TEST_RECT.left, TEST_RECT.top, TEST_RECT.right, TEST_RECT.bottom); + + verify(mScreenMagnificationController, never()).onRectangleOnScreenRequested( + eq(TEST_DISPLAY), anyInt(), anyInt(), anyInt(), anyInt()); + verify(mWindowMagnificationManager, never()).onRectangleOnScreenRequested(anyInt(), + anyInt(), anyInt(), anyInt(), anyInt()); + } + + @Test + public void onWindowModeActivated_fullScreenIsActivatedByExternal_fullScreenIsDisabled() { mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y, true, TEST_SERVICE_ID); @@ -461,11 +524,12 @@ public class MagnificationControllerTest { @Test public void onFullScreenMagnificationActivationState_fullScreenActivated_logFullScreenDuration() { - mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); + MagnificationController spyController = spy(mMagnificationController); + spyController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); - mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, false); + spyController.onFullScreenMagnificationActivationState(TEST_DISPLAY, false); - verify(mMagnificationController).logMagnificationUsageState( + verify(spyController).logMagnificationUsageState( eq(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN), anyLong()); } @@ -627,43 +691,48 @@ public class MagnificationControllerTest { @Test public void imeWindowStateShown_windowMagnifying_logWindowMode() { - mMagnificationController.onWindowMagnificationActivationState(TEST_DISPLAY, true); + MagnificationController spyController = spy(mMagnificationController); + spyController.onWindowMagnificationActivationState(TEST_DISPLAY, true); - mMagnificationController.onImeWindowVisibilityChanged(true); + spyController.onImeWindowVisibilityChanged(true); - verify(mMagnificationController).logMagnificationModeWithIme( + verify(spyController).logMagnificationModeWithIme( eq(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)); } @Test public void imeWindowStateShown_fullScreenMagnifying_logFullScreenMode() { - mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); + MagnificationController spyController = spy(mMagnificationController); + spyController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); - mMagnificationController.onImeWindowVisibilityChanged(true); + spyController.onImeWindowVisibilityChanged(true); - verify(mMagnificationController).logMagnificationModeWithIme( + verify(spyController).logMagnificationModeWithIme( eq(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)); } @Test public void imeWindowStateShown_noMagnifying_noLogAnyMode() { - mMagnificationController.onImeWindowVisibilityChanged(true); + MagnificationController spyController = spy(mMagnificationController); + spyController.onImeWindowVisibilityChanged(true); - verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt()); + verify(spyController, never()).logMagnificationModeWithIme(anyInt()); } @Test public void imeWindowStateHidden_windowMagnifying_noLogAnyMode() { - mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); + MagnificationController spyController = spy(mMagnificationController); + spyController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); - verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt()); + verify(spyController, never()).logMagnificationModeWithIme(anyInt()); } @Test public void imeWindowStateHidden_fullScreenMagnifying_noLogAnyMode() { - mMagnificationController.onWindowMagnificationActivationState(TEST_DISPLAY, true); + MagnificationController spyController = spy(mMagnificationController); + spyController.onWindowMagnificationActivationState(TEST_DISPLAY, true); - verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt()); + verify(spyController, never()).logMagnificationModeWithIme(anyInt()); } @Test @@ -718,6 +787,17 @@ public class MagnificationControllerTest { MAGNIFIED_CENTER_X).setCenterY(MAGNIFIED_CENTER_Y).build(); } + private WindowManagerInternal.AccessibilityControllerInternal.UiChangesForAccessibilityCallbacks + getUiChangesForAccessibilityCallbacks() { + ArgumentCaptor captor = ArgumentCaptor.forClass( + WindowManagerInternal.AccessibilityControllerInternal + .UiChangesForAccessibilityCallbacks.class); + verify(mMockWindowManagerInternal.getAccessibilityController()) + .setUiChangesForAccessibilityCallbacks(captor.capture()); + return captor.getValue(); + } + /** * Stubs public methods to simulate the real beahviours. */