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