Initial change for using input monitor for swipe up handling

Change-Id: Ie2cf982e86d7e47435db933bff13b29d45926c8b
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
index 63c2e5d..fb73f9e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
@@ -56,6 +56,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.BackgroundExecutor;
 import com.android.systemui.shared.system.InputConsumerController;
+import com.android.systemui.shared.system.InputMonitorCompat;
 import com.android.systemui.shared.system.NavigationBarCompat;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 
@@ -81,6 +82,7 @@
     private final TaskOverlayFactory mTaskOverlayFactory;
     private final InputConsumerController mInputConsumer;
     private final SwipeSharedState mSwipeSharedState;
+    private final InputMonitorCompat mInputMonitorCompat;
 
     private final int mDisplayRotation;
     private final Rect mStableInsets = new Rect();
@@ -118,7 +120,7 @@
             boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
             TaskOverlayFactory taskOverlayFactory, InputConsumerController inputConsumer,
             Consumer<OtherActivityInputConsumer> onCompleteCallback,
-            SwipeSharedState swipeSharedState) {
+            SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat) {
         super(base);
 
         mMainThreadHandler = new Handler(Looper.getMainLooper());
@@ -129,6 +131,7 @@
         mMotionPauseDetector = new MotionPauseDetector(base);
         mOnCompleteCallback = onCompleteCallback;
         mVelocityTracker = VelocityTracker.obtain();
+        mInputMonitorCompat = inputMonitorCompat;
 
         mActivityControlHelper = activityControl;
         boolean continuingPreviousGesture = swipeSharedState.getActiveListener() != null;
@@ -275,6 +278,7 @@
         if (mInteractionHandler == null) {
             return;
         }
+        mInputMonitorCompat.pilferPointers();
 
         mOverviewCallbacks.closeAllWindows();
         ActivityManagerWrapper.getInstance().closeSystemWindows(
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 323dd9a..60ba27d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -18,7 +18,7 @@
 import static android.view.MotionEvent.ACTION_DOWN;
 
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_CHANNEL;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
 
 import android.annotation.TargetApi;
@@ -29,17 +29,25 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.RectF;
 import android.graphics.Region;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Process;
+import android.os.RemoteException;
 import android.util.Log;
-import android.util.Pair;
 import android.view.Choreographer;
+import android.view.Display;
 import android.view.InputEvent;
 import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.WindowManager;
 
 import com.android.launcher3.MainThreadExecutor;
 import com.android.launcher3.Utilities;
@@ -48,13 +56,13 @@
 import com.android.launcher3.util.LooperExecutor;
 import com.android.launcher3.util.UiThreadHelper;
 import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.InputChannelCompat;
-import com.android.systemui.shared.system.InputChannelCompat.InputEventDispatcher;
 import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
 import com.android.systemui.shared.system.InputConsumerController;
+import com.android.systemui.shared.system.InputMonitorCompat;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -65,12 +73,16 @@
  * Service connected by system-UI for handling touch interaction.
  */
 @TargetApi(Build.VERSION_CODES.O)
-public class TouchInteractionService extends Service {
+public class TouchInteractionService extends Service implements
+        NavigationModeChangeListener, DisplayListener {
 
     public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
     public static final LooperExecutor BACKGROUND_EXECUTOR =
             new LooperExecutor(UiThreadHelper.getBackgroundLooper());
 
+    private static final String NAVBAR_VERTICAL_SIZE = "navigation_bar_frame_height";
+    private static final String NAVBAR_HORIZONTAL_SIZE = "navigation_bar_frame_width";
+
     public static final EventLogArray TOUCH_INTERACTION_LOG =
             new EventLogArray("touch_interaction_log", 40);
 
@@ -85,16 +97,12 @@
         public void onInitialize(Bundle bundle) {
             mISystemUiProxy = ISystemUiProxy.Stub
                     .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
+            MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
             runWhenUserUnlocked(() -> {
                 mRecentsModel.setSystemUiProxy(mISystemUiProxy);
                 mRecentsModel.onInitializeSystemUI(bundle);
                 mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
             });
-
-            disposeEventHandlers();
-            mInputEventReceiver = InputChannelCompat.fromBundle(bundle, KEY_EXTRA_INPUT_CHANNEL,
-                    Looper.getMainLooper(), mMainChoreographer,
-                    TouchInteractionService.this::onInputEvent);
         }
 
         @Override
@@ -137,28 +145,10 @@
         public void onPreMotionEvent(int downHitTarget) { }
 
         public void onMotionEvent(MotionEvent ev) {
-            if (mDeprecatedDispatcher == null) {
-                ev.recycle();
-            } else {
-                mDeprecatedDispatcher.dispatch(ev);
-            }
+            ev.recycle();
         }
 
-        public void onBind(ISystemUiProxy iSystemUiProxy) {
-            mISystemUiProxy = iSystemUiProxy;
-            runWhenUserUnlocked(() -> {
-                mRecentsModel.setSystemUiProxy(mISystemUiProxy);
-                mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
-            });
-
-            // On Bind is received before onInitialize which will dispose these handlers
-            disposeEventHandlers();
-            Pair<InputEventDispatcher, InputEventReceiver> pair = InputChannelCompat.createPair(
-                    "sysui-callbacks", Looper.getMainLooper(), mMainChoreographer,
-                    TouchInteractionService.this::onInputEvent);
-            mDeprecatedDispatcher = pair.first;
-            mInputEventReceiver = pair.second;
-        }
+        public void onBind(ISystemUiProxy iSystemUiProxy) { }
     };
 
     private static boolean sConnected = false;
@@ -191,13 +181,17 @@
         }
     };
 
+    private InputConsumer mUncheckedConsumer = InputConsumer.NO_OP;
     private InputConsumer mConsumer = InputConsumer.NO_OP;
     private Choreographer mMainChoreographer;
 
-    private InputEventReceiver mInputEventReceiver;
     private Region mActiveNavBarRegion = new Region();
 
-    private InputEventDispatcher mDeprecatedDispatcher;
+    private InputMonitorCompat mInputMonitorCompat;
+    private InputEventReceiver mInputEventReceiver;
+    private Mode mMode = Mode.THREE_BUTTONS;
+    private int mDefaultDisplayId;
+    private final RectF mSwipeTouchRegion = new RectF();
 
     @Override
     public void onCreate() {
@@ -215,10 +209,112 @@
             mIsUserUnlocked = false;
             registerReceiver(mUserUnlockedReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
         }
+        onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this));
 
+        mDefaultDisplayId = getSystemService(WindowManager.class).getDefaultDisplay()
+                .getDisplayId();
         sConnected = true;
     }
 
+    private void disposeEventHandlers() {
+        if (mInputEventReceiver != null) {
+            mInputEventReceiver.dispose();
+            mInputEventReceiver = null;
+        }
+        if (mInputMonitorCompat != null) {
+            mInputMonitorCompat.dispose();
+            mInputMonitorCompat = null;
+        }
+    }
+
+    private void initInputMonitor() {
+        if (!mMode.hasGestures || mISystemUiProxy == null) {
+            return;
+        }
+        disposeEventHandlers();
+
+        try {
+            mInputMonitorCompat = InputMonitorCompat.fromBundle(mISystemUiProxy
+                    .monitorGestureInput("swipe-up", mDefaultDisplayId), KEY_EXTRA_INPUT_MONITOR);
+            mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
+                    mMainChoreographer, this::onInputEvent);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to create input monitor", e);
+        }
+        initTouchBounds();
+    }
+
+    private int getNavbarSize(String resName) {
+        int frameSize;
+        Resources res = getResources();
+        int frameSizeResID = res.getIdentifier(resName, "dimen", "android");
+        if (frameSizeResID != 0) {
+            frameSize = res.getDimensionPixelSize(frameSizeResID);
+        } else {
+            frameSize = Utilities.pxFromDp(48, res.getDisplayMetrics());
+        }
+        return frameSize;
+    }
+
+    private void initTouchBounds() {
+        if (!mMode.hasGestures) {
+            return;
+        }
+
+        Display defaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay();
+        Point realSize = new Point();
+        defaultDisplay.getRealSize(realSize);
+        mSwipeTouchRegion.set(0, 0, realSize.x, realSize.y);
+        if (mMode == Mode.NO_BUTTON) {
+            mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize(NAVBAR_VERTICAL_SIZE);
+        } else {
+            switch (defaultDisplay.getRotation()) {
+                case Surface.ROTATION_90:
+                    mSwipeTouchRegion.left = mSwipeTouchRegion.right
+                            - getNavbarSize(NAVBAR_HORIZONTAL_SIZE);
+                    break;
+                case Surface.ROTATION_270:
+                    mSwipeTouchRegion.right = mSwipeTouchRegion.left
+                            + getNavbarSize(NAVBAR_HORIZONTAL_SIZE);
+                    break;
+                default:
+                    mSwipeTouchRegion.top = mSwipeTouchRegion.bottom
+                            - getNavbarSize(NAVBAR_VERTICAL_SIZE);
+            }
+        }
+    }
+
+    @Override
+    public void onNavigationModeChanged(Mode newMode) {
+        if (mMode.hasGestures != newMode.hasGestures) {
+            if (newMode.hasGestures) {
+                getSystemService(DisplayManager.class).registerDisplayListener(
+                        this, MAIN_THREAD_EXECUTOR.getHandler());
+            } else {
+                getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+            }
+        }
+        mMode = newMode;
+
+        disposeEventHandlers();
+        initInputMonitor();
+    }
+
+    @Override
+    public void onDisplayAdded(int i) { }
+
+    @Override
+    public void onDisplayRemoved(int i) { }
+
+    @Override
+    public void onDisplayChanged(int displayId) {
+        if (displayId != mDefaultDisplayId) {
+            return;
+        }
+
+        initTouchBounds();
+    }
+
     private void initWhenUserUnlocked() {
         mIsUserUnlocked = true;
 
@@ -260,20 +356,15 @@
             mOverviewComponentObserver.onDestroy();
         }
         disposeEventHandlers();
+        if (mMode.hasGestures) {
+            getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+        }
+
         sConnected = false;
         Utilities.unregisterReceiverSafely(this, mUserUnlockedReceiver);
-        super.onDestroy();
-    }
+        SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
 
-    private void disposeEventHandlers() {
-        if (mInputEventReceiver != null) {
-            mInputEventReceiver.dispose();
-            mInputEventReceiver = null;
-        }
-        if (mDeprecatedDispatcher != null) {
-            mDeprecatedDispatcher.dispose();
-            mDeprecatedDispatcher = null;
-        }
+        super.onDestroy();
     }
 
     @Override
@@ -290,12 +381,17 @@
         MotionEvent event = (MotionEvent) ev;
         TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
         if (event.getAction() == ACTION_DOWN) {
-            boolean useSharedState = mConsumer.isActive();
-            mConsumer.onConsumerAboutToBeSwitched();
-            mConsumer = newConsumer(useSharedState, event);
-            TOUCH_INTERACTION_LOG.addLog("setInputConsumer", mConsumer.getType());
+            if (mSwipeTouchRegion.contains(event.getX(), event.getY())) {
+                boolean useSharedState = mConsumer.isActive();
+                mConsumer.onConsumerAboutToBeSwitched();
+                mConsumer = newConsumer(useSharedState, event);
+                TOUCH_INTERACTION_LOG.addLog("setInputConsumer", mConsumer.getType());
+                mUncheckedConsumer = mConsumer;
+            } else {
+                mUncheckedConsumer = InputConsumer.NO_OP;
+            }
         }
-        mConsumer.onMotionEvent(event);
+        mUncheckedConsumer.onMotionEvent(event);
     }
 
     private InputConsumer newConsumer(boolean useSharedState, MotionEvent event) {
@@ -338,7 +434,7 @@
         return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel,
                 mOverviewComponentObserver.getOverviewIntent(), activityControl,
                 shouldDefer, mOverviewCallbacks, mTaskOverlayFactory, mInputConsumer,
-                this::onConsumerInactive, mSwipeSharedState);
+                this::onConsumerInactive, mSwipeSharedState, mInputMonitorCompat);
     }
 
     /**