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 a958209669264..fa32452f389ec 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java @@ -303,7 +303,7 @@ public class FullScreenMagnificationController implements public void onImeWindowVisibilityChanged(boolean shown) { final Message m = PooledLambda.obtainMessage( FullScreenMagnificationController::notifyImeWindowVisibilityChanged, - FullScreenMagnificationController.this, shown); + FullScreenMagnificationController.this, mDisplayId, shown); mControllerCtx.getHandler().sendMessage(m); } @@ -1215,11 +1215,12 @@ public class FullScreenMagnificationController implements /** * Notifies that the IME window visibility changed. * + * @param displayId the logical display id * @param shown {@code true} means the IME window shows on the screen. Otherwise it's * hidden. */ - void notifyImeWindowVisibilityChanged(boolean shown) { - mMagnificationInfoChangedCallback.onImeWindowVisibilityChanged(shown); + void notifyImeWindowVisibilityChanged(int displayId, boolean shown) { + mMagnificationInfoChangedCallback.onImeWindowVisibilityChanged(displayId, shown); } /** @@ -1609,17 +1610,19 @@ public class FullScreenMagnificationController implements * Called when the state of the magnification activation is changed. * It is for the logging data of the magnification activation state. * - * @param displayId The logical display id. + * @param displayId the logical display id * @param activated {@code true} if the magnification is activated, otherwise {@code false}. */ void onFullScreenMagnificationActivationState(int displayId, boolean activated); /** * Called when the IME window visibility changed. + * + * @param displayId the logical display id * @param shown {@code true} means the IME window shows on the screen. Otherwise it's * hidden. */ - void onImeWindowVisibilityChanged(boolean shown); + void onImeWindowVisibilityChanged(int displayId, boolean shown); /** * Called when the magnification spec changed. 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 09e82c787c904..fcfba1cfc316e 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -38,6 +38,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.view.accessibility.MagnificationAnimationCallback; import com.android.internal.accessibility.util.AccessibilityStatsLogUtils; @@ -99,7 +100,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb // Track the active user to reset the magnification and get the associated user settings. private @UserIdInt int mUserId = UserHandle.USER_SYSTEM; @GuardedBy("mLock") - private boolean mImeWindowVisible = false; + private final SparseBooleanArray mIsImeVisibleArray = new SparseBooleanArray(); private long mWindowModeEnabledTime = 0; private long mFullScreenModeEnabledTime = 0; @@ -377,7 +378,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); mLastActivatedMode = mActivatedMode; } - logMagnificationModeWithImeOnIfNeeded(); + logMagnificationModeWithImeOnIfNeeded(displayId); disableFullScreenMagnificationIfNeeded(displayId); } else { logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, @@ -432,7 +433,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb setActivatedModeAndSwitchDelegate(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); mLastActivatedMode = mActivatedMode; } - logMagnificationModeWithImeOnIfNeeded(); + logMagnificationModeWithImeOnIfNeeded(displayId); disableWindowMagnificationIfNeeded(displayId); } else { logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, @@ -454,12 +455,12 @@ public class MagnificationController implements WindowMagnificationManager.Callb } @Override - public void onImeWindowVisibilityChanged(boolean shown) { + public void onImeWindowVisibilityChanged(int displayId, boolean shown) { synchronized (mLock) { - mImeWindowVisible = shown; + mIsImeVisibleArray.put(displayId, shown); } - getWindowMagnificationMgr().onImeWindowVisibilityChanged(shown); - logMagnificationModeWithImeOnIfNeeded(); + getWindowMagnificationMgr().onImeWindowVisibilityChanged(displayId, shown); + logMagnificationModeWithImeOnIfNeeded(displayId); } /** @@ -575,11 +576,12 @@ public class MagnificationController implements WindowMagnificationManager.Callb } } - private void logMagnificationModeWithImeOnIfNeeded() { + private void logMagnificationModeWithImeOnIfNeeded(int displayId) { final int mode; synchronized (mLock) { - if (!mImeWindowVisible || mActivatedMode == ACCESSIBILITY_MAGNIFICATION_MODE_NONE) { + if (!mIsImeVisibleArray.get(displayId, false) + || mActivatedMode == ACCESSIBILITY_MAGNIFICATION_MODE_NONE) { return; } mode = mActivatedMode; 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 50e65809f67e2..f1b6a996b6dba 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java @@ -38,6 +38,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.view.MotionEvent; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; @@ -99,6 +100,7 @@ public class WindowMagnificationManager implements private SparseArray mWindowMagnifiers = new SparseArray<>(); // Whether the following typing focus feature for magnification is enabled. private boolean mMagnificationFollowTypingEnabled = true; + private final SparseBooleanArray mIsImeVisibleArray = new SparseBooleanArray(); private boolean mReceiverRegistered = false; @VisibleForTesting @@ -315,7 +317,8 @@ public class WindowMagnificationManager implements float toCenterY = (float) (top + bottom) / 2; synchronized (mLock) { - if (!isPositionInSourceBounds(displayId, toCenterX, toCenterY) + if (mIsImeVisibleArray.get(displayId, false) + && !isPositionInSourceBounds(displayId, toCenterX, toCenterY) && isTrackingTypingFocusEnabled(displayId)) { moveWindowMagnifierToPositionInternal(displayId, toCenterX, toCenterY, STUB_ANIMATION_CALLBACK); @@ -387,7 +390,8 @@ public class WindowMagnificationManager implements * * @param shown {@code true} means the IME window shows on the screen. Otherwise, it's hidden. */ - void onImeWindowVisibilityChanged(boolean shown) { + void onImeWindowVisibilityChanged(int displayId, boolean shown) { + mIsImeVisibleArray.put(displayId, shown); if (shown) { enableAllTrackingTypingFocus(); } diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 57f77d5b7b945..e37b08f417f20 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -79,6 +79,7 @@ import android.util.ArraySet; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.TypedValue; import android.util.proto.ProtoOutputStream; import android.view.Display; @@ -138,7 +139,7 @@ final class AccessibilityController { new SparseArray<>(); private SparseArray mFocusedWindow = new SparseArray<>(); private int mFocusedDisplay = -1; - private boolean mIsImeVisible = false; + private final SparseBooleanArray mIsImeVisibleArray = new SparseBooleanArray(); // Set to true if initializing window population complete. private boolean mAllObserversInitialized = true; private final AccessibilityWindowsPopulator mAccessibilityWindowsPopulator; @@ -167,8 +168,11 @@ final class AccessibilityController { if (dc != null) { final Display display = dc.getDisplay(); if (display != null && display.getType() != Display.TYPE_OVERLAY) { - mDisplayMagnifiers.put(displayId, new DisplayMagnifier( - mService, dc, display, callbacks)); + final DisplayMagnifier magnifier = new DisplayMagnifier( + mService, dc, display, callbacks); + magnifier.notifyImeWindowVisibilityChanged( + mIsImeVisibleArray.get(displayId, false)); + mDisplayMagnifiers.put(displayId, magnifier); result = true; } } @@ -483,11 +487,13 @@ final class AccessibilityController { mAccessibilityTracing.logTrace(TAG + ".updateImeVisibilityIfNeeded", FLAGS_MAGNIFICATION_CALLBACK, "displayId=" + displayId + ";shown=" + shown); } - if (mIsImeVisible == shown) { + + final boolean isDisplayImeVisible = mIsImeVisibleArray.get(displayId, false); + if (isDisplayImeVisible == shown) { return; } - mIsImeVisible = shown; + mIsImeVisibleArray.put(displayId, shown); final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); if (displayMagnifier != null) { displayMagnifier.notifyImeWindowVisibilityChanged(shown); @@ -523,6 +529,7 @@ final class AccessibilityController { } public void onDisplayRemoved(int displayId) { + mIsImeVisibleArray.delete(displayId); mFocusedWindow.remove(displayId); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java index 3ce2ed84d3e8f..f3a0b7fa1ea73 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java @@ -1158,7 +1158,7 @@ public class FullScreenMagnificationControllerTest { MagnificationCallbacks callbacks = getMagnificationCallbacks(DISPLAY_0); callbacks.onImeWindowVisibilityChanged(true); mMessageCapturingHandler.sendAllMessages(); - verify(mRequestObserver).onImeWindowVisibilityChanged(eq(true)); + verify(mRequestObserver).onImeWindowVisibilityChanged(eq(DISPLAY_0), eq(true)); } private void setScaleToMagnifying() { 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 ec59090240f3c..ddbee988cfcb9 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 @@ -748,7 +748,7 @@ public class MagnificationControllerTest { MagnificationController spyController = spy(mMagnificationController); spyController.onWindowMagnificationActivationState(TEST_DISPLAY, true); - spyController.onImeWindowVisibilityChanged(true); + spyController.onImeWindowVisibilityChanged(TEST_DISPLAY, true); verify(spyController).logMagnificationModeWithIme( eq(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)); @@ -759,7 +759,7 @@ public class MagnificationControllerTest { MagnificationController spyController = spy(mMagnificationController); spyController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true); - spyController.onImeWindowVisibilityChanged(true); + spyController.onImeWindowVisibilityChanged(TEST_DISPLAY, true); verify(spyController).logMagnificationModeWithIme( eq(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)); @@ -768,7 +768,7 @@ public class MagnificationControllerTest { @Test public void imeWindowStateShown_noMagnifying_noLogAnyMode() { MagnificationController spyController = spy(mMagnificationController); - spyController.onImeWindowVisibilityChanged(true); + spyController.onImeWindowVisibilityChanged(TEST_DISPLAY, true); verify(spyController, never()).logMagnificationModeWithIme(anyInt()); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java index 2f75493e5e2c3..096b63cbf0044 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java @@ -281,6 +281,7 @@ public class WindowMagnificationManagerTest { throws RemoteException { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); @@ -302,6 +303,7 @@ public class WindowMagnificationManagerTest { final float distanceY = 10f; mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); @@ -320,6 +322,7 @@ public class WindowMagnificationManagerTest { throws RemoteException { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); @@ -331,12 +334,29 @@ public class WindowMagnificationManagerTest { verify(mMockConnection.getConnection(), never()) .moveWindowMagnifierToPosition(anyInt(), anyFloat(), anyFloat(), any()); } + @Test + public void onRectangleOnScreenRequested_imeVisibilityDefaultInvisible_withoutMovingMagnifier() + throws RemoteException { + mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + final Region outRegion = new Region(); + mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); + final Rect requestedRect = outRegion.getBounds(); + requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); + + mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); + + verify(mMockConnection.getConnection(), never()) + .moveWindowMagnifierToPosition(anyInt(), anyFloat(), anyFloat(), any()); + } @Test public void onRectangleOnScreenRequested_trackingEnabledByDefault_movingMagnifier() throws RemoteException { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); @@ -350,13 +370,33 @@ public class WindowMagnificationManagerTest { any(IRemoteMagnificationAnimationCallback.class)); } + @Test + public void onRectangleOnScreenRequested_imeInvisible_withoutMovingMagnifier() + throws RemoteException { + mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); + mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); + final Region outRegion = new Region(); + mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); + final Rect requestedRect = outRegion.getBounds(); + requestedRect.offsetTo(requestedRect.right + 10, requestedRect.bottom + 10); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, false); + + mWindowMagnificationManager.onRectangleOnScreenRequested(TEST_DISPLAY, + requestedRect.left, requestedRect.top, requestedRect.right, requestedRect.bottom); + + verify(mMockConnection.getConnection(), never()) + .moveWindowMagnifierToPosition(anyInt(), anyFloat(), anyFloat(), any()); + } + @Test public void onRectangleOnScreenRequested_trackingEnabledByDragAndReset_movingMagnifier() throws RemoteException { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); mMockConnection.getConnectionCallback().onMove(TEST_DISPLAY); - mWindowMagnificationManager.onImeWindowVisibilityChanged(true); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region outRegion = new Region(); mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, outRegion); final Rect requestedRect = outRegion.getBounds(); @@ -374,6 +414,7 @@ public class WindowMagnificationManagerTest { public void onRectangleOnScreenRequested_followTypingIsDisabled_withoutMovingMagnifier() { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); final Region beforeRegion = new Region(); mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion); final Rect requestedRect = beforeRegion.getBounds(); @@ -392,6 +433,7 @@ public class WindowMagnificationManagerTest { public void onRectangleOnScreenRequested_trackingDisabled_withoutMovingMagnifier() { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); mWindowMagnificationManager.setTrackingTypingFocusEnabled(TEST_DISPLAY, false); final Region beforeRegion = new Region(); mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion); @@ -411,6 +453,7 @@ public class WindowMagnificationManagerTest { throws RemoteException { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f); + mWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, true); mWindowMagnificationManager.setTrackingTypingFocusEnabled(TEST_DISPLAY, false); final Region beforeRegion = new Region(); mWindowMagnificationManager.getMagnificationSourceBounds(TEST_DISPLAY, beforeRegion);