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 com.android.test.input 18 19 import android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS 20 import android.os.Looper 21 import android.view.InputChannel 22 import android.view.InputEvent 23 import android.view.InputEventReceiver 24 import android.view.InputEventSender 25 import android.view.KeyEvent 26 import android.view.MotionEvent 27 import java.util.concurrent.LinkedBlockingQueue 28 import java.util.concurrent.TimeUnit 29 30 private fun <T> getEvent(queue: LinkedBlockingQueue<T>): T? { 31 return queue.poll(DEFAULT_DISPATCHING_TIMEOUT_MILLIS.toLong(), TimeUnit.MILLISECONDS) 32 } 33 34 class SpyInputEventReceiver(channel: InputChannel, looper: Looper) : 35 InputEventReceiver(channel, looper) { 36 private val mInputEvents = LinkedBlockingQueue<InputEvent>() 37 38 override fun onInputEvent(event: InputEvent) { 39 when (event) { 40 is KeyEvent -> mInputEvents.put(KeyEvent.obtain(event)) 41 is MotionEvent -> mInputEvents.put(MotionEvent.obtain(event)) 42 else -> throw Exception("Received $event is neither a key nor a motion") 43 } 44 finishInputEvent(event, true /*handled*/) 45 } 46 47 fun getInputEvent(): InputEvent? { 48 return getEvent(mInputEvents) 49 } 50 } 51 52 class SpyInputEventSender(channel: InputChannel, looper: Looper) : 53 InputEventSender(channel, looper) { 54 data class FinishedSignal(val seq: Int, val handled: Boolean) 55 data class Timeline(val inputEventId: Int, val gpuCompletedTime: Long, val presentTime: Long) 56 57 private val mFinishedSignals = LinkedBlockingQueue<FinishedSignal>() 58 private val mTimelines = LinkedBlockingQueue<Timeline>() 59 60 override fun onInputEventFinished(seq: Int, handled: Boolean) { 61 mFinishedSignals.put(FinishedSignal(seq, handled)) 62 } 63 64 override fun onTimelineReported(inputEventId: Int, gpuCompletedTime: Long, presentTime: Long) { 65 mTimelines.put(Timeline(inputEventId, gpuCompletedTime, presentTime)) 66 } 67 68 fun getFinishedSignal(): FinishedSignal? { 69 return getEvent(mFinishedSignals) 70 } 71 72 fun getTimeline(): Timeline? { 73 return getEvent(mTimelines) 74 } 75 } 76