• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 android.view;
18 
19 import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
20 import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
21 
22 /**
23  * Process input events and assign input event id to a specific frame.
24  *
25  * The assigned input event id is determined by where the current gesture is relative to the vsync.
26  * In the middle of the gesture (we already processed some input events, and already received at
27  * least 1 vsync), the latest InputEvent is assigned to the next frame.
28  * If a gesture just started, then the ACTION_DOWN event will be assigned to the next frame.
29  *
30  * Consider the following sequence:
31  * DOWN -> VSYNC 1 -> MOVE 1 -> MOVE 2 -> VSYNC 2.
32  *
33  * For VSYNC 1, we will assign the "DOWN" input event.
34  * For VSYNC 2, we will assign the "MOVE 2" input event.
35  *
36  * Consider another sequence:
37  * DOWN -> MOVE 1 -> MOVE 2 -> VSYNC 1 -> MOVE 3 -> VSYNC 2.
38  *
39  * For VSYNC 1, we will still assign the "DOWN" input event. That means that "MOVE 1" and "MOVE 2"
40  * events are not attributed to any frame.
41  * For VSYNC 2, the "MOVE 3" input event will be assigned.
42  *
43  * @hide
44  */
45 public class InputEventAssigner {
46     private static final String TAG = "InputEventAssigner";
47     private boolean mHasUnprocessedDown = false;
48     private int mDownEventId = INVALID_INPUT_EVENT_ID;
49 
50     /**
51      * Notify InputEventAssigner that a frame has been processed. We no longer need to keep track of
52      * the DOWN event because a frame has already been produced for it.
53      */
notifyFrameProcessed()54     public void notifyFrameProcessed() {
55         // Mark completion of this frame. Use newest input event from now on.
56         mHasUnprocessedDown = false;
57     }
58 
59     /**
60      * Process the provided input event to determine which event id to assign to the current frame.
61      * @param event the input event currently being processed
62      * @return the id of the input event to use for the current frame
63      */
processEvent(InputEvent event)64     public int processEvent(InputEvent event) {
65         if (event instanceof MotionEvent) {
66             MotionEvent motionEvent = (MotionEvent) event;
67             if (motionEvent.isFromSource(SOURCE_TOUCHSCREEN)) {
68                 final int action = motionEvent.getActionMasked();
69                 if (action == MotionEvent.ACTION_DOWN) {
70                     mHasUnprocessedDown = true;
71                     mDownEventId = event.getId();
72                 }
73                 if (mHasUnprocessedDown && action == MotionEvent.ACTION_MOVE) {
74                     return mDownEventId;
75                 }
76                 if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
77                     mHasUnprocessedDown = false;
78                 }
79             }
80         }
81         return event.getId();
82     }
83 }
84