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

Commit df256ae8 authored by Himanshu Jaju's avatar Himanshu Jaju Committed by Winson Chung
Browse files

Add screen size to touch regions cache.

The general design for foldable devices contains a smaller screen and a
larger screen. Hence we need to move from caching based on rotation to
caching based on {display size, rotation} tuple.

Test: Manual on fold2
Bug: 172240450
Change-Id: I445a7545e684134d7d880f957bb97ff847b726b7
parent fd03d04a
Loading
Loading
Loading
Loading
+71 −27
Original line number Diff line number Diff line
@@ -43,8 +43,18 @@ import org.robolectric.RobolectricTestRunner;

@RunWith(RobolectricTestRunner.class)
public class OrientationTouchTransformerTest {
    private static final int SIZE_WIDTH = 1080;
    private static final int SIZE_HEIGHT = 2280;
    static class ScreenSize {
        int mHeight;
        int mWidth;

        ScreenSize(int height, int width) {
            mHeight = height;
            mWidth = width;
        }
    }

    private static final ScreenSize NORMAL_SCREEN_SIZE = new ScreenSize(2280, 1080);
    private static final ScreenSize LARGE_SCREEN_SIZE = new ScreenSize(3280, 1080);
    private static final float DENSITY_DISPLAY_METRICS = 3.0f;

    private OrientationTouchTransformer mTouchTransformer;
@@ -63,14 +73,16 @@ public class OrientationTouchTransformerTest {
        DisplayMetrics mockDisplayMetrics = new DisplayMetrics();
        mockDisplayMetrics.density = DENSITY_DISPLAY_METRICS;
        when(mResources.getDisplayMetrics()).thenReturn(mockDisplayMetrics);
        mInfo = createDisplayInfo(Surface.ROTATION_0);
        mInfo = createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_0);
        mTouchTransformer = new OrientationTouchTransformer(mResources, NO_BUTTON, () -> 0);
    }

    @Test
    public void disabledMultipleRegions_shouldOverrideFirstRegion() {
        float portraitRegionY = generateTouchRegionHeight(Surface.ROTATION_0) + 1;
        float landscapeRegionY = generateTouchRegionHeight(Surface.ROTATION_90) + 1;
        float portraitRegionY =
                generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0) + 1;
        float landscapeRegionY =
                generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;

        mTouchTransformer.createOrAddTouchRegion(mInfo);
        tapAndAssertTrue(100, portraitRegionY,
@@ -83,7 +95,8 @@ public class OrientationTouchTransformerTest {
                event -> mTouchTransformer.touchInAssistantRegion(event));

        // Override region
        mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90));
        mTouchTransformer
            .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
        tapAndAssertFalse(100, portraitRegionY,
                event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
        tapAndAssertTrue(100, landscapeRegionY,
@@ -107,10 +120,13 @@ public class OrientationTouchTransformerTest {

    @Test
    public void enableMultipleRegions_shouldOverrideFirstRegion() {
        float portraitRegionY = generateTouchRegionHeight(Surface.ROTATION_0) + 1;
        float landscapeRegionY = generateTouchRegionHeight(Surface.ROTATION_90) + 1;
        float portraitRegionY =
                generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0) + 1;
        float landscapeRegionY =
                generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;

        mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90));
        mTouchTransformer
            .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
        tapAndAssertFalse(100, portraitRegionY,
                event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
        tapAndAssertTrue(100, landscapeRegionY,
@@ -136,11 +152,14 @@ public class OrientationTouchTransformerTest {

    @Test
    public void enableMultipleRegions_assistantTriggersInMostRecent() {
        float portraitRegionY = generateTouchRegionHeight(Surface.ROTATION_0) + 1;
        float landscapeRegionY = generateTouchRegionHeight(Surface.ROTATION_90) + 1;
        float portraitRegionY =
                generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0) + 1;
        float landscapeRegionY =
                generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;

        mTouchTransformer.enableMultipleRegions(true, mInfo);
        mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90));
        mTouchTransformer
            .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
        mTouchTransformer.createOrAddTouchRegion(mInfo);
        tapAndAssertTrue(0, portraitRegionY,
                event -> mTouchTransformer.touchInAssistantRegion(event));
@@ -150,12 +169,15 @@ public class OrientationTouchTransformerTest {

    @Test
    public void enableMultipleRegions_assistantTriggersInCurrentOrientationAfterDisable() {
        float portraitRegionY = generateTouchRegionHeight(Surface.ROTATION_0) + 1;
        float landscapeRegionY = generateTouchRegionHeight(Surface.ROTATION_90) + 1;
        float portraitRegionY =
                generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0) + 1;
        float landscapeRegionY =
                generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;

        mTouchTransformer.enableMultipleRegions(true, mInfo);
        mTouchTransformer.createOrAddTouchRegion(mInfo);
        mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90));
        mTouchTransformer
            .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
        mTouchTransformer.enableMultipleRegions(false, mInfo);
        tapAndAssertTrue(0, portraitRegionY,
                event -> mTouchTransformer.touchInAssistantRegion(event));
@@ -163,6 +185,26 @@ public class OrientationTouchTransformerTest {
                event -> mTouchTransformer.touchInAssistantRegion(event));
    }

    @Test
    public void assistantTriggersInCurrentScreenAfterScreenSizeChange() {
        float smallerScreenPortraitRegionY =
                generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0) + 1;
        float largerScreenPortraitRegionY =
                generateTouchRegionHeight(LARGE_SCREEN_SIZE, Surface.ROTATION_0) + 1;

        mTouchTransformer.enableMultipleRegions(false,
                createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_0));
        tapAndAssertTrue(0, smallerScreenPortraitRegionY,
                event -> mTouchTransformer.touchInAssistantRegion(event));

        mTouchTransformer
            .enableMultipleRegions(false, createDisplayInfo(LARGE_SCREEN_SIZE, Surface.ROTATION_0));
        tapAndAssertTrue(0, largerScreenPortraitRegionY,
                event -> mTouchTransformer.touchInAssistantRegion(event));
        tapAndAssertFalse(0, smallerScreenPortraitRegionY,
                event -> mTouchTransformer.touchInAssistantRegion(event));
    }

    @Test
    public void applyTransform_taskNotFrozen_notInRegion() {
        mTouchTransformer.createOrAddTouchRegion(mInfo);
@@ -182,7 +224,7 @@ public class OrientationTouchTransformerTest {
    public void applyTransform_taskFrozen_noRotate_inRegion() {
        mTouchTransformer.createOrAddTouchRegion(mInfo);
        mTouchTransformer.enableMultipleRegions(true, mInfo);
        float y = generateTouchRegionHeight(Surface.ROTATION_0) + 1;
        float y = generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0) + 1;
        tapAndAssertTrue(100, y,
                event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
    }
@@ -190,15 +232,16 @@ public class OrientationTouchTransformerTest {
    @Test
    public void applyTransform_taskNotFrozen_noRotate_inDefaultRegion() {
        mTouchTransformer.createOrAddTouchRegion(mInfo);
        float y = generateTouchRegionHeight(Surface.ROTATION_0) + 1;
        float y = generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0) + 1;
        tapAndAssertTrue(100, y,
                event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
    }

    @Test
    public void applyTransform_taskNotFrozen_90Rotate_inRegion() {
        mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90));
        float y = generateTouchRegionHeight(Surface.ROTATION_90) + 1;
        mTouchTransformer
            .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
        float y = generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;
        tapAndAssertTrue(100, y,
                event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
    }
@@ -210,9 +253,10 @@ public class OrientationTouchTransformerTest {
    public void applyTransform_taskNotFrozen_90Rotate_inTwoRegions() {
        mTouchTransformer.createOrAddTouchRegion(mInfo);
        mTouchTransformer.enableMultipleRegions(true, mInfo);
        mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90));
        mTouchTransformer
            .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
        // Landscape point
        float y1 = generateTouchRegionHeight(Surface.ROTATION_90) + 1;
        float y1 = generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;
        MotionEvent inRegion1_down = generateMotionEvent(MotionEvent.ACTION_DOWN, 10, y1);
        MotionEvent inRegion1_up = generateMotionEvent(MotionEvent.ACTION_UP, 10, y1);
        // Portrait point in landscape orientation axis
@@ -231,18 +275,18 @@ public class OrientationTouchTransformerTest {
        assertTrue(mTouchTransformer.touchInValidSwipeRegions(inRegion2.getX(), inRegion2.getY()));
    }

    private DisplayController.Info createDisplayInfo(int rotation) {
        Point p = new Point(SIZE_WIDTH, SIZE_HEIGHT);
    private DisplayController.Info createDisplayInfo(ScreenSize screenSize, int rotation) {
        Point p = new Point(screenSize.mWidth, screenSize.mHeight);
        if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
            p = new Point(SIZE_HEIGHT, SIZE_WIDTH);
            p = new Point(screenSize.mHeight, screenSize.mWidth);
        }
        return new DisplayController.Info(0, rotation, 0, p, p, p, null);
    }

    private float generateTouchRegionHeight(int rotation) {
        float height = SIZE_HEIGHT;
    private float generateTouchRegionHeight(ScreenSize screenSize, int rotation) {
        float height = screenSize.mHeight;
        if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
            height = SIZE_WIDTH;
            height = screenSize.mWidth;
        }
        return height - ResourceUtils.DEFAULT_NAVBAR_VALUE * DENSITY_DISPLAY_METRICS;
    }
+57 −20
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.Log;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.Surface;

@@ -40,6 +39,9 @@ import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DisplayController.Info;

import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * Maintains state for supporting nav bars and tracking their gestures in multiple orientations.
@@ -51,6 +53,37 @@ import java.io.PrintWriter;
 */
class OrientationTouchTransformer {

    class CurrentDisplay {
        public Point size;
        public int rotation;

        CurrentDisplay() {
            this.size = new Point(0, 0);
            this.rotation = 0;
        }

        CurrentDisplay(Point size, int rotation) {
            this.size = size;
            this.rotation = rotation;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            CurrentDisplay display = (CurrentDisplay) o;
            if (rotation != display.rotation) return false;

            return Objects.equals(size, display.size);
        }

        @Override
        public int hashCode() {
            return Objects.hash(size, rotation);
        }
    };

    private static final String TAG = "OrientationTouchTransformer";
    private static final boolean DEBUG = false;
    private static final int MAX_ORIENTATIONS = 4;
@@ -60,11 +93,12 @@ class OrientationTouchTransformer {
    private final Matrix mTmpMatrix = new Matrix();
    private final float[] mTmpPoint = new float[2];

    private SparseArray<OrientationRectF> mSwipeTouchRegions = new SparseArray<>(MAX_ORIENTATIONS);
    private Map<CurrentDisplay, OrientationRectF> mSwipeTouchRegions =
            new HashMap<CurrentDisplay, OrientationRectF>();
    private final RectF mAssistantLeftRegion = new RectF();
    private final RectF mAssistantRightRegion = new RectF();
    private final RectF mOneHandedModeRegion = new RectF();
    private int mCurrentDisplayRotation;
    private CurrentDisplay mCurrentDisplay = new CurrentDisplay();
    private int mNavBarGesturalHeight;
    private int mNavBarLargerGesturalHeight;
    private boolean mEnableMultipleRegions;
@@ -147,21 +181,22 @@ class OrientationTouchTransformer {
     * @see #enableMultipleRegions(boolean, Info)
     */
    void createOrAddTouchRegion(Info info) {
        mCurrentDisplayRotation = info.rotation;
        mCurrentDisplay = new CurrentDisplay(info.realSize, info.rotation);

        if (mQuickStepStartingRotation > QUICKSTEP_ROTATION_UNINITIALIZED
                && mCurrentDisplayRotation == mQuickStepStartingRotation) {
                && mCurrentDisplay.rotation == mQuickStepStartingRotation) {
            // User already was swiping and the current screen is same rotation as the starting one
            // Remove active nav bars in other rotations except for the one we started out in
            resetSwipeRegions(info);
            return;
        }
        OrientationRectF region = mSwipeTouchRegions.get(mCurrentDisplayRotation);
        OrientationRectF region = mSwipeTouchRegions.get(mCurrentDisplay);
        if (region != null) {
            return;
        }

        if (mEnableMultipleRegions) {
            mSwipeTouchRegions.put(mCurrentDisplayRotation, createRegionForDisplay(info));
            mSwipeTouchRegions.put(mCurrentDisplay, createRegionForDisplay(info));
        } else {
            resetSwipeRegions(info);
        }
@@ -208,31 +243,31 @@ class OrientationTouchTransformer {
     */
    private void resetSwipeRegions(Info region) {
        if (DEBUG) {
            Log.d(TAG, "clearing all regions except rotation: " + mCurrentDisplayRotation);
            Log.d(TAG, "clearing all regions except rotation: " + mCurrentDisplay.rotation);
        }

        mCurrentDisplayRotation = region.rotation;
        OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplayRotation);
        mCurrentDisplay = new CurrentDisplay(region.realSize, region.rotation);
        OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplay);
        if (regionToKeep == null) {
            regionToKeep = createRegionForDisplay(region);
        }
        mSwipeTouchRegions.clear();
        mSwipeTouchRegions.put(mCurrentDisplayRotation, regionToKeep);
        mSwipeTouchRegions.put(mCurrentDisplay, regionToKeep);
        updateAssistantRegions(regionToKeep);
    }

    private void resetSwipeRegions() {
        OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplayRotation);
        OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplay);
        mSwipeTouchRegions.clear();
        if (regionToKeep != null) {
            mSwipeTouchRegions.put(mCurrentDisplayRotation, regionToKeep);
            mSwipeTouchRegions.put(mCurrentDisplay, regionToKeep);
            updateAssistantRegions(regionToKeep);
        }
    }

    private OrientationRectF createRegionForDisplay(Info display) {
        if (DEBUG) {
            Log.d(TAG, "creating rotation region for: " + mCurrentDisplayRotation);
            Log.d(TAG, "creating rotation region for: " + mCurrentDisplay.rotation);
        }

        Point size = display.realSize;
@@ -341,7 +376,9 @@ class OrientationTouchTransformer {
                }

                for (int i = 0; i < MAX_ORIENTATIONS; i++) {
                    OrientationRectF rect = mSwipeTouchRegions.get(i);
                    CurrentDisplay display = new CurrentDisplay(mCurrentDisplay.size, i);
                    OrientationRectF rect = mSwipeTouchRegions.get(display);

                    if (TestProtocol.sDebugTracing) {
                        Log.d(TestProtocol.NO_SWIPE_TO_HOME, "transform:DOWN, rect=" + rect);
                    }
@@ -355,7 +392,7 @@ class OrientationTouchTransformer {
                        mLastRectTouched = rect;
                        mActiveTouchRotation = rect.mRotation;
                        if (mEnableMultipleRegions
                                && mCurrentDisplayRotation == mActiveTouchRotation) {
                                && mCurrentDisplay.rotation == mActiveTouchRotation) {
                            // TODO(b/154580671) might make this block unnecessary
                            // Start a touch session for the default nav region for the display
                            mQuickStepStartingRotation = mLastRectTouched.mRotation;
@@ -378,8 +415,8 @@ class OrientationTouchTransformer {
        pw.println("  lastTouchedRegion=" + mLastRectTouched);
        pw.println("  multipleRegionsEnabled=" + mEnableMultipleRegions);
        StringBuilder regions = new StringBuilder("  currentTouchableRotations=");
        for(int i = 0; i < mSwipeTouchRegions.size(); i++) {
            OrientationRectF rectF = mSwipeTouchRegions.get(mSwipeTouchRegions.keyAt(i));
        for (CurrentDisplay key: mSwipeTouchRegions.keySet()) {
            OrientationRectF rectF = mSwipeTouchRegions.get(key);
            regions.append(rectF).append(" ");
        }
        pw.println(regions.toString());
@@ -417,12 +454,12 @@ class OrientationTouchTransformer {

        boolean applyTransform(MotionEvent event, boolean forceTransform) {
            mTmpMatrix.reset();
            postDisplayRotation(deltaRotation(mCurrentDisplayRotation, mRotation),
            postDisplayRotation(deltaRotation(mCurrentDisplay.rotation, mRotation),
                    mHeight, mWidth, mTmpMatrix);
            if (forceTransform) {
                if (DEBUG) {
                    Log.d(TAG, "Transforming rotation due to forceTransform, "
                            + "mCurrentRotation: " + mCurrentDisplayRotation
                            + "mCurrentRotation: " + mCurrentDisplay.rotation
                            + "mRotation: " + mRotation);
                }
                event.transform(mTmpMatrix);