• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * 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.HandlerThread
20 import android.view.InputChannel
21 import android.view.InputDevice
22 import android.view.MotionEvent
23 import android.view.WindowManagerPolicyConstants.PointerEventListener
24 import com.android.server.UiThread
25 import com.android.server.wm.PointerEventDispatcher
26 import org.junit.After
27 import org.junit.Assert.assertEquals
28 import org.junit.Before
29 import org.junit.Test
30 
31 private class CrashingPointerEventListener : PointerEventListener {
32     override fun onPointerEvent(motionEvent: MotionEvent) {
33         throw IllegalArgumentException("This listener crashes when input event occurs")
34     }
35 }
36 
37 class PointerEventDispatcherTest {
38     companion object {
39         private const val TAG = "PointerEventDispatcherTest"
40     }
41 
42     private val mHandlerThread = HandlerThread("Process input events")
43     private lateinit var mSender: SpyInputEventSender
44     private lateinit var mPointerEventDispatcher: PointerEventDispatcher
45     private val mListener = CrashingPointerEventListener()
46 
47     @Before
setUpnull48     fun setUp() {
49         val channels = InputChannel.openInputChannelPair("TestChannel")
50 
51         mHandlerThread.start()
52         val looper = mHandlerThread.getLooper()
53         mSender = SpyInputEventSender(channels[0], looper)
54 
55         mPointerEventDispatcher = PointerEventDispatcher(channels[1])
56         mPointerEventDispatcher.registerInputEventListener(mListener)
57     }
58 
59     @After
tearDownnull60     fun tearDown() {
61         mHandlerThread.quitSafely()
62     }
63 
64     @Test
testSendMotionToCrashingListenerDoesNotCrashnull65     fun testSendMotionToCrashingListenerDoesNotCrash() {
66         // The exception will occur on the UiThread, so we can't catch it here on the test thread
67         UiThread.get().setUncaughtExceptionHandler { thread, exception ->
68             if (thread == UiThread.get() && exception is IllegalArgumentException) {
69                 // do nothing - this is the exception that we need to ignore
70             } else {
71                 throw exception
72             }
73         }
74 
75         // The MotionEvent properties aren't important for this test, as long as the event
76         // is a pointer event, so that it gets processed by CrashingPointerEventListener
77         val downTime = 0L
78         val motionEvent =
79             MotionEvent.obtain(
80                 downTime,
81                 downTime,
82                 MotionEvent.ACTION_DOWN,
83                 0f /* x */,
84                 0f /* y */,
85                 0, /* metaState */
86             )
87         motionEvent.source = InputDevice.SOURCE_TOUCHSCREEN
88         val seq = 10
89         mSender.sendInputEvent(seq, motionEvent)
90         val finishedSignal = mSender.getFinishedSignal()
91 
92         // Since the listener raises an exception during the event handling, the event should be
93         // marked as 'not handled'.
94         assertEquals(SpyInputEventSender.FinishedSignal(seq, handled = false), finishedSignal)
95         // Ensure that there aren't double finish calls.
96         mSender.assertNoEvents()
97     }
98 }
99