Merge "Added edge swipe support for along nav bar direction"

This commit is contained in:
TreeHugger Robot
2018-12-08 23:08:34 +00:00
committed by Android (Google) Code Review
9 changed files with 326 additions and 119 deletions

View File

@@ -23,6 +23,8 @@
<dimen name="navigation_bar_size">@*android:dimen/navigation_bar_height</dimen>
<!-- Minimum swipe distance to catch the swipe gestures to invoke assist or switch tasks. -->
<dimen name="navigation_bar_min_swipe_distance">48dp</dimen>
<!-- The distance from a side of device of the navigation bar to start an edge swipe -->
<dimen name="navigation_bar_edge_swipe_threshold">60dp</dimen>
<!-- thickness (height) of the dead zone at the top of the navigation bar,
reducing false presses on navbar buttons; approx 2mm -->

View File

@@ -55,6 +55,11 @@ public class NavigationBackAction extends NavigationGestureAction {
super(navigationBarView, service);
}
@Override
public boolean allowHitTargetToMoveOverDrag() {
return true;
}
@Override
public boolean canPerformAction() {
return mProxySender.getBackButtonAlpha() > 0;

View File

@@ -154,6 +154,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
private QuickScrubAction mQuickScrubAction;
private QuickStepAction mQuickStepAction;
private NavigationBackAction mBackAction;
private QuickSwitchAction mQuickSwitchAction;
/**
* Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -326,9 +327,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
mQuickScrubAction = new QuickScrubAction(this, mOverviewProxyService);
mQuickStepAction = new QuickStepAction(this, mOverviewProxyService);
mBackAction = new NavigationBackAction(this, mOverviewProxyService);
mQuickSwitchAction = new QuickSwitchAction(this, mOverviewProxyService);
mDefaultGestureMap = new NavigationGestureAction[] {
mQuickStepAction, null /* swipeDownAction*/, null /* swipeLeftAction */,
mQuickScrubAction
mQuickScrubAction, null /* swipeLeftEdgeAction */, null /* swipeRightEdgeAction */
};
mPrototypeController = new NavigationPrototypeController(mHandler, mContext);
@@ -359,7 +361,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
getNavigationActionFromType(assignedMap[0], mDefaultGestureMap[0]),
getNavigationActionFromType(assignedMap[1], mDefaultGestureMap[1]),
getNavigationActionFromType(assignedMap[2], mDefaultGestureMap[2]),
getNavigationActionFromType(assignedMap[3], mDefaultGestureMap[3]));
getNavigationActionFromType(assignedMap[3], mDefaultGestureMap[3]),
getNavigationActionFromType(assignedMap[4], mDefaultGestureMap[4]),
getNavigationActionFromType(assignedMap[5], mDefaultGestureMap[5]));
}
}
@@ -372,6 +376,8 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
return mQuickScrubAction;
case NavigationPrototypeController.ACTION_BACK:
return mBackAction;
case NavigationPrototypeController.ACTION_QUICKSWITCH:
return mQuickSwitchAction;
default:
return defaultAction;
}

View File

@@ -112,7 +112,7 @@ public abstract class NavigationGestureAction {
/**
* @return whether or not to move the button that started gesture over with user input drag
*/
public boolean requiresDragWithHitTarget() {
public boolean allowHitTargetToMoveOverDrag() {
return false;
}
@@ -139,9 +139,9 @@ public abstract class NavigationGestureAction {
* Tell if action is enabled. Compared to {@link #canPerformAction()} this is based on settings
* if the action is disabled for a particular gesture. For example a back action can be enabled
* however if there is nothing to back to then {@link #canPerformAction()} should return false.
* In this way if the action requires {@link #requiresDragWithHitTarget()} then if enabled, the
* button can be dragged with a large dampening factor during the gesture but will not activate
* the action.
* In this way if the action requires {@link #allowHitTargetToMoveOverDrag()} then if enabled,
* the button can be dragged with a large dampening factor during the gesture but will not
* activate the action.
* @return true if this action is enabled and can run
*/
public abstract boolean isEnabled();

View File

@@ -24,7 +24,6 @@ import android.os.Handler;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -46,6 +45,7 @@ public class NavigationPrototypeController extends ContentObserver {
static final int ACTION_QUICKSTEP = 1;
static final int ACTION_QUICKSCRUB = 2;
static final int ACTION_BACK = 3;
static final int ACTION_QUICKSWITCH = 4;
private OnPrototypeChangedListener mListener;
@@ -53,7 +53,7 @@ public class NavigationPrototypeController extends ContentObserver {
* Each index corresponds to a different action set in QuickStepController
* {@see updateSwipeLTRBackSetting}
*/
private int[] mActionMap = new int[4];
private int[] mActionMap = new int[6];
private final Context mContext;

View File

@@ -18,8 +18,6 @@ package com.android.systemui.statusbar.phone;
import static com.android.systemui.Interpolators.ALPHA_IN;
import static com.android.systemui.Interpolators.ALPHA_OUT;
import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -31,11 +29,8 @@ import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.RemoteException;
import android.util.FloatProperty;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -46,7 +41,7 @@ import com.android.systemui.shared.recents.utilities.Utilities;
/**
* QuickScrub action to send to launcher to start quickscrub gesture
*/
public class QuickScrubAction extends NavigationGestureAction {
public class QuickScrubAction extends QuickSwitchAction {
private static final String TAG = "QuickScrubAction";
private static final float TRACK_SCALE = 0.95f;
@@ -65,7 +60,6 @@ public class QuickScrubAction extends NavigationGestureAction {
private final int mTrackThickness;
private final int mTrackEndPadding;
private final Paint mTrackPaint = new Paint();
private final Rect mTrackRect = new Rect();
private final FloatProperty<QuickScrubAction> mTrackAlphaProperty =
new FloatProperty<QuickScrubAction>("TrackAlpha") {
@@ -177,7 +171,7 @@ public class QuickScrubAction extends NavigationGestureAction {
x1 = mNavigationBarView.getPaddingStart() + mTrackEndPadding;
x2 = x1 + width - 2 * mTrackEndPadding;
}
mTrackRect.set(x1, y1, x2, y2);
mDragOverRect.set(x1, y1, x2, y2);
}
@Override
@@ -194,15 +188,16 @@ public class QuickScrubAction extends NavigationGestureAction {
mTrackPaint.setAlpha(Math.round(255f * mTrackAlpha));
// Scale the track, but apply the inverse scale from the nav bar
final float radius = mTrackRect.height() / 2;
final float radius = mDragOverRect.height() / 2;
canvas.save();
float translate = Utilities.clamp(mHighlightCenter, mTrackRect.left, mTrackRect.right);
float translate = Utilities.clamp(mHighlightCenter, mDragOverRect.left,
mDragOverRect.right);
canvas.translate(translate, 0);
canvas.scale(mTrackScale / mNavigationBarView.getScaleX(),
1f / mNavigationBarView.getScaleY(),
mTrackRect.centerX(), mTrackRect.centerY());
canvas.drawRoundRect(mTrackRect.left - translate, mTrackRect.top,
mTrackRect.right - translate, mTrackRect.bottom, radius, radius, mTrackPaint);
mDragOverRect.centerX(), mDragOverRect.centerY());
canvas.drawRoundRect(mDragOverRect.left - translate, mDragOverRect.top,
mDragOverRect.right - translate, mDragOverRect.bottom, radius, radius, mTrackPaint);
canvas.restore();
}
@@ -211,11 +206,6 @@ public class QuickScrubAction extends NavigationGestureAction {
return mNavigationBarView.isQuickScrubEnabled();
}
@Override
public boolean disableProxyEvents() {
return true;
}
@Override
protected void onGestureStart(MotionEvent event) {
updateHighlight();
@@ -231,42 +221,12 @@ public class QuickScrubAction extends NavigationGestureAction {
mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
mTrackAnimator.start();
// Disable slippery for quick scrub to not cancel outside the nav bar
mNavigationBarView.updateSlippery();
try {
mProxySender.getProxy().onQuickScrubStart();
if (DEBUG_OVERVIEW_PROXY) {
Log.d(TAG_OPS, "Quick Scrub Start");
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to send start of quick scrub.", e);
}
mProxySender.notifyQuickScrubStarted();
startQuickGesture(event);
}
@Override
public void onGestureMove(int x, int y) {
int trackSize, offset;
if (isNavBarVertical()) {
trackSize = mTrackRect.height();
offset = y - mTrackRect.top;
} else {
offset = x - mTrackRect.left;
trackSize = mTrackRect.width();
}
if (!mDragHorizontalPositive || !mDragVerticalPositive) {
offset -= isNavBarVertical() ? mTrackRect.height() : mTrackRect.width();
}
float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
try {
mProxySender.getProxy().onQuickScrubProgress(scrubFraction);
if (DEBUG_OVERVIEW_PROXY) {
Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to send progress of quick scrub.", e);
}
super.onGestureMove(x, y);
mHighlightCenter = x;
mNavigationBarView.invalidate();
}
@@ -278,14 +238,7 @@ public class QuickScrubAction extends NavigationGestureAction {
private void endQuickScrub(boolean animate) {
animateEnd();
try {
mProxySender.getProxy().onQuickScrubEnd();
if (DEBUG_OVERVIEW_PROXY) {
Log.d(TAG_OPS, "Quick Scrub End");
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to send end of quick scrub.", e);
}
endQuickGesture(animate);
if (!animate) {
if (mTrackAnimator != null) {
mTrackAnimator.end();
@@ -295,7 +248,7 @@ public class QuickScrubAction extends NavigationGestureAction {
}
private void updateHighlight() {
if (mTrackRect.isEmpty()) {
if (mDragOverRect.isEmpty()) {
return;
}
int colorBase, colorGrad;
@@ -306,8 +259,8 @@ public class QuickScrubAction extends NavigationGestureAction {
colorBase = getContext().getColor(R.color.quick_step_track_background_background_light);
colorGrad = getContext().getColor(R.color.quick_step_track_background_foreground_light);
}
final RadialGradient mHighlight = new RadialGradient(0, mTrackRect.height() / 2,
mTrackRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
final RadialGradient mHighlight = new RadialGradient(0, mDragOverRect.height() / 2,
mDragOverRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
Shader.TileMode.CLAMP);
mTrackPaint.setShader(mHighlight);
}

View File

@@ -76,7 +76,9 @@ public class QuickStepController implements GestureHelper {
private static final int ACTION_SWIPE_DOWN_INDEX = 1;
private static final int ACTION_SWIPE_LEFT_INDEX = 2;
private static final int ACTION_SWIPE_RIGHT_INDEX = 3;
private static final int MAX_GESTURES = 4;
private static final int ACTION_SWIPE_LEFT_FROM_EDGE_INDEX = 4;
private static final int ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX = 5;
private static final int MAX_GESTURES = 6;
private NavigationBarView mNavigationBarView;
@@ -97,6 +99,7 @@ public class QuickStepController implements GestureHelper {
private float mMaxDragLimit;
private float mMinDragLimit;
private float mDragDampeningFactor;
private float mEdgeSwipeThreshold;
private NavigationGestureAction mCurrentAction;
private NavigationGestureAction[] mGestureActions = new NavigationGestureAction[MAX_GESTURES];
@@ -128,15 +131,21 @@ public class QuickStepController implements GestureHelper {
* @param swipeDownAction action after swiping down
* @param swipeLeftAction action after swiping left
* @param swipeRightAction action after swiping right
* @param swipeLeftFromEdgeAction action swiping left starting from the right side
* @param swipeRightFromEdgeAction action swiping right starting from the left side
*/
public void setGestureActions(@Nullable NavigationGestureAction swipeUpAction,
@Nullable NavigationGestureAction swipeDownAction,
@Nullable NavigationGestureAction swipeLeftAction,
@Nullable NavigationGestureAction swipeRightAction) {
@Nullable NavigationGestureAction swipeRightAction,
@Nullable NavigationGestureAction swipeLeftFromEdgeAction,
@Nullable NavigationGestureAction swipeRightFromEdgeAction) {
mGestureActions[ACTION_SWIPE_UP_INDEX] = swipeUpAction;
mGestureActions[ACTION_SWIPE_DOWN_INDEX] = swipeDownAction;
mGestureActions[ACTION_SWIPE_LEFT_INDEX] = swipeLeftAction;
mGestureActions[ACTION_SWIPE_RIGHT_INDEX] = swipeRightAction;
mGestureActions[ACTION_SWIPE_LEFT_FROM_EDGE_INDEX] = swipeLeftFromEdgeAction;
mGestureActions[ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX] = swipeRightFromEdgeAction;
// Set the current state to all actions
for (NavigationGestureAction action: mGestureActions) {
@@ -233,6 +242,8 @@ public class QuickStepController implements GestureHelper {
mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
mAllowGestureDetection = true;
mNotificationsVisibleOnDown = !mNavigationBarView.isNotificationsFullyCollapsed();
mEdgeSwipeThreshold = mContext.getResources()
.getDimensionPixelSize(R.dimen.navigation_bar_edge_swipe_threshold);
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -284,13 +295,17 @@ public class QuickStepController implements GestureHelper {
}
} else if (exceededSwipeHorizontalTouchSlop) {
if (mDragHPositive ? (posH < touchDownH) : (posH > touchDownH)) {
// Swiping left (ltr) gesture
tryToStartGesture(mGestureActions[ACTION_SWIPE_LEFT_INDEX],
true /* alignedWithNavBar */, event);
// Swiping left (rtl) gesture
int index = isEdgeSwipeAlongNavBar(touchDownH, !mDragHPositive)
? ACTION_SWIPE_LEFT_FROM_EDGE_INDEX : ACTION_SWIPE_LEFT_INDEX;
tryToStartGesture(mGestureActions[index], true /* alignedWithNavBar */,
event);
} else {
// Swiping right (ltr) gesture
tryToStartGesture(mGestureActions[ACTION_SWIPE_RIGHT_INDEX],
true /* alignedWithNavBar */, event);
int index = isEdgeSwipeAlongNavBar(touchDownH, mDragHPositive)
? ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX : ACTION_SWIPE_RIGHT_INDEX;
tryToStartGesture(mGestureActions[index], true /* alignedWithNavBar */,
event);
}
}
}
@@ -333,6 +348,17 @@ public class QuickStepController implements GestureHelper {
return mCurrentAction != null || deadZoneConsumed;
}
private boolean isEdgeSwipeAlongNavBar(int touchDown, boolean dragPositiveDirection) {
// Detect edge swipe from side of 0 -> threshold
if (dragPositiveDirection) {
return touchDown < mEdgeSwipeThreshold;
}
// Detect edge swipe from side of size -> (size - threshold)
final int largeSide = isNavBarVertical()
? mNavigationBarView.getHeight() : mNavigationBarView.getWidth();
return touchDown > largeSide - mEdgeSwipeThreshold;
}
private void handleDragHitTarget(int position, int touchDown) {
// Drag the hit target if gesture action requires it
if (mHitTarget != null && (mGestureVerticalDragsButton || mGestureHorizontalDragsButton)) {
@@ -480,7 +506,7 @@ public class QuickStepController implements GestureHelper {
event.transform(mTransformLocalMatrix);
// Calculate the bounding limits of drag to avoid dragging off nav bar's window
if (action.requiresDragWithHitTarget() && mHitTarget != null) {
if (action.allowHitTargetToMoveOverDrag() && mHitTarget != null) {
final int[] buttonCenter = new int[2];
View button = mHitTarget.getCurrentView();
button.getLocationInWindow(buttonCenter);
@@ -505,7 +531,7 @@ public class QuickStepController implements GestureHelper {
// Handle direction of the hit target drag from the axis that started the gesture
// Also calculate the dampening factor, weaker dampening if there is an active action
if (action.requiresDragWithHitTarget()) {
if (action.allowHitTargetToMoveOverDrag()) {
if (alignedWithNavBar) {
mGestureHorizontalDragsButton = true;
mGestureVerticalDragsButton = false;

View File

@@ -0,0 +1,139 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.phone;
import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
import android.annotation.NonNull;
import android.graphics.Rect;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;
import android.view.MotionEvent;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.recents.utilities.Utilities;
/**
* QuickSwitch action to send to launcher
*/
public class QuickSwitchAction extends NavigationGestureAction {
private static final String TAG = "QuickSwitchAction";
private static final String QUICKSWITCH_ENABLED_SETTING = "QUICK_SWITCH";
protected final Rect mDragOverRect = new Rect();
public QuickSwitchAction(@NonNull NavigationBarView navigationBar,
@NonNull OverviewProxyService service) {
super(navigationBar, service);
}
@Override
public void setBarState(boolean changed, int navBarPos, boolean dragHorPositive,
boolean dragVerPositive) {
super.setBarState(changed, navBarPos, dragHorPositive, dragVerPositive);
if (changed && isActive()) {
// End quickscrub if the state changes mid-transition
endQuickGesture(false /* animate */);
}
}
@Override
public boolean isEnabled() {
return mNavigationBarView.isQuickScrubEnabled();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mDragOverRect.set(top, left, right, bottom);
}
@Override
public boolean disableProxyEvents() {
return true;
}
@Override
protected void onGestureStart(MotionEvent event) {
// Temporarily enable launcher to allow quick switch instead of quick scrub
Settings.Global.putInt(mNavigationBarView.getContext().getContentResolver(),
QUICKSWITCH_ENABLED_SETTING, 1 /* enabled */);
startQuickGesture(event);
}
@Override
public void onGestureMove(int x, int y) {
int dragLength, offset;
if (isNavBarVertical()) {
dragLength = mDragOverRect.height();
offset = y - mDragOverRect.top;
} else {
offset = x - mDragOverRect.left;
dragLength = mDragOverRect.width();
}
if (!mDragHorizontalPositive || !mDragVerticalPositive) {
offset -= dragLength;
}
float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / dragLength, 0, 1);
try {
mProxySender.getProxy().onQuickScrubProgress(scrubFraction);
if (DEBUG_OVERVIEW_PROXY) {
Log.d(TAG_OPS, "Quick Switch Progress:" + scrubFraction);
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to send progress of quick switch.", e);
}
}
@Override
protected void onGestureEnd() {
endQuickGesture(true /* animate */);
// Disable launcher to use quick switch instead of quick scrub
Settings.Global.putInt(mNavigationBarView.getContext().getContentResolver(),
QUICKSWITCH_ENABLED_SETTING, 0 /* disabled */);
}
protected void startQuickGesture(MotionEvent event) {
// Disable slippery for quick scrub to not cancel outside the nav bar
mNavigationBarView.updateSlippery();
try {
mProxySender.getProxy().onQuickScrubStart();
if (DEBUG_OVERVIEW_PROXY) {
Log.d(TAG_OPS, "Quick Scrub Start");
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to send start of quick scrub.", e);
}
mProxySender.notifyQuickScrubStarted();
}
protected void endQuickGesture(boolean animate) {
try {
mProxySender.getProxy().onQuickScrubEnd();
if (DEBUG_OVERVIEW_PROXY) {
Log.d(TAG_OPS, "Quick Scrub End");
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to send end of quick scrub.", e);
}
}
}

View File

@@ -61,6 +61,10 @@ import org.mockito.MockitoAnnotations;
@RunWithLooper
@SmallTest
public class QuickStepControllerTest extends SysuiTestCase {
private static final int NAVBAR_WIDTH = 1000;
private static final int NAVBAR_HEIGHT = 300;
private static final int EDGE_THRESHOLD = 100;
private QuickStepController mController;
private NavigationBarView mNavigationBarView;
private StatusBar mStatusBar;
@@ -73,6 +77,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
final ButtonDispatcher backButton = mock(ButtonDispatcher.class);
mResources = mock(Resources.class);
doReturn(EDGE_THRESHOLD).when(mResources)
.getDimensionPixelSize(R.dimen.navigation_bar_edge_swipe_threshold);
mProxyService = mock(OverviewProxyService.class);
mProxy = mock(IOverviewProxy.Stub.class);
@@ -109,7 +115,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
public void testNoGesturesWhenSwipeUpDisabled() throws Exception {
doReturn(false).when(mProxyService).shouldShowSwipeUpUI();
mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
null /* swipeLeftAction */, null /* swipeRightAction */);
null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
assertFalse(mController.onInterceptTouchEvent(ev));
@@ -124,7 +131,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
// Add enabled gesture action
NavigationGestureAction action = mockAction(true);
mController.setGestureActions(action, null /* swipeDownAction */,
null /* swipeLeftAction */, null /* swipeRightAction */);
null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
assertFalse(mController.onInterceptTouchEvent(ev));
verify(mNavigationBarView, times(1)).requestUnbufferedDispatch(ev);
@@ -140,7 +148,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
// Add enabled gesture action
mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
null /* swipeLeftAction */, null /* swipeRightAction */);
null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
// Set the gesture on deadzone
doReturn(null).when(mProxyService).getProxy();
@@ -165,7 +174,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
@Test
public void testOnTouchIgnoredDownEventAfterOnIntercept() {
mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
null /* swipeLeftAction */, null /* swipeRightAction */);
null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
assertFalse(touch(ev));
@@ -178,29 +188,45 @@ public class QuickStepControllerTest extends SysuiTestCase {
@Test
public void testGesturesCallCorrectAction() throws Exception {
doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
NavigationGestureAction swipeUp = mockAction(true);
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
NavigationGestureAction swipeLeftFromEdge = mockAction(true);
NavigationGestureAction swipeRightFromEdge = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
swipeRightFromEdge);
// Swipe Up
assertGestureTriggersAction(swipeUp, 1, 100, 5, 1);
// Swipe Down
assertGestureTriggersAction(swipeDown, 1, 1, 5, 100);
// Swipe Left
assertGestureTriggersAction(swipeLeft, 100, 1, 5, 1);
assertGestureTriggersAction(swipeLeft, NAVBAR_WIDTH / 2, 1, 5, 1);
// Swipe Right
assertGestureTriggersAction(swipeRight, 1, 1, 100, 5);
assertGestureTriggersAction(swipeRight, NAVBAR_WIDTH / 2, 1, NAVBAR_WIDTH, 5);
// Swipe Left from Edge
assertGestureTriggersAction(swipeLeftFromEdge, NAVBAR_WIDTH, 1, 5, 1);
// Swipe Right from Edge
assertGestureTriggersAction(swipeRightFromEdge, 0, 1, NAVBAR_WIDTH, 5);
}
@Test
public void testGesturesCallCorrectActionLandscape() throws Exception {
doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
NavigationGestureAction swipeUp = mockAction(true);
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
NavigationGestureAction swipeLeftFromEdge = mockAction(true);
NavigationGestureAction swipeRightFromEdge = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
swipeRightFromEdge);
// In landscape
mController.setBarState(false /* isRTL */, NAV_BAR_RIGHT);
@@ -208,34 +234,50 @@ public class QuickStepControllerTest extends SysuiTestCase {
// Swipe Up
assertGestureTriggersAction(swipeRight, 1, 100, 5, 1);
// Swipe Down
assertGestureTriggersAction(swipeLeft, 1, 1, 5, 100);
assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
// Swipe Left
assertGestureTriggersAction(swipeUp, 100, 1, 5, 1);
// Swipe Right
assertGestureTriggersAction(swipeDown, 1, 1, 100, 5);
// Swipe Up from Edge
assertGestureTriggersAction(swipeRightFromEdge, 1, NAVBAR_WIDTH, 5, 0);
// Swipe Down from Edge
assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, 0, NAVBAR_WIDTH);
}
@Test
public void testGesturesCallCorrectActionSeascape() throws Exception {
doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
mController.setBarState(false /* isRTL */, NAV_BAR_LEFT);
NavigationGestureAction swipeUp = mockAction(true);
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
NavigationGestureAction swipeLeftFromEdge = mockAction(true);
NavigationGestureAction swipeRightFromEdge = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
swipeRightFromEdge);
// Swipe Up
assertGestureTriggersAction(swipeLeft, 1, 100, 5, 1);
assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, 1);
// Swipe Down
assertGestureTriggersAction(swipeRight, 1, 1, 5, 100);
assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
// Swipe Left
assertGestureTriggersAction(swipeDown, 100, 1, 5, 1);
// Swipe Right
assertGestureTriggersAction(swipeUp, 1, 1, 100, 5);
// Swipe Up from Edge
assertGestureTriggersAction(swipeLeftFromEdge, 1, NAVBAR_WIDTH, 5, 0);
// Swipe Down from Edge
assertGestureTriggersAction(swipeRightFromEdge, 0, 1, 0, NAVBAR_WIDTH);
}
@Test
public void testGesturesCallCorrectActionRTL() throws Exception {
doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
mController.setBarState(true /* isRTL */, NAV_BAR_BOTTOM);
// The swipe gestures below are for LTR, so RTL in portrait will be swapped
@@ -243,20 +285,29 @@ public class QuickStepControllerTest extends SysuiTestCase {
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
NavigationGestureAction swipeLeftFromEdge = mockAction(true);
NavigationGestureAction swipeRightFromEdge = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
swipeRightFromEdge);
// Swipe Up in RTL
assertGestureTriggersAction(swipeUp, 1, 100, 5, 1);
// Swipe Down in RTL
assertGestureTriggersAction(swipeDown, 1, 1, 5, 100);
// Swipe Left in RTL
assertGestureTriggersAction(swipeRight, 100, 1, 5, 1);
assertGestureTriggersAction(swipeRight, NAVBAR_WIDTH / 2, 1, 5, 1);
// Swipe Right in RTL
assertGestureTriggersAction(swipeLeft, 1, 1, 100, 5);
assertGestureTriggersAction(swipeLeft, NAVBAR_WIDTH / 2, 1, NAVBAR_WIDTH, 0);
// Swipe Left from Edge
assertGestureTriggersAction(swipeRightFromEdge, NAVBAR_WIDTH, 1, 5, 1);
// Swipe Right from Edge
assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, NAVBAR_WIDTH, 5);
}
@Test
public void testGesturesCallCorrectActionLandscapeRTL() throws Exception {
doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
mController.setBarState(true /* isRTL */, NAV_BAR_RIGHT);
// The swipe gestures below are for LTR, so RTL in landscape will be swapped
@@ -264,20 +315,29 @@ public class QuickStepControllerTest extends SysuiTestCase {
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
NavigationGestureAction swipeLeftFromEdge = mockAction(true);
NavigationGestureAction swipeRightFromEdge = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
swipeRightFromEdge);
// Swipe Up
assertGestureTriggersAction(swipeLeft, 1, 100, 5, 1);
assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, 1);
// Swipe Down
assertGestureTriggersAction(swipeRight, 1, 1, 5, 100);
assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
// Swipe Left
assertGestureTriggersAction(swipeUp, 100, 1, 5, 1);
// Swipe Right
assertGestureTriggersAction(swipeDown, 1, 1, 100, 5);
// Swipe Up from Edge
assertGestureTriggersAction(swipeLeftFromEdge, 1, NAVBAR_WIDTH, 5, 0);
// Swipe Down from Edge
assertGestureTriggersAction(swipeRightFromEdge, 0, 1, 0, NAVBAR_WIDTH);
}
@Test
public void testGesturesCallCorrectActionSeascapeRTL() throws Exception {
doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
mController.setBarState(true /* isRTL */, NAV_BAR_LEFT);
// The swipe gestures below are for LTR, so RTL in seascape will be swapped
@@ -285,16 +345,23 @@ public class QuickStepControllerTest extends SysuiTestCase {
NavigationGestureAction swipeDown = mockAction(true);
NavigationGestureAction swipeLeft = mockAction(true);
NavigationGestureAction swipeRight = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
NavigationGestureAction swipeLeftFromEdge = mockAction(true);
NavigationGestureAction swipeRightFromEdge = mockAction(true);
mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
swipeRightFromEdge);
// Swipe Up
assertGestureTriggersAction(swipeRight, 1, 100, 5, 1);
assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, 1);
// Swipe Down
assertGestureTriggersAction(swipeLeft, 1, 1, 5, 100);
assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
// Swipe Left
assertGestureTriggersAction(swipeDown, 100, 1, 5, 1);
// Swipe Right
assertGestureTriggersAction(swipeUp, 1, 1, 100, 5);
// Swipe Up from Edge
assertGestureTriggersAction(swipeRightFromEdge, 1, NAVBAR_WIDTH, 5, 0);
// Swipe Down from Edge
assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, 0, NAVBAR_WIDTH);
}
@Test
@@ -305,7 +372,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
// Add enabled gesture action
NavigationGestureAction action = mockAction(true);
mController.setGestureActions(action, null /* swipeDownAction */,
null /* swipeLeftAction */, null /* swipeRightAction */);
null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
// Touch down to begin swipe
MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, 1, 100);
@@ -326,7 +394,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
NavigationGestureAction action = mockAction(true);
doReturn(false).when(action).canRunWhenNotificationsShowing();
mController.setGestureActions(action, null /* swipeDownAction */,
null /* swipeLeftAction */, null /* swipeRightAction */);
null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
// Show the notifications
doReturn(false).when(mNavigationBarView).isNotificationsFullyCollapsed();
@@ -351,7 +420,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
public void testActionCannotPerform() throws Exception {
NavigationGestureAction action = mockAction(true);
mController.setGestureActions(action, null /* swipeDownAction */,
null /* swipeLeftAction */, null /* swipeRightAction */);
null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
// Cannot perform action
doReturn(false).when(action).canPerformAction();
@@ -374,13 +444,17 @@ public class QuickStepControllerTest extends SysuiTestCase {
@Test
public void testQuickScrub() throws Exception {
doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
QuickScrubAction action = spy(new QuickScrubAction(mNavigationBarView, mProxyService));
mController.setGestureActions(null /* swipeUpAction */, null /* swipeDownAction */,
null /* swipeLeftAction */, action);
null /* swipeLeftAction */, action, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
int x = NAVBAR_WIDTH / 2;
int y = 20;
// Set the layout and other padding to make sure the scrub fraction is calculated correctly
action.onLayout(true, 0, 0, 400, 100);
action.onLayout(true, 0, 0, NAVBAR_WIDTH, NAVBAR_HEIGHT);
doReturn(0).when(mNavigationBarView).getPaddingLeft();
doReturn(0).when(mNavigationBarView).getPaddingRight();
doReturn(0).when(mNavigationBarView).getPaddingStart();
@@ -393,14 +467,14 @@ public class QuickStepControllerTest extends SysuiTestCase {
doReturn(true).when(mNavigationBarView).isQuickScrubEnabled();
// Touch down
MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, 0, y);
MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, x, y);
assertFalse(touch(downEvent));
assertNull(mController.getCurrentAction());
verify(mProxy, times(1)).onPreMotionEvent(mNavigationBarView.getDownHitTarget());
verify(mProxy, times(1)).onMotionEvent(downEvent);
// Move to start trigger action from gesture
MotionEvent moveEvent1 = event(MotionEvent.ACTION_MOVE, 100, y);
MotionEvent moveEvent1 = event(MotionEvent.ACTION_MOVE, x + 100, y);
assertTrue(touch(moveEvent1));
assertEquals(action, mController.getCurrentAction());
verify(action, times(1)).onGestureStart(moveEvent1);
@@ -410,11 +484,13 @@ public class QuickStepControllerTest extends SysuiTestCase {
verify(mProxy, never()).onMotionEvent(moveEvent1);
// Move again for scrub
MotionEvent moveEvent2 = event(MotionEvent.ACTION_MOVE, 200, y);
float fraction = 3f / 4;
x = (int) (NAVBAR_WIDTH * fraction);
MotionEvent moveEvent2 = event(MotionEvent.ACTION_MOVE, x, y);
assertTrue(touch(moveEvent2));
assertEquals(action, mController.getCurrentAction());
verify(action, times(1)).onGestureMove(200, y);
verify(mProxy, times(1)).onQuickScrubProgress(1f / 2);
verify(action, times(1)).onGestureMove(x, y);
verify(mProxy, times(1)).onQuickScrubProgress(fraction);
verify(mProxy, never()).onMotionEvent(moveEvent2);
// Action up
@@ -430,7 +506,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
public void testQuickStep() throws Exception {
QuickStepAction action = new QuickStepAction(mNavigationBarView, mProxyService);
mController.setGestureActions(action, null /* swipeDownAction */,
null /* swipeLeftAction */, null /* swipeRightAction */);
null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
// Notifications are up, should prevent quickstep
doReturn(false).when(mNavigationBarView).isNotificationsFullyCollapsed();
@@ -466,7 +543,8 @@ public class QuickStepControllerTest extends SysuiTestCase {
public void testLongPressPreventDetection() throws Exception {
NavigationGestureAction action = mockAction(true);
mController.setGestureActions(action, null /* swipeDownAction */,
null /* swipeLeftAction */, null /* swipeRightAction */);
null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
null /* rightEdgeSwipe */);
// Start the drag up
assertFalse(touch(MotionEvent.ACTION_DOWN, 100, 1));
@@ -488,23 +566,21 @@ public class QuickStepControllerTest extends SysuiTestCase {
@Test
public void testHitTargetDragged() throws Exception {
final int navbarWidth = 1000;
final int navbarHeight = 1000;
ButtonDispatcher button = mock(ButtonDispatcher.class);
FakeLocationView buttonView = spy(new FakeLocationView(mContext, navbarWidth / 2,
navbarHeight / 2));
FakeLocationView buttonView = spy(new FakeLocationView(mContext, NAVBAR_WIDTH / 2,
NAVBAR_HEIGHT / 2));
doReturn(buttonView).when(button).getCurrentView();
NavigationGestureAction action = mockAction(true);
mController.setGestureActions(action, action, action, action);
mController.setGestureActions(action, action, action, action, action, action);
// Setup getting the hit target
doReturn(HIT_TARGET_HOME).when(action).requiresTouchDownHitTarget();
doReturn(true).when(action).requiresDragWithHitTarget();
doReturn(true).when(action).allowHitTargetToMoveOverDrag();
doReturn(HIT_TARGET_HOME).when(mNavigationBarView).getDownHitTarget();
doReturn(button).when(mNavigationBarView).getHomeButton();
doReturn(navbarWidth).when(mNavigationBarView).getWidth();
doReturn(navbarHeight).when(mNavigationBarView).getHeight();
doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
// Portrait
assertGestureDragsHitTargetAllDirections(buttonView, false /* isRTL */, NAV_BAR_BOTTOM);