• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wm.shell.back;
18 
19 import android.os.SystemProperties;
20 import android.view.RemoteAnimationTarget;
21 import android.window.BackEvent;
22 import android.window.BackMotionEvent;
23 
24 /**
25  * Helper class to record the touch location for gesture and generate back events.
26  */
27 class TouchTracker {
28     private static final String PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP =
29             "persist.wm.debug.predictive_back_progress_threshold";
30     private static final int PROGRESS_THRESHOLD = SystemProperties
31             .getInt(PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP, -1);
32     private float mProgressThreshold;
33     /**
34      * Location of the latest touch event
35      */
36     private float mLatestTouchX;
37     private float mLatestTouchY;
38     private boolean mTriggerBack;
39 
40     /**
41      * Location of the initial touch event of the back gesture.
42      */
43     private float mInitTouchX;
44     private float mInitTouchY;
45     private float mStartThresholdX;
46     private int mSwipeEdge;
47     private boolean mCancelled;
48 
update(float touchX, float touchY)49     void update(float touchX, float touchY) {
50         /**
51          * If back was previously cancelled but the user has started swiping in the forward
52          * direction again, restart back.
53          */
54         if (mCancelled && ((touchX > mLatestTouchX && mSwipeEdge == BackEvent.EDGE_LEFT)
55                 || touchX < mLatestTouchX && mSwipeEdge == BackEvent.EDGE_RIGHT)) {
56             mCancelled = false;
57             mStartThresholdX = touchX;
58         }
59         mLatestTouchX = touchX;
60         mLatestTouchY = touchY;
61     }
62 
setTriggerBack(boolean triggerBack)63     void setTriggerBack(boolean triggerBack) {
64         if (mTriggerBack != triggerBack && !triggerBack) {
65             mCancelled = true;
66         }
67         mTriggerBack = triggerBack;
68     }
69 
setGestureStartLocation(float touchX, float touchY, int swipeEdge)70     void setGestureStartLocation(float touchX, float touchY, int swipeEdge) {
71         mInitTouchX = touchX;
72         mInitTouchY = touchY;
73         mSwipeEdge = swipeEdge;
74         mStartThresholdX = mInitTouchX;
75     }
76 
reset()77     void reset() {
78         mInitTouchX = 0;
79         mInitTouchY = 0;
80         mStartThresholdX = 0;
81         mCancelled = false;
82         mTriggerBack = false;
83         mSwipeEdge = BackEvent.EDGE_LEFT;
84     }
85 
createStartEvent(RemoteAnimationTarget target)86     BackMotionEvent createStartEvent(RemoteAnimationTarget target) {
87         return new BackMotionEvent(mInitTouchX, mInitTouchY, 0, mSwipeEdge, target);
88     }
89 
createProgressEvent()90     BackMotionEvent createProgressEvent() {
91         float progressThreshold = PROGRESS_THRESHOLD >= 0
92                 ? PROGRESS_THRESHOLD : mProgressThreshold;
93         progressThreshold = progressThreshold == 0 ? 1 : progressThreshold;
94         float progress = 0;
95         // Progress is always 0 when back is cancelled and not restarted.
96         if (!mCancelled) {
97             // If back is committed, progress is the distance between the last and first touch
98             // point, divided by the max drag distance. Otherwise, it's the distance between
99             // the last touch point and the starting threshold, divided by max drag distance.
100             // The starting threshold is initially the first touch location, and updated to
101             // the location everytime back is restarted after being cancelled.
102             float startX = mTriggerBack ? mInitTouchX : mStartThresholdX;
103             float deltaX = Math.max(
104                     mSwipeEdge == BackEvent.EDGE_LEFT
105                             ? mLatestTouchX - startX
106                             : startX - mLatestTouchX,
107                     0);
108             progress = Math.min(Math.max(deltaX / progressThreshold, 0), 1);
109         }
110         return createProgressEvent(progress);
111     }
112 
createProgressEvent(float progress)113     BackMotionEvent createProgressEvent(float progress) {
114         return new BackMotionEvent(mLatestTouchX, mLatestTouchY, progress, mSwipeEdge, null);
115     }
116 
setProgressThreshold(float progressThreshold)117     public void setProgressThreshold(float progressThreshold) {
118         mProgressThreshold = progressThreshold;
119     }
120 }
121