content: /*
   * 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 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_UP;
  
  import static com.android.launcher3.Utilities.squaredHypot;
  import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
  
  import android.content.Context;
  import android.content.Intent;
  import android.graphics.PointF;
  import android.view.MotionEvent;
  import android.view.VelocityTracker;
  import android.view.ViewConfiguration;
  
  import com.android.launcher3.BaseActivity;
  import com.android.launcher3.BaseDraggingActivity;
  import com.android.launcher3.Utilities;
  import com.android.launcher3.logging.StatsLogUtils;
  import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
  import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
  import com.android.quickstep.util.NavBarPosition;
  import com.android.systemui.shared.system.InputMonitorCompat;
  
  public class OverviewWithoutFocusInputConsumer implements InputConsumer {
  
      private final InputMonitorCompat mInputMonitor;
      private final boolean mDisableHorizontalSwipe;
      private final PointF mDownPos = new PointF();
      private final float mSquaredTouchSlop;
      private final Context mContext;
      private final NavBarPosition mNavBarPosition;
  
      private boolean mInterceptedTouch;
      private VelocityTracker mVelocityTracker;
  
  
      public OverviewWithoutFocusInputConsumer(Context context, InputMonitorCompat inputMonitor,
              boolean disableHorizontalSwipe) {
          mInputMonitor = inputMonitor;
          mDisableHorizontalSwipe = disableHorizontalSwipe;
          mContext = context;
          mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
          mNavBarPosition = new NavBarPosition(context);
  
          mVelocityTracker = VelocityTracker.obtain();
      }
  
      @Override
      public int getType() {
          return TYPE_OVERVIEW_WITHOUT_FOCUS;
      }
  
      @Override
      public boolean allowInterceptByParent() {
          return !mInterceptedTouch;
      }
  
      private void endTouchTracking() {
          if (mVelocityTracker != null) {
              mVelocityTracker.recycle();
              mVelocityTracker = null;
          }
      }
  
      @Override
      public void onMotionEvent(MotionEvent ev) {
          if (mVelocityTracker == null) {
              return;
          }
  
          mVelocityTracker.addMovement(ev);
          switch (ev.getActionMasked()) {
              case ACTION_DOWN: {
                  mDownPos.set(ev.getX(), ev.getY());
                  break;
              }
              case ACTION_MOVE: {
                  if (!mInterceptedTouch) {
                      float displacementX = ev.getX() - mDownPos.x;
                      float displacementY = ev.getY() - mDownPos.y;
                      if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) {
                          if (mDisableHorizontalSwipe
                                  && Math.abs(displacementX) > Math.abs(displacementY)) {
                              // Horizontal gesture is not allowed in this region
                              endTouchTracking();
                              break;
                          }
  
                          mInterceptedTouch = true;
  
                          if (mInputMonitor != null) {
                              mInputMonitor.pilferPointers();
                          }
                      }
                  }
                  break;
              }
  
              case ACTION_CANCEL:
                  endTouchTracking();
                  break;
  
              case ACTION_UP: {
                  finishTouchTracking(ev);
                  endTouchTracking();
                  break;
              }
          }
      }
  
      private void finishTouchTracking(MotionEvent ev) {
          mVelocityTracker.computeCurrentVelocity(100);
          float velocityX = mVelocityTracker.getXVelocity();
          float velocityY = mVelocityTracker.getYVelocity();
          float velocity = mNavBarPosition.isRightEdge()
                  ? -velocityX : (mNavBarPosition.isLeftEdge() ? velocityX : -velocityY);
  
          final boolean triggerQuickstep;
          int touch = Touch.FLING;
          if (Math.abs(velocity) >= ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) {
              triggerQuickstep = velocity > 0;
          } else {
              float displacementX = mDisableHorizontalSwipe ? 0 : (ev.getX() - mDownPos.x);
              float displacementY = ev.getY() - mDownPos.y;
              triggerQuickstep = squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop;
              touch = Touch.SWIPE;
          }
  
          if (triggerQuickstep) {
              mContext.startActivity(new Intent(Intent.ACTION_MAIN)
                      .addCategory(Intent.CATEGORY_HOME)
                      .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
              TOUCH_INTERACTION_LOG.addLog("startQuickstep");
              BaseActivity activity = BaseDraggingActivity.fromContext(mContext);
              int pageIndex = -1; // This number doesn't reflect workspace page index.
                                  // It only indicates that launcher client screen was shown.
              int containerType = StatsLogUtils.getContainerTypeFromState(activity.getCurrentState());
              activity.getUserEventDispatcher().logActionOnContainer(
                      touch, Direction.UP, containerType, pageIndex);
              activity.getUserEventDispatcher().setPreviousHomeGesture(true);
          } else {
              // ignore
          }
      }
  }
  