Merge "Only detect swipe directions that lead to new states" into ub-launcher3-edmonton
diff --git a/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java
index a7cf545..42f6c74 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java
@@ -11,6 +11,7 @@
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.touch.AbstractStateChangeTouchController;
 import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
 import com.android.quickstep.RecentsModel;
 import com.android.quickstep.util.SysuiEventLogger;
@@ -39,17 +40,17 @@
     }
 
     @Override
-    protected int getSwipeDirection(MotionEvent ev) {
-        return SwipeDetector.DIRECTION_BOTH;
-    }
-
-    @Override
     protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
         boolean draggingFromNav = mLauncher.getDeviceProfile().isSeascape() != isDragTowardPositive;
         return draggingFromNav ? OVERVIEW : NORMAL;
     }
 
     @Override
+    protected int getLogContainerTypeForNormalState() {
+        return LauncherLogProto.ContainerType.NAVBAR;
+    }
+
+    @Override
     protected float getShiftRange() {
         return mLauncher.getDragLayer().getWidth();
     }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java
index e7816be..0f9b57f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java
@@ -24,6 +24,7 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.quickstep.TouchInteractionService;
 import com.android.quickstep.views.RecentsView;
 
@@ -72,4 +73,8 @@
         return fromState;
     }
 
+    @Override
+    protected int getLogContainerTypeForNormalState() {
+        return LauncherLogProto.ContainerType.WORKSPACE;
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
index 2a603d7..2f0bdc6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
@@ -125,26 +125,6 @@
     }
 
     @Override
-    protected int getSwipeDirection(MotionEvent ev) {
-        final int directionsToDetectScroll;
-        if (mLauncher.isInState(ALL_APPS)) {
-            directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE;
-            mStartContainerType = ContainerType.ALLAPPS;
-        } else if (mLauncher.isInState(NORMAL)) {
-            directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
-            mStartContainerType = ContainerType.HOTSEAT;
-        } else if (mLauncher.isInState(OVERVIEW)) {
-            boolean canSwipeDownFromOverview = getTargetState(OVERVIEW, false) != OVERVIEW;
-            directionsToDetectScroll = canSwipeDownFromOverview ? SwipeDetector.DIRECTION_BOTH
-                    : SwipeDetector.DIRECTION_POSITIVE;
-            mStartContainerType = ContainerType.TASKSWITCHER;
-        } else {
-            return 0;
-        }
-        return directionsToDetectScroll;
-    }
-
-    @Override
     protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
         if (fromState == ALL_APPS && !isDragTowardPositive) {
             // Should swipe down go to OVERVIEW instead?
@@ -152,12 +132,17 @@
                     mLauncher.getStateManager().getLastState() : NORMAL;
         } else if (fromState == OVERVIEW) {
             return isDragTowardPositive ? ALL_APPS : NORMAL;
-        } else if (isDragTowardPositive) {
+        } else if (fromState == NORMAL && isDragTowardPositive) {
             return TouchInteractionService.isConnected() ? OVERVIEW : ALL_APPS;
         }
         return fromState;
     }
 
+    @Override
+    protected int getLogContainerTypeForNormalState() {
+        return ContainerType.HOTSEAT;
+    }
+
     private AnimatorSetBuilder getNormalToOverviewAnimation() {
         mAllAppsInterpolatorWrapper.baseInterpolator = mAllAppsDampedInterpolator;
 
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index d5c0788..658af95 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -15,6 +15,9 @@
  */
 package com.android.launcher3.touch;
 
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
 import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
 
@@ -27,6 +30,7 @@
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 import com.android.launcher3.util.PendingAnimation;
 import com.android.launcher3.util.TouchController;
 
@@ -65,12 +69,6 @@
 
     protected abstract boolean canInterceptTouch(MotionEvent ev);
 
-    /**
-     * Initializes the {@code mFromState} and {@code mToState} and swipe direction to use for
-     * the detector. In case of disabling swipe, return 0.
-     */
-    protected abstract int getSwipeDirection(MotionEvent ev);
-
     @Override
     public final boolean onControllerInterceptTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
@@ -94,7 +92,7 @@
                     ignoreSlopWhenSettling = true;
                 }
             } else {
-                directionsToDetectScroll = getSwipeDirection(ev);
+                directionsToDetectScroll = getSwipeDirection();
                 if (directionsToDetectScroll == 0) {
                     mNoIntercept = true;
                     return false;
@@ -112,6 +110,18 @@
         return mDetector.isDraggingOrSettling();
     }
 
+    private int getSwipeDirection() {
+        LauncherState fromState = mLauncher.getStateManager().getState();
+        int swipeDirection = 0;
+        if (getTargetState(fromState, true /* isDragTowardPositive */) != fromState) {
+            swipeDirection |= SwipeDetector.DIRECTION_POSITIVE;
+        }
+        if (getTargetState(fromState, false /* isDragTowardPositive */) != fromState) {
+            swipeDirection |= SwipeDetector.DIRECTION_NEGATIVE;
+        }
+        return swipeDirection;
+    }
+
     @Override
     public final boolean onControllerTouchEvent(MotionEvent ev) {
         return mDetector.onTouchEvent(ev);
@@ -130,6 +140,11 @@
 
     protected abstract float initCurrentAnimation();
 
+    /**
+     * Returns the container that the touch started from when leaving NORMAL state.
+     */
+    protected abstract int getLogContainerTypeForNormalState();
+
     private boolean reinitCurrentAnimation(boolean reachedToState, boolean isDragTowardPositive) {
         LauncherState newFromState = mFromState == null ? mLauncher.getStateManager().getState()
                 : reachedToState ? mToState : mFromState;
@@ -139,6 +154,17 @@
             return false;
         }
 
+        if (reachedToState) {
+            logReachedState(Touch.SWIPE);
+        }
+        if (newFromState == ALL_APPS) {
+            mStartContainerType = ContainerType.ALLAPPS;
+        } else if (newFromState == NORMAL) {
+            mStartContainerType = getLogContainerTypeForNormalState();
+        } else if (newFromState == OVERVIEW){
+            mStartContainerType = ContainerType.TASKSWITCHER;
+        }
+
         mFromState = newFromState;
         mToState = newToState;
 
@@ -261,18 +287,22 @@
         }
         if (shouldGoToTargetState) {
             if (targetState != mFromState) {
-                // Transition complete. log the action
-                mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
-                        getDirectionForLog(),
-                        mStartContainerType,
-                        mFromState.containerType,
-                        mToState.containerType,
-                        mLauncher.getWorkspace().getCurrentPage());
+                logReachedState(logAction);
             }
             mLauncher.getStateManager().goToState(targetState, false /* animated */);
         }
     }
 
+    private void logReachedState(int logAction) {
+        // Transition complete. log the action
+        mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
+                getDirectionForLog(),
+                mStartContainerType,
+                mFromState.containerType,
+                mToState.containerType,
+                mLauncher.getWorkspace().getCurrentPage());
+    }
+
     protected void clearState() {
         mCurrentAnimation = null;
         mDetector.finishedScrolling();
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java
index d1cddc1..860be5f 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java
@@ -17,12 +17,17 @@
  */
 public class AllAppsSwipeController extends AbstractStateChangeTouchController {
 
+    private MotionEvent mTouchDownEvent;
+
     public AllAppsSwipeController(Launcher l) {
         super(l, SwipeDetector.VERTICAL);
     }
 
     @Override
     protected boolean canInterceptTouch(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            mTouchDownEvent = ev;
+        }
         if (mCurrentAnimation != null) {
             // If we are already animating from a previous state, we can intercept.
             return true;
@@ -41,18 +46,6 @@
     }
 
     @Override
-    protected int getSwipeDirection(MotionEvent ev) {
-        if (mLauncher.isInState(ALL_APPS)) {
-            mStartContainerType = ContainerType.ALLAPPS;
-            return SwipeDetector.DIRECTION_NEGATIVE;
-        } else {
-            mStartContainerType = mLauncher.getDragLayer().isEventOverHotseat(ev) ?
-                    ContainerType.HOTSEAT : ContainerType.WORKSPACE;
-            return SwipeDetector.DIRECTION_POSITIVE;
-        }
-    }
-
-    @Override
     protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
         if (fromState == NORMAL && isDragTowardPositive) {
             return ALL_APPS;
@@ -63,6 +56,12 @@
     }
 
     @Override
+    protected int getLogContainerTypeForNormalState() {
+        return mLauncher.getDragLayer().isEventOverHotseat(mTouchDownEvent) ?
+                ContainerType.HOTSEAT : ContainerType.WORKSPACE;
+    }
+
+    @Override
     protected float initCurrentAnimation() {
         float range = getShiftRange();
         long maxAccuracy = (long) (2 * range);