1 package com.android.systemui.statusbar.gesture
2 
3 import android.testing.AndroidTestingRunner
4 import android.testing.TestableLooper
5 import android.view.InputEvent
6 import android.view.MotionEvent
7 import androidx.test.filters.SmallTest
8 import com.android.systemui.SysuiTestCase
9 import com.android.systemui.settings.FakeDisplayTracker
10 import com.google.common.truth.Truth.assertThat
11 import org.junit.Before
12 import org.junit.Test
13 import org.junit.runner.RunWith
14 
15 @SmallTest
16 @RunWith(AndroidTestingRunner::class)
17 @TestableLooper.RunWithLooper
18 class GenericGestureDetectorTest : SysuiTestCase() {
19 
20     private lateinit var gestureDetector: TestGestureDetector
21     private lateinit var displayTracker: FakeDisplayTracker
22 
23     @Before
24     fun setUp() {
25         displayTracker = FakeDisplayTracker(mContext)
26         gestureDetector = TestGestureDetector()
27     }
28 
29     @Test
30     fun noCallbacksRegistered_notGestureListening() {
31         assertThat(gestureDetector.isGestureListening).isFalse()
32     }
33 
34     @Test
35     fun callbackRegistered_isGestureListening() {
36         gestureDetector.addOnGestureDetectedCallback("tag"){}
37 
38         assertThat(gestureDetector.isGestureListening).isTrue()
39     }
40 
41     @Test
42     fun multipleCallbacksRegistered_isGestureListening() {
43         gestureDetector.addOnGestureDetectedCallback("tag"){}
44         gestureDetector.addOnGestureDetectedCallback("tag2"){}
45 
46         assertThat(gestureDetector.isGestureListening).isTrue()
47     }
48 
49     @Test
50     fun allCallbacksUnregistered_notGestureListening() {
51         gestureDetector.addOnGestureDetectedCallback("tag"){}
52         gestureDetector.addOnGestureDetectedCallback("tag2"){}
53 
54         gestureDetector.removeOnGestureDetectedCallback("tag")
55         gestureDetector.removeOnGestureDetectedCallback("tag2")
56 
57         assertThat(gestureDetector.isGestureListening).isFalse()
58     }
59 
60     @Test
61     fun someButNotAllCallbacksUnregistered_isGestureListening() {
62         gestureDetector.addOnGestureDetectedCallback("tag"){}
63         gestureDetector.addOnGestureDetectedCallback("tag2"){}
64 
65         gestureDetector.removeOnGestureDetectedCallback("tag2")
66 
67         assertThat(gestureDetector.isGestureListening).isTrue()
68     }
69 
70     @Test
71     fun onInputEvent_meetsGestureCriteria_allCallbacksNotified() {
72         var callbackNotified = false
73         gestureDetector.addOnGestureDetectedCallback("tag"){
74             callbackNotified = true
75         }
76 
77         gestureDetector.onInputEvent(
78             MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, CORRECT_X, 0f, 0)
79         )
80 
81         assertThat(callbackNotified).isTrue()
82     }
83 
84     @Test
85     fun onInputEvent_doesNotMeetGestureCriteria_callbackNotNotified() {
86         var callbackNotified = false
87         gestureDetector.addOnGestureDetectedCallback("tag"){
88             callbackNotified = true
89         }
90 
91         gestureDetector.onInputEvent(
92             MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, CORRECT_X - 5, 0f, 0)
93         )
94 
95         assertThat(callbackNotified).isFalse()
96     }
97 
98     @Test
99     fun callbackUnregisteredThenGestureDetected_oldCallbackNotNotified() {
100         var oldCallbackNotified = false
101         gestureDetector.addOnGestureDetectedCallback("tag"){
102             oldCallbackNotified = true
103         }
104         gestureDetector.addOnGestureDetectedCallback("tag2"){}
105 
106         gestureDetector.removeOnGestureDetectedCallback("tag")
107         gestureDetector.onInputEvent(
108             MotionEvent.obtain(
109                 0,
110                 0,
111                 MotionEvent.ACTION_DOWN,
112                 CORRECT_X,
113                 0f,
114                 0
115             )
116         )
117 
118         assertThat(oldCallbackNotified).isFalse()
119     }
120 
121     inner class TestGestureDetector : GenericGestureDetector(
122             "fakeTag",
123             displayTracker.defaultDisplayId
124     ) {
125         var isGestureListening = false
126 
127         override fun onInputEvent(ev: InputEvent) {
128             if (ev is MotionEvent && ev.x == CORRECT_X) {
129                 onGestureDetected(ev)
130             }
131         }
132 
133         override fun startGestureListening() {
134             super.startGestureListening()
135             isGestureListening = true
136         }
137 
138         override fun stopGestureListening() {
139             super.stopGestureListening()
140             isGestureListening = false
141         }
142     }
143 }
144 
145 private const val CORRECT_X = 1234f
146