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