Added assistant gesture swipe up right side region on nav bar

Bug: 112934365
Test: manual
Change-Id: I467e71f13da4afba3a556fafb0bfdf01650ab4bf
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 8c58e3e..2b76924 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
new file mode 100644
index 0000000..e02c696
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
@@ -0,0 +1,195 @@
+/*
+ * 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;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_POINTER_UP;
+import static android.view.MotionEvent.ACTION_UP;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.Display;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
+import com.android.systemui.shared.recents.ISystemUiProxy;
+import com.android.systemui.shared.system.NavigationBarCompat;
+import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.launcher3.R;
+
+/**
+ * Touch consumer for handling events to launch assistant from launcher
+ */
+public class AssistantTouchConsumer implements InputConsumer {
+    private static final String TAG = "AssistantTouchConsumer";
+
+    private final PointF mDownPos = new PointF();
+    private final PointF mLastPos = new PointF();
+    private int mActivePointerId = -1;
+
+    private final int mDisplayRotation;
+    private final Rect mStableInsets = new Rect();
+
+    private final float mDragSlop;
+    private final float mTouchSlop;
+    private final float mThreshold;
+
+    private float mStartDisplacement;
+    private boolean mPassedDragSlop;
+    private boolean mPassedTouchSlop;
+    private long mPassedTouchSlopTime;
+    private boolean mLaunchedAssistant;
+    private float mLastProgress;
+
+    private final ISystemUiProxy mSysUiProxy;
+
+    public AssistantTouchConsumer(Context context, ISystemUiProxy systemUiProxy) {
+        mSysUiProxy = systemUiProxy;
+
+        mDragSlop = NavigationBarCompat.getQuickStepDragSlopPx();
+        mTouchSlop = NavigationBarCompat.getQuickStepTouchSlopPx();
+        mThreshold = context.getResources().getDimension(R.dimen.gestures_assistant_threshold);
+
+        Display display = context.getSystemService(WindowManager.class).getDefaultDisplay();
+        mDisplayRotation = display.getRotation();
+        WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
+    }
+
+    @Override
+    public void onMotionEvent(MotionEvent ev) {
+        // TODO add logging
+        switch (ev.getActionMasked()) {
+            case ACTION_DOWN: {
+                mActivePointerId = ev.getPointerId(0);
+                mDownPos.set(ev.getX(), ev.getY());
+                mLastPos.set(mDownPos);
+                mLastProgress = -1;
+                break;
+            }
+            case ACTION_POINTER_UP: {
+                int ptrIdx = ev.getActionIndex();
+                int ptrId = ev.getPointerId(ptrIdx);
+                if (ptrId == mActivePointerId) {
+                    final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
+                    mDownPos.set(
+                        ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
+                        ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
+                    mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
+                    mActivePointerId = ev.getPointerId(newPointerIdx);
+                }
+                break;
+            }
+            case ACTION_MOVE: {
+                int pointerIndex = ev.findPointerIndex(mActivePointerId);
+                if (pointerIndex == -1) {
+                    break;
+                }
+                mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
+                float displacement = getDisplacement(ev);
+
+                if (!mPassedDragSlop) {
+                    // Normal gesture, ensure we pass the drag slop before we start tracking
+                    // the gesture
+                    if (Math.abs(displacement) > mDragSlop) {
+                        mPassedDragSlop = true;
+                        mStartDisplacement = displacement;
+                        mPassedTouchSlopTime = SystemClock.uptimeMillis();
+                    }
+                }
+
+                if (!mPassedTouchSlop) {
+                    if (Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y) >=
+                        mTouchSlop) {
+                        mPassedTouchSlop = true;
+                        if (!mPassedDragSlop) {
+                            mPassedDragSlop = true;
+                            mStartDisplacement = displacement;
+                            mPassedTouchSlopTime = SystemClock.uptimeMillis();
+                        }
+                    }
+                }
+
+                if (mPassedDragSlop) {
+                    // Move
+                    float distance = mStartDisplacement - displacement;
+                    if (distance >= 0) {
+                        onAssistantProgress(distance / mThreshold);
+                    }
+                }
+                break;
+            }
+            case ACTION_CANCEL:
+                break;
+            case ACTION_UP: {
+                if (ev.getEventTime() - mPassedTouchSlopTime < ViewConfiguration.getTapTimeout()) {
+                    onAssistantProgress(1);
+                }
+
+                break;
+            }
+        }
+    }
+
+    private void onAssistantProgress(float progress) {
+        if (mLastProgress == progress) {
+            return;
+        }
+        try {
+            mSysUiProxy.onAssistantProgress(Math.max(0, Math.min(1, progress)));
+            if (progress >= 1 && !mLaunchedAssistant) {
+                mSysUiProxy.startAssistant(new Bundle());
+                mLaunchedAssistant = true;
+            }
+            mLastProgress = progress;
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to notify SysUI to start/send assistant progress: " + progress, e);
+        }
+    }
+
+    private boolean isNavBarOnRight() {
+        return mDisplayRotation == Surface.ROTATION_90 && mStableInsets.right > 0;
+    }
+
+    private boolean isNavBarOnLeft() {
+        return mDisplayRotation == Surface.ROTATION_270 && mStableInsets.left > 0;
+    }
+
+    private float getDisplacement(MotionEvent ev) {
+        float eventX = ev.getX();
+        float eventY = ev.getY();
+        float displacement = eventY - mDownPos.y;
+        if (isNavBarOnRight()) {
+            displacement = eventX - mDownPos.x;
+        } else if (isNavBarOnLeft()) {
+            displacement = mDownPos.x - eventX;
+        }
+        return displacement;
+    }
+
+    static boolean withinTouchRegion(Context context, float x) {
+        return x > context.getResources().getDisplayMetrics().widthPixels
+                - context.getResources().getDimension(R.dimen.gestures_assistant_width);
+    }
+}
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 cf50fc1..d1d0e86 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -44,6 +44,7 @@
 import com.android.launcher3.MainThreadExecutor;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.LooperExecutor;
 import com.android.launcher3.util.UiThreadHelper;
 import com.android.systemui.shared.recents.IOverviewProxy;
@@ -307,6 +308,10 @@
 
         if (runningTaskInfo == null && !mSwipeSharedState.goingToLauncher) {
             return InputConsumer.NO_OP;
+        } else if (mOverviewInteractionState.isSwipeUpGestureEnabled()
+                && FeatureFlags.ENABLE_ASSISTANT_GESTURE.get()
+                && AssistantTouchConsumer.withinTouchRegion(this, event.getX())) {
+            return new AssistantTouchConsumer(this, mRecentsModel.getSystemUiProxy());
         } else if (mSwipeSharedState.goingToLauncher ||
                 mOverviewComponentObserver.getActivityControlHelper().isResumed()) {
             return OverviewInputConsumer.newInstance(
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 2626481..f7126d0 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -65,4 +65,8 @@
     <dimen name="shelf_surface_radius">16dp</dimen>
     <!-- same as vertical_drag_handle_size -->
     <dimen name="shelf_surface_offset">24dp</dimen>
+
+    <!-- Assistant Gestures -->
+    <dimen name="gestures_assistant_width">70dp</dimen>
+    <dimen name="gestures_assistant_threshold">200dp</dimen>
 </resources>
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index 882529d..1e19685 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -112,6 +112,10 @@
             "ENABLE_HINTS_IN_OVERVIEW", false,
             "Show chip hints and gleams on the overview screen");
 
+    public static final TogglableFlag ENABLE_ASSISTANT_GESTURE = new TogglableFlag(
+            "ENABLE_ASSISTANT_GESTURE", false,
+            "Enable swipe up from the bottom right corner to start assistant");
+
     public static void initialize(Context context) {
         // Avoid the disk read for user builds
         if (Utilities.IS_DEBUG_DEVICE) {