Merge "Bypass systemstate check when using shared state" into ub-launcher3-qt-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
index 5a039cd..6689ce3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
@@ -15,8 +15,11 @@
  */
 package com.android.quickstep;
 
+import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+
 import android.util.Log;
 
+import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.Preconditions;
 import com.android.quickstep.util.RecentsAnimationListenerSet;
@@ -29,7 +32,7 @@
  */
 public class SwipeSharedState implements SwipeAnimationListener {
 
-    private final OverviewComponentObserver mOverviewComponentObserver;
+    private OverviewComponentObserver mOverviewComponentObserver;
 
     private RecentsAnimationListenerSet mRecentsAnimationListener;
     private SwipeAnimationTargetSet mLastAnimationTarget;
@@ -42,8 +45,8 @@
     public boolean recentsAnimationFinishInterrupted;
     public int nextRunningTaskId = -1;
 
-    public SwipeSharedState(OverviewComponentObserver overviewComponentObserver) {
-        mOverviewComponentObserver = overviewComponentObserver;
+    public void setOverviewComponentObserver(OverviewComponentObserver observer) {
+        mOverviewComponentObserver = observer;
     }
 
     @Override
@@ -72,6 +75,12 @@
     private void clearListenerState() {
         if (mRecentsAnimationListener != null) {
             mRecentsAnimationListener.removeListener(this);
+            mRecentsAnimationListener.cancelListener();
+            if (mLastAnimationRunning && mLastAnimationTarget != null) {
+                Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(),
+                        mLastAnimationTarget::cancelAnimation);
+                mLastAnimationTarget = null;
+            }
         }
         mRecentsAnimationListener = null;
         clearAnimationTarget();
@@ -98,9 +107,10 @@
         }
 
         clearListenerState();
-        mRecentsAnimationListener = new RecentsAnimationListenerSet(mOverviewComponentObserver
-                .getActivityControlHelper().shouldMinimizeSplitScreen(),
-                this::onSwipeAnimationFinished);
+        boolean shouldMinimiseSplitScreen = mOverviewComponentObserver == null ? false
+                : mOverviewComponentObserver.getActivityControlHelper().shouldMinimizeSplitScreen();
+        mRecentsAnimationListener = new RecentsAnimationListenerSet(
+                shouldMinimiseSplitScreen, this::onSwipeAnimationFinished);
         mRecentsAnimationListener.addListener(this);
         return mRecentsAnimationListener;
     }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index e95612b..f34051f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -86,6 +86,7 @@
 import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
 import com.android.quickstep.inputconsumers.OverviewInputConsumer;
 import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
+import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
 import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -229,6 +230,10 @@
         return sConnected;
     }
 
+    private final SwipeSharedState mSwipeSharedState = new SwipeSharedState();
+    private final InputConsumer mResetGestureInputConsumer =
+            new ResetGestureInputConsumer(mSwipeSharedState);
+
     private KeyguardManager mKM;
     private ActivityManagerWrapper mAM;
     private RecentsModel mRecentsModel;
@@ -239,7 +244,6 @@
     private OverviewCallbacks mOverviewCallbacks;
     private TaskOverlayFactory mTaskOverlayFactory;
     private InputConsumerController mInputConsumer;
-    private SwipeSharedState mSwipeSharedState;
     private boolean mAssistantAvailable;
     private float mLastAssistantVisibility = 0;
     private @SystemUiStateFlags int mSystemUiStateFlags;
@@ -412,10 +416,10 @@
         mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this);
         mOverviewCallbacks = OverviewCallbacks.get(this);
         mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this);
-        mSwipeSharedState = new SwipeSharedState(mOverviewComponentObserver);
         mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
         mIsUserUnlocked = true;
 
+        mSwipeSharedState.setOverviewComponentObserver(mOverviewComponentObserver);
         mInputConsumer.registerInputConsumer();
         onSystemUiProxySet();
         onSystemUiFlagsChanged();
@@ -513,12 +517,14 @@
                 // launched while device is locked even after exiting direct boot mode (e.g. camera).
                 return createDeviceLockedInputConsumer(mAM.getRunningTask(0));
             } else {
-                return InputConsumer.NO_OP;
+                return mResetGestureInputConsumer;
             }
         }
 
-        InputConsumer base = isInValidSystemUiState
-                ? newBaseConsumer(useSharedState, event) : InputConsumer.NO_OP;
+        // When using sharedState, bypass systemState check as this is a followup gesture and the
+        // first gesture started in a valid system state.
+        InputConsumer base = isInValidSystemUiState || useSharedState
+                ? newBaseConsumer(useSharedState, event) : mResetGestureInputConsumer;
         if (mMode == Mode.NO_BUTTON) {
             final ActivityControlHelper activityControl =
                     mOverviewComponentObserver.getActivityControlHelper();
@@ -563,7 +569,7 @@
 
         if (runningTaskInfo == null && !mSwipeSharedState.goingToLauncher
                 && !mSwipeSharedState.recentsAnimationFinishInterrupted) {
-            return InputConsumer.NO_OP;
+            return mResetGestureInputConsumer;
         } else if (mSwipeSharedState.recentsAnimationFinishInterrupted) {
             // If the finish animation was interrupted, then continue using the other activity input
             // consumer but with the next task as the running task
@@ -576,7 +582,7 @@
             return createOverviewInputConsumer(event);
         } else if (mGestureBlockingActivity != null && runningTaskInfo != null
                 && mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) {
-            return InputConsumer.NO_OP;
+            return mResetGestureInputConsumer;
         } else {
             return createOtherActivityInputConsumer(event, runningTaskInfo);
         }
@@ -607,7 +613,7 @@
             return new DeviceLockedInputConsumer(this, mSwipeSharedState, mInputMonitorCompat,
                     mSwipeTouchRegion, taskInfo.taskId);
         } else {
-            return InputConsumer.NO_OP;
+            return mResetGestureInputConsumer;
         }
     }
 
@@ -616,7 +622,7 @@
                 mOverviewComponentObserver.getActivityControlHelper();
         BaseDraggingActivity activity = activityControl.getCreatedActivity();
         if (activity == null) {
-            return InputConsumer.NO_OP;
+            return mResetGestureInputConsumer;
         }
 
         if (activity.getRootView().hasWindowFocus() || mSwipeSharedState.goingToLauncher) {
@@ -633,7 +639,8 @@
      */
     private void onConsumerInactive(InputConsumer caller) {
         if (mConsumer == caller) {
-            mConsumer = InputConsumer.NO_OP;
+            mConsumer = mResetGestureInputConsumer;
+            mUncheckedConsumer = mConsumer;
         }
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
index 489eb27..a1e5d47 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
@@ -32,6 +32,19 @@
     int TYPE_ACCESSIBILITY = 1 << 5;
     int TYPE_SCREEN_PINNED = 1 << 6;
     int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7;
+    int TYPE_RESET_GESTURE = 1 << 8;
+
+    String[] NAMES = new String[] {
+           "TYPE_NO_OP",                    // 0
+            "TYPE_OVERVIEW",                // 1
+            "TYPE_OTHER_ACTIVITY",          // 2
+            "TYPE_ASSISTANT",               // 3
+            "TYPE_DEVICE_LOCKED",           // 4
+            "TYPE_ACCESSIBILITY",           // 5
+            "TYPE_SCREEN_PINNED",           // 6
+            "TYPE_OVERVIEW_WITHOUT_FOCUS",  // 7
+            "TYPE_RESET_GESTURE",           // 8
+    };
 
     InputConsumer NO_OP = () -> TYPE_NO_OP;
 
@@ -66,23 +79,15 @@
     }
 
     default String getName() {
-        switch (getType()) {
-            case TYPE_OVERVIEW:
-                return "OVERVIEW";
-            case TYPE_OTHER_ACTIVITY:
-                return "OTHER_ACTIVITY";
-            case TYPE_ASSISTANT:
-                return "ASSISTANT";
-            case TYPE_DEVICE_LOCKED:
-                return "DEVICE_LOCKED";
-            case TYPE_ACCESSIBILITY:
-                return "ACCESSIBILITY";
-            case TYPE_SCREEN_PINNED:
-                return "SCREEN_PINNED";
-            case TYPE_OVERVIEW_WITHOUT_FOCUS:
-                return "TYPE_OVERVIEW_WITHOUT_FOCUS";
-            default:
-                return "NO_OP";
+        String name = "";
+        for (int i = 0; i < NAMES.length; i++) {
+            if ((getType() & (1 << i)) != 0) {
+                if (name.length() > 0) {
+                    name += ":";
+                }
+                name += NAMES[i];
+            }
         }
+        return name;
     }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java
new file mode 100644
index 0000000..56cba21
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 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.quickstep.inputconsumers;
+
+import android.view.MotionEvent;
+
+import com.android.quickstep.SwipeSharedState;
+
+/**
+ * A NO_OP input consumer which also resets any pending gesture
+ */
+public class ResetGestureInputConsumer implements InputConsumer {
+
+    private final SwipeSharedState mSwipeSharedState;
+
+    public ResetGestureInputConsumer(SwipeSharedState swipeSharedState) {
+        mSwipeSharedState = swipeSharedState;
+    }
+
+    @Override
+    public int getType() {
+        return TYPE_RESET_GESTURE;
+    }
+
+    @Override
+    public void onMotionEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN
+                && mSwipeSharedState.getActiveListener() != null) {
+            mSwipeSharedState.clearAllState();
+        }
+    }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
index 94e704a..83601e6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
@@ -49,6 +49,8 @@
     private final Consumer<SwipeAnimationTargetSet> mOnFinishListener;
     private RecentsAnimationControllerCompat mController;
 
+    private boolean mCancelled;
+
     public RecentsAnimationListenerSet(boolean shouldMinimizeSplitScreen,
             Consumer<SwipeAnimationTargetSet> onFinishListener) {
         mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen;
@@ -75,11 +77,16 @@
         SwipeAnimationTargetSet targetSet = new SwipeAnimationTargetSet(controller, targets,
                 homeContentInsets, minimizedHomeBounds, mShouldMinimizeSplitScreen,
                 mOnFinishListener);
-        Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
-            for (SwipeAnimationListener listener : getListeners()) {
-                listener.onRecentsAnimationStart(targetSet);
-            }
-        });
+
+        if (mCancelled) {
+            targetSet.cancelAnimation();
+        } else {
+            Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
+                for (SwipeAnimationListener listener : getListeners()) {
+                    listener.onRecentsAnimationStart(targetSet);
+                }
+            });
+        }
     }
 
     @Override
@@ -99,4 +106,9 @@
     private SwipeAnimationListener[] getListeners() {
         return mListeners.toArray(new SwipeAnimationListener[mListeners.size()]);
     }
+
+    public void cancelListener() {
+        mCancelled = true;
+        onAnimationCanceled(false);
+    }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
index f5a9e8a..df9efa2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
@@ -36,7 +36,6 @@
     private final boolean mShouldMinimizeSplitScreen;
     private final Consumer<SwipeAnimationTargetSet> mOnFinishListener;
 
-
     public final RecentsAnimationControllerCompat controller;
     public final Rect homeContentInsets;
     public final Rect minimizedHomeBounds;
@@ -103,6 +102,10 @@
         return controller != null ? controller.screenshotTask(taskId) : null;
     }
 
+    public void cancelAnimation() {
+        finishController(false /* toRecents */, null, false /* sendUserLeaveHint */);
+    }
+
     public interface SwipeAnimationListener {
 
         void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet);