• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2024 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.input.cts
18 
19 import android.app.Activity
20 import android.graphics.Color
21 import android.server.wm.CtsWindowInfoUtils.waitForWindowVisible
22 import android.view.Gravity
23 import android.view.InputDevice.SOURCE_STYLUS
24 import android.view.InputDevice.SOURCE_TOUCHSCREEN
25 import android.view.InputEvent
26 import android.view.KeyEvent
27 import android.view.MotionEvent
28 import android.view.View
29 import android.view.ViewGroup
30 import android.view.WindowInsets
31 import android.view.WindowManager
32 import android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
33 import android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
34 import android.view.WindowManager.LayoutParams.TYPE_APPLICATION
35 import java.util.concurrent.FutureTask
36 import java.util.concurrent.LinkedBlockingQueue
37 import java.util.concurrent.TimeUnit
38 import org.junit.Assert.assertNull
39 import org.junit.Assert.fail
40 
41 private fun assertNoEvents(queue: LinkedBlockingQueue<InputEvent>) {
42     val event = queue.poll(100, TimeUnit.MILLISECONDS)
43     assertNull("Expected no events, but received $event", event)
44 }
45 
46 class TwoWindowsActivity : Activity() {
47     private val leftWindowEvents = LinkedBlockingQueue<InputEvent>()
48     private val rightWindowEvents = LinkedBlockingQueue<InputEvent>()
49 
50     /**
51      * Launch two windows and wait for them to be visible. Must not be called on UI thread.
52      */
launchTwoWindowsnull53     fun launchTwoWindows() {
54         lateinit var leftView: View
55         lateinit var rightView: View
56         val addWindowsTask = FutureTask<Unit> {
57             val wm = getSystemService(WindowManager::class.java)
58             var wmlp = WindowManager.LayoutParams(
59                 TYPE_APPLICATION,
60                 FLAG_NOT_TOUCH_MODAL or FLAG_SPLIT_TOUCH
61             )
62 
63             val windowMetrics = windowManager.currentWindowMetrics
64             val insets = windowMetrics.windowInsets.getInsetsIgnoringVisibility(
65                 WindowInsets.Type.systemBars()
66             )
67             val width = windowMetrics.bounds.width() - insets.left - insets.right
68             val height = windowMetrics.bounds.height() - insets.top - insets.bottom
69 
70             wmlp.setTitle("Left -- " + getPackageName())
71             wmlp.width = width / 2
72             wmlp.height = height
73             wmlp.gravity = Gravity.TOP or Gravity.LEFT
74             wmlp.setTitle(getPackageName())
75 
76             val vglp = ViewGroup.LayoutParams(
77                 ViewGroup.LayoutParams.MATCH_PARENT,
78                 ViewGroup.LayoutParams.MATCH_PARENT
79             )
80 
81             leftView = View(this)
82             leftView.setOnTouchListener { _: View, event: MotionEvent ->
83                                             leftWindowEvents.add(MotionEvent.obtain(event)); true }
84             leftView.setOnHoverListener { _, event ->
85                                             leftWindowEvents.add(MotionEvent.obtain(event)); true }
86             leftView.setBackgroundColor(Color.GREEN)
87             leftView.setLayoutParams(vglp)
88             wm.addView(leftView, wmlp)
89 
90             wmlp.setTitle("Right -- " + getPackageName())
91             wmlp.gravity = Gravity.TOP or Gravity.RIGHT
92 
93             rightView = View(this)
94             rightView.setBackgroundColor(Color.BLUE)
95             rightView.setOnTouchListener{ _: View, event: MotionEvent ->
96                                             rightWindowEvents.add(MotionEvent.obtain(event)); true }
97             rightView.setOnHoverListener { _, event ->
98                                             rightWindowEvents.add(MotionEvent.obtain(event)); true }
99             rightView.setLayoutParams(vglp)
100 
101             wm.addView(rightView, wmlp)
102 
103             // Disable resampling, otherwise ACTION_MOVE events could contain unexpected coordinates
104             leftView.requestUnbufferedDispatch(SOURCE_TOUCHSCREEN or SOURCE_STYLUS)
105             rightView.requestUnbufferedDispatch(SOURCE_TOUCHSCREEN or SOURCE_STYLUS)
106         }
107         runOnUiThread(addWindowsTask)
108         try {
109             addWindowsTask.get(); // this will block until FutureTask completes on the main thread
110         } catch (e: Exception) {
111             fail("Interrupted while waiting to add windows")
112         }
113 
114         waitForWindowVisible(leftView)
115         waitForWindowVisible(rightView)
116     }
117 
dispatchGenericMotionEventnull118     override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
119         fail("Unexpected event " + ev)
120         return true
121     }
122 
dispatchTouchEventnull123     override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
124         fail("Unexpected event " + ev)
125         return true
126     }
127 
dispatchKeyEventnull128     override fun dispatchKeyEvent(ev: KeyEvent?): Boolean {
129         fail("Unexpected event " + ev)
130         return true
131     }
132 
dispatchTrackballEventnull133     override fun dispatchTrackballEvent(ev: MotionEvent?): Boolean {
134         fail("Unexpected event " + ev)
135         return true
136     }
137 
getLeftWindowInputEventnull138     fun getLeftWindowInputEvent(): InputEvent? {
139         return leftWindowEvents.poll(5, TimeUnit.SECONDS)
140     }
141 
getRightWindowInputEventnull142     fun getRightWindowInputEvent(): InputEvent? {
143         return rightWindowEvents.poll(5, TimeUnit.SECONDS)
144     }
145 
assertNoEventsnull146     fun assertNoEvents() {
147         assertNoEvents(leftWindowEvents)
148         assertNoEvents(rightWindowEvents)
149     }
150 }
151