From 2b7842fc753b0c9b03d4018e00635ce2e4d644d4 Mon Sep 17 00:00:00 2001 From: Daniel Hsieh Date: Thu, 3 Mar 2022 11:15:42 +0000 Subject: [PATCH] Offsets an additional distance for requestRectangleOnScreen. In previous, requestRectangleOnScreen would only apply the shortest movement on the magnifier to the rectangle. However, it will make typing words out of the screen. Therefore, we add an additional distance for moving the magnifier to help a user know the surrounding context. Bug: 148882866 Test: atest FullScreenMagnificationControllerTest Change-Id: Iee7a4f13395ed8acf3ffa7df759542fcb08190f8 --- .../FullScreenMagnificationController.java | 35 ++++++++++++++++--- ...FullScreenMagnificationControllerTest.java | 12 +++++++ 2 files changed, 43 insertions(+), 4 deletions(-) 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 fa32452f389ec..ecc45eb743c60 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java @@ -18,6 +18,7 @@ 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.util.TypedValue.COMPLEX_UNIT_DIP; import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK; import static com.android.server.accessibility.AccessibilityManagerService.INVALID_SERVICE_ID; @@ -31,15 +32,20 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.CompatibilityInfo; import android.graphics.Rect; import android.graphics.Region; +import android.hardware.display.DisplayManagerInternal; import android.os.Handler; import android.os.Message; import android.text.TextUtils; +import android.util.DisplayMetrics; import android.util.MathUtils; import android.util.Slog; import android.util.SparseArray; +import android.util.TypedValue; import android.view.Display; +import android.view.DisplayInfo; import android.view.MagnificationSpec; import android.view.View; import android.view.accessibility.MagnificationAnimationCallback; @@ -93,6 +99,8 @@ public class FullScreenMagnificationController implements // Whether the following typing focus feature for magnification is enabled. private boolean mMagnificationFollowTypingEnabled = true; + private final DisplayManagerInternal mDisplayManagerInternal; + /** * This class implements {@link WindowManagerInternal.MagnificationCallbacks} and holds * magnification information per display. @@ -395,6 +403,18 @@ public class FullScreenMagnificationController implements outRegion.set(mMagnificationRegion); } + private DisplayMetrics getDisplayMetricsForId() { + final DisplayMetrics outMetrics = new DisplayMetrics(); + final DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId); + if (displayInfo != null) { + displayInfo.getLogicalMetrics(outMetrics, + CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); + } else { + outMetrics.setToDefaults(); + } + return outMetrics; + } + void requestRectangleOnScreen(int left, int top, int right, int bottom) { synchronized (mLock) { final Rect magnifiedFrame = mTempRect; @@ -408,6 +428,12 @@ public class FullScreenMagnificationController implements final float scrollX; final float scrollY; + // We offset an additional distance for a user to know the surrounding context. + DisplayMetrics metrics = getDisplayMetricsForId(); + final float offsetViewportX = (float) magnifFrameInScreenCoords.width() / 4; + final float offsetViewportY = + TypedValue.applyDimension(COMPLEX_UNIT_DIP, 10, metrics); + if (right - left > magnifFrameInScreenCoords.width()) { final int direction = TextUtils .getLayoutDirectionFromLocale(Locale.getDefault()); @@ -417,9 +443,9 @@ public class FullScreenMagnificationController implements scrollX = right - magnifFrameInScreenCoords.right; } } else if (left < magnifFrameInScreenCoords.left) { - scrollX = left - magnifFrameInScreenCoords.left; + scrollX = left - magnifFrameInScreenCoords.left - offsetViewportX; } else if (right > magnifFrameInScreenCoords.right) { - scrollX = right - magnifFrameInScreenCoords.right; + scrollX = right - magnifFrameInScreenCoords.right + offsetViewportX; } else { scrollX = 0; } @@ -427,9 +453,9 @@ public class FullScreenMagnificationController implements if (bottom - top > magnifFrameInScreenCoords.height()) { scrollY = top - magnifFrameInScreenCoords.top; } else if (top < magnifFrameInScreenCoords.top) { - scrollY = top - magnifFrameInScreenCoords.top; + scrollY = top - magnifFrameInScreenCoords.top - offsetViewportY; } else if (bottom > magnifFrameInScreenCoords.bottom) { - scrollY = bottom - magnifFrameInScreenCoords.bottom; + scrollY = bottom - magnifFrameInScreenCoords.bottom + offsetViewportY; } else { scrollY = 0; } @@ -687,6 +713,7 @@ public class FullScreenMagnificationController implements mScreenStateObserver = new ScreenStateObserver(mControllerCtx.getContext(), this); mMagnificationInfoChangedCallback = magnificationInfoChangedCallback; mScaleProvider = scaleProvider; + mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); } /** 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 f3a0b7fa1ea73..0780d219dc80a 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 @@ -28,6 +28,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -45,13 +46,16 @@ import android.content.IntentFilter; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region; +import android.hardware.display.DisplayManagerInternal; import android.os.Looper; +import android.view.DisplayInfo; import android.view.MagnificationSpec; import android.view.accessibility.MagnificationAnimationCallback; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.server.LocalServices; import com.android.server.accessibility.AccessibilityTraceManager; import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.wm.WindowManagerInternal; @@ -113,6 +117,8 @@ public class FullScreenMagnificationControllerTest { FullScreenMagnificationController mFullScreenMagnificationController; + public DisplayManagerInternal mDisplayManagerInternalMock = mock(DisplayManagerInternal.class); + @Before public void setUp() { Looper looper = InstrumentationRegistry.getContext().getMainLooper(); @@ -125,6 +131,12 @@ public class FullScreenMagnificationControllerTest { when(mMockControllerCtx.getAnimationDuration()).thenReturn(1000L); initMockWindowManager(); + final DisplayInfo displayInfo = new DisplayInfo(); + displayInfo.logicalDensityDpi = 300; + doReturn(displayInfo).when(mDisplayManagerInternalMock).getDisplayInfo(anyInt()); + LocalServices.removeServiceForTest(DisplayManagerInternal.class); + LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock); + mFullScreenMagnificationController = new FullScreenMagnificationController( mMockControllerCtx, new Object(), mRequestObserver, mScaleProvider); }