Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2d58ee0 authored by Candice's avatar Candice
Browse files

fix(window magnification): Update the boundary for window magnifier at the bottom

To avoid gesture conflicts between the window magnifier and system
gestures at the bottom of the screen, we don't allow the window magnifer
to overlap with the system gesture botton inset.

Bug: 380320995
Test: atest WindowMagnificationControllerTest
Flag: com.android.systemui.update_window_magnifier_bottom_boundary
Change-Id: I11a56f586ffdedf63f6321f9ba01e8e71e4fe7a5
parent fff82706
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -203,8 +203,8 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp
            return;
        }
        final float currentScale = mController.getScale();
        final float currentCenterX = mController.getCenterX();
        final float currentCenterY = mController.getCenterY();
        final float currentCenterX = mController.getMagnificationFrameCenterX();
        final float currentCenterY = mController.getMagnificationFrameCenterY();

        if (mState == STATE_DISABLED) {
            // We don't need to offset the center during the animation.
+43 −7
Original line number Diff line number Diff line
@@ -497,6 +497,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
        if (configDiff == 0) {
            return;
        }
        if (Flags.updateWindowMagnifierBottomBoundary()) {
            updateSystemGestureInsetsTop();
        }
        if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
            onRotate();
        }
@@ -542,8 +545,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
        }
        mWindowBounds.set(currentWindowBounds);
        final Size windowFrameSize = restoreMagnificationWindowFrameIndexAndSizeIfPossible();
        final float newCenterX = (getCenterX()) * mWindowBounds.width() / oldWindowBounds.width();
        final float newCenterY = (getCenterY()) * mWindowBounds.height() / oldWindowBounds.height();
        final float newCenterX =
                (getMagnificationFrameCenterX()) * mWindowBounds.width() / oldWindowBounds.width();
        final float newCenterY =
                (getMagnificationFrameCenterY()) * mWindowBounds.height()
                        / oldWindowBounds.height();

        setMagnificationFrame(windowFrameSize.getWidth(), windowFrameSize.getHeight(),
                (int) newCenterX, (int) newCenterY);
@@ -672,10 +678,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
    }

    private void onWindowInsetChanged() {
        if (Flags.updateWindowMagnifierBottomBoundary()) {
            updateSystemGestureInsetsTop();
        } else {
            if (updateSystemGestureInsetsTop()) {
                updateSystemUIStateIfNeeded();
            }
        }
    }

    private void applyTouchableRegion() {
        // Sometimes this can get posted and run after deleteWindowMagnification() is called.
@@ -939,7 +949,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
        final int x = MathUtils.clamp(mMagnificationFrame.left - mMirrorSurfaceMargin, minX, maxX);

        final int minY = -mOuterBorderSize;
        final int maxY = mWindowBounds.bottom - height + mOuterBorderSize;
        final int maxY = Flags.updateWindowMagnifierBottomBoundary()
                ? mSystemGestureTop - height + mOuterBorderSize
                : mWindowBounds.bottom - height + mOuterBorderSize;
        final int y = MathUtils.clamp(mMagnificationFrame.top - mMirrorSurfaceMargin, minY, maxY);

        if (computeWindowSize) {
@@ -1098,6 +1110,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
    }

    private void updateSysUIState(boolean force) {
        if (Flags.updateWindowMagnifierBottomBoundary()) {
            return;
        }

        final boolean overlap = isActivated() && mSystemGestureTop > 0
                && mMirrorViewBounds.bottom > mSystemGestureTop;
        if (force || overlap != mOverlapWithGestureInsets) {
@@ -1313,7 +1329,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
     *
     * @return the X coordinate. {@link Float#NaN} if the window is invisible.
     */
    float getCenterX() {
    float getMagnificationFrameCenterX() {
        return isActivated() ? mMagnificationFrame.exactCenterX() : Float.NaN;
    }

@@ -1322,10 +1338,30 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
     *
     * @return the Y coordinate. {@link Float#NaN} if the window is invisible.
     */
    float getCenterY() {
    float getMagnificationFrameCenterY() {
        return isActivated() ? mMagnificationFrame.exactCenterY() : Float.NaN;
    }

    /**
     * Returns the screen-relative X coordinate of the center of the magnifier window.
     * This could be different from the position of the magnification frame since the magnification
     * frame could overlap with the bottom inset, but the magnifier window would not.
     * @return the Y coordinate. {@link Float#NaN} if the window is invisible.
     */
    float getMagnifierWindowX() {
        return isActivated() ? (float) mMirrorViewBounds.left : Float.NaN;
    }

    /**
     * Returns the screen-relative Y coordinate of the center of the magnifier window.
     * This could be different from the position of the magnification frame since the magnification
     * frame could overlap with the bottom inset, but the magnifier window would not.
     * @return the Y coordinate. {@link Float#NaN} if the window is invisible.
     */
    float getMagnifierWindowY() {
        return isActivated() ? (float) mMirrorViewBounds.top : Float.NaN;
    }


    @VisibleForTesting
    boolean isDiagonalScrollingEnabled() {
+16 −16
Original line number Diff line number Diff line
@@ -242,8 +242,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                    targetCenterX, targetCenterY, mAnimationCallback2);
            mCurrentScale.set(mController.getScale());
            mCurrentCenterX.set(mController.getCenterX());
            mCurrentCenterY.set(mController.getCenterY());
            mCurrentCenterX.set(mController.getMagnificationFrameCenterX());
            mCurrentCenterY.set(mController.getMagnificationFrameCenterY());
            advanceTimeBy(mWaitAnimationDuration);
        });

@@ -297,8 +297,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                    targetCenterX, targetCenterY, mAnimationCallback);
            mCurrentScale.set(mController.getScale());
            mCurrentCenterX.set(mController.getCenterX());
            mCurrentCenterY.set(mController.getCenterY());
            mCurrentCenterX.set(mController.getMagnificationFrameCenterX());
            mCurrentCenterY.set(mController.getMagnificationFrameCenterY());
            advanceTimeBy(mWaitAnimationDuration);
        });

@@ -339,8 +339,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                    targetCenterX, targetCenterY, mAnimationCallback);
            mCurrentScale.set(mController.getScale());
            mCurrentCenterX.set(mController.getCenterX());
            mCurrentCenterY.set(mController.getCenterY());
            mCurrentCenterX.set(mController.getMagnificationFrameCenterX());
            mCurrentCenterY.set(mController.getMagnificationFrameCenterY());
            advanceTimeBy(mWaitAnimationDuration);
        });

@@ -375,8 +375,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                    targetCenterX, targetCenterY, mAnimationCallback);
            mCurrentScale.set(mController.getScale());
            mCurrentCenterX.set(mController.getCenterX());
            mCurrentCenterY.set(mController.getCenterY());
            mCurrentCenterX.set(mController.getMagnificationFrameCenterX());
            mCurrentCenterY.set(mController.getMagnificationFrameCenterY());
            advanceTimeBy(mWaitAnimationDuration);
        });

@@ -463,8 +463,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                    targetCenterX, targetCenterY, mAnimationCallback2);
            mCurrentScale.set(mController.getScale());
            mCurrentCenterX.set(mController.getCenterX());
            mCurrentCenterY.set(mController.getCenterY());
            mCurrentCenterX.set(mController.getMagnificationFrameCenterX());
            mCurrentCenterY.set(mController.getMagnificationFrameCenterY());
        });

        // Current spec shouldn't match given spec.
@@ -548,8 +548,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                    targetCenterX, targetCenterY, mAnimationCallback2);
            mCurrentScale.set(mController.getScale());
            mCurrentCenterX.set(mController.getCenterX());
            mCurrentCenterY.set(mController.getCenterY());
            mCurrentCenterX.set(mController.getMagnificationFrameCenterX());
            mCurrentCenterY.set(mController.getMagnificationFrameCenterY());
            advanceTimeBy(mWaitAnimationDuration);
        });

@@ -777,8 +777,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
            mWindowMagnificationAnimationController.deleteWindowMagnification(
                    mAnimationCallback2);
            mCurrentScale.set(mController.getScale());
            mCurrentCenterX.set(mController.getCenterX());
            mCurrentCenterY.set(mController.getCenterY());
            mCurrentCenterX.set(mController.getMagnificationFrameCenterX());
            mCurrentCenterY.set(mController.getMagnificationFrameCenterY());
            // ValueAnimator.reverse() could not work correctly with the AnimatorTestRule since it
            // is using SystemClock in reverse() (b/305731398). Therefore, we call end() on the
            // animator directly to verify the result of animation is correct instead of querying
@@ -940,8 +940,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
    private void verifyFinalSpec(float expectedScale, float expectedCenterX,
            float expectedCenterY) {
        assertEquals(expectedScale, mController.getScale(), 0f);
        assertEquals(expectedCenterX, mController.getCenterX(), 0f);
        assertEquals(expectedCenterY, mController.getCenterY(), 0f);
        assertEquals(expectedCenterX, mController.getMagnificationFrameCenterX(), 0f);
        assertEquals(expectedCenterY, mController.getMagnificationFrameCenterY(), 0f);
    }

    private void enableWindowMagnificationWithoutAnimation() {
+58 −21
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@ import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.os.SystemClock;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.provider.Settings;
import android.testing.TestableLooper;
import android.testing.TestableResources;
@@ -88,6 +90,7 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;

import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.AnimatorTestRule;
import com.android.systemui.kosmos.KosmosJavaAdapter;
@@ -128,6 +131,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
    public final AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule(/* test= */ null);

    private static final int LAYOUT_CHANGE_TIMEOUT_MS = 5000;
    private static final int INSET_BOTTOM = 10;
    @Mock
    private MirrorWindowControl mMirrorWindowControl;
    @Mock
@@ -329,9 +333,9 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
        final ArgumentCaptor<Rect> sourceBoundsCaptor = ArgumentCaptor.forClass(Rect.class);
        verify(mWindowMagnifierCallback, atLeast(2)).onSourceBoundsChanged(
                (eq(mContext.getDisplayId())), sourceBoundsCaptor.capture());
        assertThat(mWindowMagnificationController.getCenterX())
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterX())
                .isEqualTo(sourceBoundsCaptor.getValue().exactCenterX());
        assertThat(mWindowMagnificationController.getCenterY())
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterY())
                .isEqualTo(sourceBoundsCaptor.getValue().exactCenterY());
    }

@@ -382,6 +386,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
    }

    @Test
    @DisableFlags(Flags.FLAG_UPDATE_WINDOW_MAGNIFIER_BOTTOM_BOUNDARY)
    public void deleteWindowMagnification_enableAtTheBottom_overlapFlagIsFalse() {
        final WindowManager wm = mContext.getSystemService(WindowManager.class);
        final Rect bounds = wm.getCurrentWindowMetrics().getBounds();
@@ -457,12 +462,14 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
        verify(mAnimationCallback, never()).onResult(eq(false));
        verify(mWindowMagnifierCallback, timeout(LAYOUT_CHANGE_TIMEOUT_MS))
                .onSourceBoundsChanged((eq(mContext.getDisplayId())), sourceBoundsCaptor.capture());
        assertThat(mWindowMagnificationController.getCenterX())
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterX())
                .isEqualTo(sourceBoundsCaptor.getValue().exactCenterX());
        assertThat(mWindowMagnificationController.getCenterY())
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterY())
                .isEqualTo(sourceBoundsCaptor.getValue().exactCenterY());
        assertThat(mWindowMagnificationController.getCenterX()).isEqualTo(targetCenterX);
        assertThat(mWindowMagnificationController.getCenterY()).isEqualTo(targetCenterY);
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterX())
                .isEqualTo(targetCenterX);
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterY())
                .isEqualTo(targetCenterY);
    }

    @Test
@@ -498,12 +505,14 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
        verify(mAnimationCallback, times(3)).onResult(eq(false));
        verify(mWindowMagnifierCallback, timeout(LAYOUT_CHANGE_TIMEOUT_MS))
                .onSourceBoundsChanged((eq(mContext.getDisplayId())), sourceBoundsCaptor.capture());
        assertThat(mWindowMagnificationController.getCenterX())
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterX())
                .isEqualTo(sourceBoundsCaptor.getValue().exactCenterX());
        assertThat(mWindowMagnificationController.getCenterY())
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterY())
                .isEqualTo(sourceBoundsCaptor.getValue().exactCenterY());
        assertThat(mWindowMagnificationController.getCenterX()).isEqualTo(centerX + 40);
        assertThat(mWindowMagnificationController.getCenterY()).isEqualTo(centerY + 40);
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterX())
                .isEqualTo(centerX + 40);
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterY())
                .isEqualTo(centerY + 40);
    }

    @Test
@@ -545,8 +554,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN,
                    magnifiedCenter.x, magnifiedCenter.y);
            // Get the center again in case the center we set is out of screen.
            magnifiedCenter.set(mWindowMagnificationController.getCenterX(),
                    mWindowMagnificationController.getCenterY());
            magnifiedCenter.set(mWindowMagnificationController.getMagnificationFrameCenterX(),
                    mWindowMagnificationController.getMagnificationFrameCenterY());
        });
        // Rotate the window clockwise 90 degree.
        windowBounds.set(windowBounds.top, windowBounds.left, windowBounds.bottom,
@@ -559,8 +568,9 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
        assertThat(mWindowMagnificationController.mRotation).isEqualTo(newRotation);
        final PointF expectedCenter = new PointF(magnifiedCenter.y,
                displayWidth - magnifiedCenter.x);
        final PointF actualCenter = new PointF(mWindowMagnificationController.getCenterX(),
                mWindowMagnificationController.getCenterY());
        final PointF actualCenter =
                new PointF(mWindowMagnificationController.getMagnificationFrameCenterX(),
                        mWindowMagnificationController.getMagnificationFrameCenterY());
        assertThat(actualCenter).isEqualTo(expectedCenter);
    }

@@ -603,10 +613,10 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
        });

        // The ratio of center to window size should be the same.
        assertThat(mWindowMagnificationController.getCenterX() / testWindowBounds.width())
                .isEqualTo(expectedRatio);
        assertThat(mWindowMagnificationController.getCenterY() / testWindowBounds.height())
                .isEqualTo(expectedRatio);
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterX()
                / testWindowBounds.width()).isEqualTo(expectedRatio);
        assertThat(mWindowMagnificationController.getMagnificationFrameCenterY()
                / testWindowBounds.height()).isEqualTo(expectedRatio);
    }

    @Test
@@ -1175,6 +1185,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
    }

    @Test
    @DisableFlags(Flags.FLAG_UPDATE_WINDOW_MAGNIFIER_BOTTOM_BOUNDARY)
    public void moveWindowMagnificationToTheBottom_enabledWithGestureInset_overlapFlagIsTrue() {
        final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
        setSystemGestureInsets();
@@ -1190,6 +1201,30 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
        ReferenceTestUtils.waitForCondition(() -> hasMagnificationOverlapFlag());
    }

    @Test
    @EnableFlags(Flags.FLAG_UPDATE_WINDOW_MAGNIFIER_BOTTOM_BOUNDARY)
    public void moveWindowMagnificationToTheBottom_stopsAtSystemGestureTop() {
        final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
        setSystemGestureInsets();
        mInstrumentation.runOnMainSync(() -> {
            mWindowMagnificationController.updateWindowMagnificationInternal(Float.NaN, Float.NaN,
                    Float.NaN);
        });

        ViewGroup.LayoutParams params = mSurfaceControlViewHost.getView().getLayoutParams();
        final int mOuterBorderSize = mResources.getDimensionPixelSize(
                R.dimen.magnification_outer_border_margin);

        final float expectedY =
                (float) (bounds.bottom - INSET_BOTTOM - params.height + mOuterBorderSize);

        mInstrumentation.runOnMainSync(() -> {
            mWindowMagnificationController.moveWindowMagnifier(0, bounds.height());
        });

        assertThat(mWindowMagnificationController.getMagnifierWindowY()).isEqualTo(expectedY);
    }

    @Test
    public void moveWindowMagnificationToRightEdge_dragHandleMovesToLeftAndUpdatesTapExcludeRegion()
            throws RemoteException {
@@ -1445,8 +1480,10 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
        mInstrumentation.runOnMainSync(() -> {
            mWindowMagnificationController.setWindowSizeAndCenter(minimumWindowSize,
                    minimumWindowSize, bounds.right, bounds.bottom);
            magnificationCenterX.set((int) mWindowMagnificationController.getCenterX());
            magnificationCenterY.set((int) mWindowMagnificationController.getCenterY());
            magnificationCenterX.set(
                    (int) mWindowMagnificationController.getMagnificationFrameCenterX());
            magnificationCenterY.set(
                    (int) mWindowMagnificationController.getMagnificationFrameCenterY());
        });

        assertThat(magnificationCenterX.get()).isLessThan(bounds.right);
@@ -1501,7 +1538,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {

    private void setSystemGestureInsets() {
        final WindowInsets testInsets = new WindowInsets.Builder()
                .setInsets(systemGestures(), Insets.of(0, 0, 0, 10))
                .setInsets(systemGestures(), Insets.of(0, 0, 0, INSET_BOTTOM))
                .build();
        mWindowManager.setWindowInsets(testInsets);
    }