diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index 02bae64274..a63f3a802f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -327,7 +327,7 @@ public abstract class BaseSwipeUpHandler, Q extend public abstract void onMotionPauseChanged(boolean isPaused); @UiThread - public void onGestureStarted() { } + public void onGestureStarted(boolean isLikelyToStartNewTask) { } @UiThread public abstract void onGestureCancelled(); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index 413a81379a..37aa0dadd2 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -492,9 +492,13 @@ public abstract class BaseSwipeUpHandlerV2, Q exte @Override public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) { + setIsLikelyToStartNewTask(isLikelyToStartNewTask, true /* animate */); + } + + private void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask, boolean animate) { if (mIsLikelyToStartNewTask != isLikelyToStartNewTask) { mIsLikelyToStartNewTask = isLikelyToStartNewTask; - maybeUpdateRecentsAttachedState(); + maybeUpdateRecentsAttachedState(animate); } } @@ -628,8 +632,9 @@ public abstract class BaseSwipeUpHandlerV2, Q exte } @Override - public void onGestureStarted() { + public void onGestureStarted(boolean isLikelyToStartNewTask) { notifyGestureStartedAsync(); + setIsLikelyToStartNewTask(isLikelyToStartNewTask, false /* animate */); mStateCallback.setStateOnUiThread(STATE_GESTURE_STARTED); mGestureStarted = true; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java index 4e967cfd10..26df9c7b93 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java @@ -277,6 +277,13 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC if (!mPassedSlopOnThisGesture && passedSlop) { mPassedSlopOnThisGesture = true; } + // Until passing slop, we don't know what direction we're going, so assume + // we're quick switching to avoid translating recents away when continuing + // the gesture (in which case mPassedPilferInputSlop starts as true). + boolean haveNotPassedSlopOnContinuedGesture = + !mPassedSlopOnThisGesture && mPassedPilferInputSlop; + boolean isLikelyToStartNewTask = haveNotPassedSlopOnContinuedGesture + || horizontalDist > upDist; if (!mPassedPilferInputSlop) { if (passedSlop) { @@ -299,7 +306,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mStartDisplacement = Math.min(displacement, -mTouchSlop); } - notifyGestureStarted(); + notifyGestureStarted(isLikelyToStartNewTask); } } @@ -310,13 +317,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC } if (mDeviceState.isFullyGesturalNavMode()) { - // Until passing slop, we don't know what direction we're going, so assume - // we're quick switching to avoid translating recents away when continuing - // the gesture. - boolean haveNotPassedSlopOnContinuedGesture = - !mPassedSlopOnThisGesture && mPassedPilferInputSlop; - boolean isLikelyToStartNewTask = haveNotPassedSlopOnContinuedGesture - || horizontalDist > upDist; mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement || isLikelyToStartNewTask); mMotionPauseDetector.addPosition(ev); @@ -340,7 +340,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC } } - private void notifyGestureStarted() { + private void notifyGestureStarted(boolean isLikelyToStartNewTask) { ActiveGestureLog.INSTANCE.addLog("startQuickstep"); if (mInteractionHandler == null) { return; @@ -353,7 +353,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); // Notify the handler that the gesture has actually started - mInteractionHandler.onGestureStarted(); + mInteractionHandler.onGestureStarted(isLikelyToStartNewTask); } private void startTouchTrackingForWindowAnimation(long touchTimeMs) { @@ -370,8 +370,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mActiveCallbacks = mTaskAnimationManager.continueRecentsAnimation(mGestureState); mActiveCallbacks.addListener(mInteractionHandler); mTaskAnimationManager.notifyRecentsAnimationState(mInteractionHandler); - mInteractionHandler.setIsLikelyToStartNewTask(true); - notifyGestureStarted(); + notifyGestureStarted(true /*isLikelyToStartNewTask*/); } else { intent.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mGestureState.getGestureId()); mActiveCallbacks = mTaskAnimationManager.startRecentsAnimation(mGestureState, intent, diff --git a/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java index 53f37c15bb..22d205a7cd 100644 --- a/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java +++ b/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java @@ -59,6 +59,7 @@ public class OrientationTouchTransformerTest { mResources = mock(Resources.class); when(mResources.getBoolean(anyInt())).thenReturn(true); when(mResources.getDimension(anyInt())).thenReturn(10.0f); + when(mResources.getDimensionPixelSize(anyInt())).thenReturn(10); DisplayMetrics mockDisplayMetrics = new DisplayMetrics(); mockDisplayMetrics.density = DENSITY_DISPLAY_METRICS; when(mResources.getDisplayMetrics()).thenReturn(mockDisplayMetrics); @@ -67,53 +68,114 @@ public class OrientationTouchTransformerTest { } @Test - public void disabledMultipeRegions_shouldOverrideFirstRegion() { - mTouchTransformer.createOrAddTouchRegion(mInfo); - DefaultDisplay.Info info2 = createDisplayInfo(Surface.ROTATION_90); - mTouchTransformer.createOrAddTouchRegion(info2); + public void disabledMultipleRegions_shouldOverrideFirstRegion() { + float portraitRegionY = generateTouchRegionHeight(Surface.ROTATION_0) + 1; + float landscapeRegionY = generateTouchRegionHeight(Surface.ROTATION_90) + 1; - float y = generateTouchRegionHeight(Surface.ROTATION_0) + 1; - MotionEvent inOldRegion = generateMotionEvent(MotionEvent.ACTION_DOWN, 100, y); - mTouchTransformer.transform(inOldRegion); - assertFalse(mTouchTransformer.touchInValidSwipeRegions(inOldRegion.getX(), inOldRegion.getY())); + mTouchTransformer.createOrAddTouchRegion(mInfo); + tapAndAssertTrue(100, portraitRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertFalse(100, landscapeRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertTrue(0, portraitRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + tapAndAssertFalse(0, landscapeRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); // Override region + mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90)); + tapAndAssertFalse(100, portraitRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertTrue(100, landscapeRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertFalse(0, portraitRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + tapAndAssertTrue(0, landscapeRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + + // Override region again mTouchTransformer.createOrAddTouchRegion(mInfo); - inOldRegion = generateMotionEvent(MotionEvent.ACTION_DOWN, 100, y); - mTouchTransformer.transform(inOldRegion); - assertTrue(mTouchTransformer.touchInValidSwipeRegions(inOldRegion.getX(), inOldRegion.getY())); + tapAndAssertTrue(100, portraitRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertFalse(100, landscapeRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertTrue(0, portraitRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + tapAndAssertFalse(0, landscapeRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); } @Test - public void allowMultipeRegions_shouldOverrideFirstRegion() { - DefaultDisplay.Info info2 = createDisplayInfo(Surface.ROTATION_90); - mTouchTransformer.createOrAddTouchRegion(info2); + public void enableMultipleRegions_shouldOverrideFirstRegion() { + float portraitRegionY = generateTouchRegionHeight(Surface.ROTATION_0) + 1; + float landscapeRegionY = generateTouchRegionHeight(Surface.ROTATION_90) + 1; + + mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90)); + tapAndAssertFalse(100, portraitRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertTrue(100, landscapeRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertFalse(0, portraitRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + tapAndAssertTrue(0, landscapeRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); // We have to add 0 rotation second so that gets set as the current rotation, otherwise // matrix transform will fail (tests only work in Portrait at the moment) mTouchTransformer.enableMultipleRegions(true, mInfo); mTouchTransformer.createOrAddTouchRegion(mInfo); - float y = generateTouchRegionHeight(Surface.ROTATION_0) + 1; - MotionEvent inNewRegion = generateMotionEvent(MotionEvent.ACTION_DOWN, 100, y); - mTouchTransformer.transform(inNewRegion); - assertTrue(mTouchTransformer.touchInValidSwipeRegions(inNewRegion.getX(), inNewRegion.getY())); + tapAndAssertTrue(100, portraitRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertFalse(100, landscapeRegionY, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); + tapAndAssertTrue(0, portraitRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + tapAndAssertFalse(0, landscapeRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + } + + @Test + public void enableMultipleRegions_assistantTriggersInMostRecent() { + float portraitRegionY = generateTouchRegionHeight(Surface.ROTATION_0) + 1; + float landscapeRegionY = generateTouchRegionHeight(Surface.ROTATION_90) + 1; + + mTouchTransformer.enableMultipleRegions(true, mInfo); + mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90)); + mTouchTransformer.createOrAddTouchRegion(mInfo); + tapAndAssertTrue(0, portraitRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + tapAndAssertFalse(0, landscapeRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + } + + @Test + public void enableMultipleRegions_assistantTriggersInCurrentOrientationAfterDisable() { + float portraitRegionY = generateTouchRegionHeight(Surface.ROTATION_0) + 1; + float landscapeRegionY = generateTouchRegionHeight(Surface.ROTATION_90) + 1; + + mTouchTransformer.enableMultipleRegions(true, mInfo); + mTouchTransformer.createOrAddTouchRegion(mInfo); + mTouchTransformer.createOrAddTouchRegion(createDisplayInfo(Surface.ROTATION_90)); + mTouchTransformer.enableMultipleRegions(false, mInfo); + tapAndAssertTrue(0, portraitRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); + tapAndAssertFalse(0, landscapeRegionY, + event -> mTouchTransformer.touchInAssistantRegion(event)); } @Test public void applyTransform_taskNotFrozen_notInRegion() { mTouchTransformer.createOrAddTouchRegion(mInfo); - MotionEvent outOfRegion = generateMotionEvent(MotionEvent.ACTION_DOWN, 100, 100); - mTouchTransformer.transform(outOfRegion); - assertFalse(mTouchTransformer.touchInValidSwipeRegions(outOfRegion.getX(), outOfRegion.getY())); + tapAndAssertFalse(100, 100, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); } @Test public void applyTransform_taskFrozen_noRotate_outOfRegion() { mTouchTransformer.createOrAddTouchRegion(mInfo); mTouchTransformer.enableMultipleRegions(true, mInfo); - MotionEvent outOfRegion = generateMotionEvent(MotionEvent.ACTION_DOWN, 100, 100); - mTouchTransformer.transform(outOfRegion); - assertFalse(mTouchTransformer.touchInValidSwipeRegions(outOfRegion.getX(), outOfRegion.getY())); + tapAndAssertFalse(100, 100, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); } @Test @@ -121,27 +183,24 @@ public class OrientationTouchTransformerTest { mTouchTransformer.createOrAddTouchRegion(mInfo); mTouchTransformer.enableMultipleRegions(true, mInfo); float y = generateTouchRegionHeight(Surface.ROTATION_0) + 1; - MotionEvent inRegion = generateMotionEvent(MotionEvent.ACTION_DOWN, 100, y); - mTouchTransformer.transform(inRegion); - assertTrue(mTouchTransformer.touchInValidSwipeRegions(inRegion.getX(), inRegion.getY())); + tapAndAssertTrue(100, y, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); } @Test public void applyTransform_taskNotFrozen_noRotate_inDefaultRegion() { mTouchTransformer.createOrAddTouchRegion(mInfo); float y = generateTouchRegionHeight(Surface.ROTATION_0) + 1; - MotionEvent inRegion = generateMotionEvent(MotionEvent.ACTION_DOWN, 100, y); - mTouchTransformer.transform(inRegion); - assertTrue(mTouchTransformer.touchInValidSwipeRegions(inRegion.getX(), inRegion.getY())); + 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; - MotionEvent inRegion = generateMotionEvent(MotionEvent.ACTION_DOWN, 100, y); - mTouchTransformer.transform(inRegion); - assertTrue(mTouchTransformer.touchInValidSwipeRegions(inRegion.getX(), inRegion.getY())); + tapAndAssertTrue(100, y, + event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY())); } @Test @@ -160,15 +219,15 @@ public class OrientationTouchTransformerTest { MotionEvent inRegion2 = generateMotionEvent(MotionEvent.ACTION_DOWN, 10, 10); mTouchTransformer.transform(inRegion1_down); mTouchTransformer.transform(inRegion2); - assertTrue(mTouchTransformer.touchInValidSwipeRegions(inRegion1_down.getX(), inRegion1_down.getY())); + assertTrue(mTouchTransformer.touchInValidSwipeRegions( + inRegion1_down.getX(), inRegion1_down.getY())); // We only process one gesture region until we see a MotionEvent.ACTION_UP assertFalse(mTouchTransformer.touchInValidSwipeRegions(inRegion2.getX(), inRegion2.getY())); mTouchTransformer.transform(inRegion1_up); // Set the new region with this MotionEvent.ACTION_DOWN - inRegion2 = generateMotionEvent(MotionEvent.ACTION_DOWN, 10, 370); - mTouchTransformer.transform(inRegion2); + inRegion2 = generateAndTransformMotionEvent(MotionEvent.ACTION_DOWN, 10, 370); assertTrue(mTouchTransformer.touchInValidSwipeRegions(inRegion2.getX(), inRegion2.getY())); } @@ -191,4 +250,26 @@ public class OrientationTouchTransformerTest { private MotionEvent generateMotionEvent(int motionAction, float x, float y) { return MotionEvent.obtain(0, 0, motionAction, x, y, 0); } + + private MotionEvent generateAndTransformMotionEvent(int motionAction, float x, float y) { + MotionEvent motionEvent = generateMotionEvent(motionAction, x, y); + mTouchTransformer.transform(motionEvent); + return motionEvent; + } + + private void tapAndAssertTrue(float x, float y, MotionEventAssertion assertion) { + MotionEvent motionEvent = generateAndTransformMotionEvent(MotionEvent.ACTION_DOWN, x, y); + assertTrue(assertion.getCondition(motionEvent)); + generateAndTransformMotionEvent(MotionEvent.ACTION_UP, x, y); + } + + private void tapAndAssertFalse(float x, float y, MotionEventAssertion assertion) { + MotionEvent motionEvent = generateAndTransformMotionEvent(MotionEvent.ACTION_DOWN, x, y); + assertFalse(assertion.getCondition(motionEvent)); + generateAndTransformMotionEvent(MotionEvent.ACTION_UP, x, y); + } + + private interface MotionEventAssertion { + boolean getCondition(MotionEvent motionEvent); + } } diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java index cf5659c7d4..1081548b0d 100644 --- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java +++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java @@ -192,15 +192,21 @@ class OrientationTouchTransformer { mCurrentDisplayRotation = region.rotation; OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplayRotation); + if (regionToKeep == null) { + regionToKeep = createRegionForDisplay(region); + } mSwipeTouchRegions.clear(); - mSwipeTouchRegions.put(mCurrentDisplayRotation, - regionToKeep != null ? regionToKeep : createRegionForDisplay(region)); + mSwipeTouchRegions.put(mCurrentDisplayRotation, regionToKeep); + updateAssistantRegions(regionToKeep); } private void resetSwipeRegions() { OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplayRotation); mSwipeTouchRegions.clear(); - mSwipeTouchRegions.put(mCurrentDisplayRotation, regionToKeep); + if (regionToKeep != null) { + mSwipeTouchRegions.put(mCurrentDisplayRotation, regionToKeep); + updateAssistantRegions(regionToKeep); + } } private OrientationRectF createRegionForDisplay(DefaultDisplay.Info display) { @@ -215,20 +221,7 @@ class OrientationTouchTransformer { if (mMode == SysUINavigationMode.Mode.NO_BUTTON) { int touchHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE); orientationRectF.top = orientationRectF.bottom - touchHeight; - - final int assistantWidth = mResources - .getDimensionPixelSize(R.dimen.gestures_assistant_width); - final float assistantHeight = Math.max(touchHeight, - mContractInfo.getWindowCornerRadius()); - mAssistantLeftRegion.bottom = mAssistantRightRegion.bottom = orientationRectF.bottom; - mAssistantLeftRegion.top = mAssistantRightRegion.top = - orientationRectF.bottom - assistantHeight; - - mAssistantLeftRegion.left = 0; - mAssistantLeftRegion.right = assistantWidth; - - mAssistantRightRegion.right = orientationRectF.right; - mAssistantRightRegion.left = orientationRectF.right - assistantWidth; + updateAssistantRegions(orientationRectF); } else { mAssistantLeftRegion.setEmpty(); mAssistantRightRegion.setEmpty(); @@ -250,6 +243,21 @@ class OrientationTouchTransformer { return orientationRectF; } + private void updateAssistantRegions(OrientationRectF orientationRectF) { + int navbarHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE); + int assistantWidth = mResources.getDimensionPixelSize(R.dimen.gestures_assistant_width); + float assistantHeight = Math.max(navbarHeight, mContractInfo.getWindowCornerRadius()); + mAssistantLeftRegion.bottom = mAssistantRightRegion.bottom = orientationRectF.bottom; + mAssistantLeftRegion.top = mAssistantRightRegion.top = + orientationRectF.bottom - assistantHeight; + + mAssistantLeftRegion.left = 0; + mAssistantLeftRegion.right = assistantWidth; + + mAssistantRightRegion.right = orientationRectF.right; + mAssistantRightRegion.left = orientationRectF.right - assistantWidth; + } + boolean touchInAssistantRegion(MotionEvent ev) { return mAssistantLeftRegion.contains(ev.getX(), ev.getY()) || mAssistantRightRegion.contains(ev.getX(), ev.getY());