Merge "QuickCaptureInputConsumer -> OverscrollInputConsumer + plugin" into ub-launcher3-master
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 e3fcd2f..8d7a534 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -35,6 +35,7 @@
 import android.app.Service;
 import android.app.TaskInfo;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
@@ -49,19 +50,18 @@
 import android.view.MotionEvent;
 
 import androidx.annotation.BinderThread;
+import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 import androidx.annotation.WorkerThread;
 
 import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.DiscoveryBounce;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.UserEventDispatcher;
 import com.android.launcher3.model.AppLaunchTracker;
 import com.android.launcher3.provider.RestoreDbTask;
 import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.SysUINavigationMode.Mode;
 import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
@@ -70,12 +70,14 @@
 import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
 import com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer;
 import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
+import com.android.quickstep.inputconsumers.OverscrollInputConsumer;
 import com.android.quickstep.inputconsumers.OverviewInputConsumer;
 import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
-import com.android.quickstep.inputconsumers.QuickCaptureInputConsumer;
 import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
 import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
 import com.android.quickstep.util.ActiveGestureLog;
+import com.android.systemui.plugins.OverscrollPlugin;
+import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -113,7 +115,7 @@
  */
 @TargetApi(Build.VERSION_CODES.Q)
 public class TouchInteractionService extends Service implements
-        NavigationModeChangeListener {
+        NavigationModeChangeListener, PluginListener<OverscrollPlugin> {
 
     private static final String TAG = "TouchInteractionService";
 
@@ -122,6 +124,8 @@
     private static final String HAS_ENABLED_QUICKSTEP_ONCE = "launcher.has_enabled_quickstep_once";
     private static final int MAX_BACK_NOTIFICATION_COUNT = 3;
     private int mBackGestureNotificationCounter = -1;
+    @Nullable
+    private OverscrollPlugin mOverscrollPlugin;
 
     private final IBinder mMyBinder = new IOverviewProxy.Stub() {
 
@@ -280,6 +284,9 @@
 
         onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this));
         sConnected = true;
+
+        PluginManagerWrapper.INSTANCE.get(getBaseContext()).addPluginListener(this,
+                OverscrollPlugin.class, false /* allowMultiple */);
     }
 
     private void disposeEventHandlers() {
@@ -400,6 +407,9 @@
         if (TestProtocol.sDebugTracing) {
             Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, "TIS destroyed");
         }
+
+        PluginManagerWrapper.INSTANCE.get(getBaseContext()).removePluginListener(this);
+
         sIsInitialized = false;
         if (mDeviceState.isUserUnlocked()) {
             mInputConsumer.unregisterInputConsumer();
@@ -489,10 +499,10 @@
                 base = new AssistantInputConsumer(this, newGestureState, base, mInputMonitorCompat);
             }
 
-            if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) {
-                // Put the Compose gesture as higher priority than the Assistant or base gestures
-                base = new QuickCaptureInputConsumer(this, newGestureState, base,
-                        mInputMonitorCompat);
+            if (mOverscrollPlugin != null) {
+                // Put the overscroll gesture as higher priority than the Assistant or base gestures
+                base = new OverscrollInputConsumer(this, newGestureState, base, mInputMonitorCompat,
+                        mOverscrollPlugin);
             }
 
             if (mDeviceState.isScreenPinningActive()) {
@@ -531,9 +541,9 @@
                     () -> mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
             if (!ActivityManagerWrapper.isHomeTask(runningTaskInfo)) {
                 final ComponentName homeComponent =
-                    mOverviewComponentObserver.getHomeIntent().getComponent();
+                        mOverviewComponentObserver.getHomeIntent().getComponent();
                 forceOverviewInputConsumer =
-                    runningTaskInfo.baseIntent.getComponent(). equals(homeComponent);
+                        runningTaskInfo.baseIntent.getComponent().equals(homeComponent);
             }
         }
 
@@ -763,4 +773,14 @@
         UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
                 .startRecentsActivity(intent, null, listener, null, null));
     }
+
+    @Override
+    public void onPluginConnected(OverscrollPlugin overscrollPlugin, Context context) {
+        mOverscrollPlugin = overscrollPlugin;
+    }
+
+    @Override
+    public void onPluginDisconnected(OverscrollPlugin overscrollPlugin) {
+        mOverscrollPlugin = null;
+    }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/QuickCaptureInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
similarity index 74%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/QuickCaptureInputConsumer.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
index 9826b3a..e3da98b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/QuickCaptureInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
@@ -24,39 +24,28 @@
 
 import static com.android.launcher3.Utilities.squaredHypot;
 
-import android.app.ActivityOptions;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.graphics.PointF;
-import android.os.Bundle;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.R;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.views.RecentsView;
+import com.android.systemui.plugins.OverscrollPlugin;
 import com.android.systemui.shared.system.InputMonitorCompat;
 
 /**
- * Input consumer for handling events to launch quick capture from launcher
+ * Input consumer for handling events to pass to an {@code OverscrollPlugin}.
+ *
  * @param <T> Draggable activity subclass used by RecentsView
  */
-public class QuickCaptureInputConsumer<T extends BaseDraggingActivity>
-        extends DelegateInputConsumer {
+public class OverscrollInputConsumer<T extends BaseDraggingActivity> extends DelegateInputConsumer {
 
-    private static final String TAG = "QuickCaptureInputConsumer";
-
-    private static final String QUICK_CAPTURE_PACKAGE = "com.google.auxe.compose";
-    private static final String QUICK_CAPTURE_PACKAGE_DEV = "com.google.auxe.compose.debug";
-
-    private static final String EXTRA_DEVICE_STATE = "deviceState";
-    private static final String DEVICE_STATE_LOCKED = "Locked";
-    private static final String DEVICE_STATE_LAUNCHER = "Launcher";
-    private static final String DEVICE_STATE_APP = "App";
-    private static final String DEVICE_STATE_UNKNOWN = "Unknown";
+    private static final String TAG = "OverscrollInputConsumer";
 
     private static final int ANGLE_THRESHOLD = 35; // Degrees
 
@@ -71,14 +60,16 @@
 
     private final Context mContext;
     private final GestureState mGestureState;
+    @Nullable private final OverscrollPlugin mPlugin;
 
     private RecentsView mRecentsView;
 
-    public QuickCaptureInputConsumer(Context context, GestureState gestureState,
-            InputConsumer delegate, InputMonitorCompat inputMonitor) {
+    public OverscrollInputConsumer(Context context, GestureState gestureState,
+            InputConsumer delegate, InputMonitorCompat inputMonitor, OverscrollPlugin plugin) {
         super(delegate, inputMonitor);
         mContext = context;
         mGestureState = gestureState;
+        mPlugin = plugin;
 
         float slop = ViewConfiguration.get(context).getScaledTouchSlop();
         mSquaredSlop = slop * slop;
@@ -89,7 +80,7 @@
 
     @Override
     public int getType() {
-        return TYPE_QUICK_CAPTURE | mDelegate.getType();
+        return TYPE_OVERSCROLL | mDelegate.getType();
     }
 
     private boolean onActivityInit(Boolean alreadyOnHome) {
@@ -149,7 +140,7 @@
                         mPassedSlop = true;
                         mStartDragPos.set(mLastPos.x, mLastPos.y);
 
-                        if (isValidQuickCaptureGesture()) {
+                        if (isOverscrolled()) {
                             setActive(ev);
                         } else {
                             mState = STATE_DELEGATE_ACTIVE;
@@ -161,8 +152,8 @@
             }
             case ACTION_CANCEL:
             case ACTION_UP:
-                if (mState != STATE_DELEGATE_ACTIVE && mPassedSlop) {
-                    startQuickCapture();
+                if (mState != STATE_DELEGATE_ACTIVE && mPassedSlop && mPlugin != null) {
+                    mPlugin.onOverscroll(getDeviceState());
                 }
 
                 mPassedSlop = false;
@@ -175,7 +166,7 @@
         }
     }
 
-    private boolean isValidQuickCaptureGesture() {
+    private boolean isOverscrolled() {
         // Make sure there isn't an app to quick switch to on our right
         boolean atRightMostApp = (mRecentsView == null || mRecentsView.getRunningTaskIndex() <= 0);
 
@@ -187,37 +178,19 @@
         return atRightMostApp && angleInBounds;
     }
 
-    private void startQuickCapture() {
-        // Inspect our delegate's type to figure out where the user invoked Compose
-        String deviceState = DEVICE_STATE_UNKNOWN;
+    private String getDeviceState() {
+        String deviceState = OverscrollPlugin.DEVICE_STATE_UNKNOWN;
         int consumerType = mDelegate.getType();
         if (((consumerType & InputConsumer.TYPE_OVERVIEW) > 0)
                 || ((consumerType & InputConsumer.TYPE_OVERVIEW_WITHOUT_FOCUS)) > 0) {
-            deviceState = DEVICE_STATE_LAUNCHER;
+            deviceState = OverscrollPlugin.DEVICE_STATE_LAUNCHER;
         } else if ((consumerType & InputConsumer.TYPE_OTHER_ACTIVITY) > 0) {
-            deviceState = DEVICE_STATE_APP;
+            deviceState = OverscrollPlugin.DEVICE_STATE_APP;
         } else if (((consumerType & InputConsumer.TYPE_RESET_GESTURE) > 0)
                 || ((consumerType & InputConsumer.TYPE_DEVICE_LOCKED) > 0)) {
-            deviceState = DEVICE_STATE_LOCKED;
+            deviceState = OverscrollPlugin.DEVICE_STATE_LOCKED;
         }
 
-        // Then launch the app
-        PackageManager pm = mContext.getPackageManager();
-
-        Intent qcIntent = pm.getLaunchIntentForPackage(QUICK_CAPTURE_PACKAGE);
-
-        if (qcIntent == null) {
-            // If we couldn't find the regular app, try the dev version
-            qcIntent = pm.getLaunchIntentForPackage(QUICK_CAPTURE_PACKAGE_DEV);
-        }
-
-        if (qcIntent != null) {
-            qcIntent.putExtra(EXTRA_DEVICE_STATE, deviceState);
-
-            Bundle options = ActivityOptions.makeCustomAnimation(mContext, R.anim.slide_in_right,
-                    0).toBundle();
-
-            mContext.startActivity(qcIntent, options);
-        }
+        return deviceState;
     }
 }
diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java
index 918645d..3e84e7d 100644
--- a/quickstep/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/src/com/android/quickstep/InputConsumer.java
@@ -33,7 +33,7 @@
     int TYPE_SCREEN_PINNED = 1 << 6;
     int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7;
     int TYPE_RESET_GESTURE = 1 << 8;
-    int TYPE_QUICK_CAPTURE = 1 << 9;
+    int TYPE_OVERSCROLL = 1 << 9;
 
     String[] NAMES = new String[] {
            "TYPE_NO_OP",                    // 0
@@ -45,7 +45,7 @@
             "TYPE_SCREEN_PINNED",           // 6
             "TYPE_OVERVIEW_WITHOUT_FOCUS",  // 7
             "TYPE_RESET_GESTURE",           // 8
-            "TYPE_QUICK_CAPTURE",           // 9
+            "TYPE_OVERSCROLL",              // 9
     };
 
     InputConsumer NO_OP = () -> TYPE_NO_OP;
diff --git a/res/anim/slide_in_right.xml b/res/anim/slide_in_right.xml
deleted file mode 100644
index 55d3e54..0000000
--- a/res/anim/slide_in_right.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shareInterpolator="false" >
-  <translate
-      android:duration="@android:integer/config_shortAnimTime"
-      android:fromXDelta="100%"
-      android:toXDelta="0%"
-      />
-</set>
\ No newline at end of file
diff --git a/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java b/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java
new file mode 100644
index 0000000..60eb304
--- /dev/null
+++ b/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java
@@ -0,0 +1,44 @@
+/*
+ * 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.systemui.plugins;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/**
+ * Implement this interface to receive a callback when the user swipes right
+ * to left on the gesture area. It won't fire if the user has quick switched to a previous app
+ * (swiped right) and the current app isn't yet the active one (i.e., if swiping left would take
+ * the user to a more recent app).
+ */
+@ProvidesInterface(action = com.android.systemui.plugins.OverscrollPlugin.ACTION,
+        version = com.android.systemui.plugins.OverlayPlugin.VERSION)
+public interface OverscrollPlugin extends Plugin {
+
+    String ACTION = "com.android.systemui.action.PLUGIN_LAUNCHER_OVERSCROLL";
+    int VERSION = 1;
+
+    String DEVICE_STATE_LOCKED = "Locked";
+    String DEVICE_STATE_LAUNCHER = "Launcher";
+    String DEVICE_STATE_APP = "App";
+    String DEVICE_STATE_UNKNOWN = "Unknown";
+
+    /**
+     * Called when the user completed a right to left swipe in the gesture area.
+     *
+     * @param deviceState One of the DEVICE_STATE_* constants.
+     */
+    void onOverscroll(String deviceState);
+}