1 /*
<lambda>null2 * Copyright (C) 2022 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.systemui.statusbar.phone
18
19 import android.graphics.Rect
20 import android.testing.AndroidTestingRunner
21 import android.testing.TestableLooper.RunWithLooper
22 import android.view.View
23 import android.widget.FrameLayout
24 import androidx.test.filters.SmallTest
25 import com.android.systemui.SysuiTestCase
26 import com.android.systemui.statusbar.phone.StatusBarBoundsProvider.BoundsChangeListener
27 import com.google.common.truth.Truth.assertThat
28 import org.junit.Before
29 import org.junit.Test
30 import org.junit.runner.RunWith
31 import org.mockito.Mock
32 import org.mockito.Mockito.any
33 import org.mockito.Mockito.doAnswer
34 import org.mockito.Mockito.never
35 import org.mockito.Mockito.spy
36 import org.mockito.Mockito.verify
37 import org.mockito.MockitoAnnotations
38
39 @RunWith(AndroidTestingRunner::class)
40 @RunWithLooper(setAsMainLooper = true)
41 @SmallTest
42 class StatusBarBoundsProviderTest : SysuiTestCase() {
43
44 companion object {
45 private val START_SIDE_BOUNDS = Rect(50, 100, 150, 200)
46 private val END_SIDE_BOUNDS = Rect(250, 300, 350, 400)
47 }
48
49 @Mock private lateinit var boundsChangeListener: BoundsChangeListener
50
51 private lateinit var boundsProvider: StatusBarBoundsProvider
52
53 private lateinit var startSideContent: View
54 private lateinit var endSideContent: View
55
56 @Before
57 fun setUp() {
58 MockitoAnnotations.initMocks(this)
59
60 startSideContent = spy(FrameLayout(context)).apply { setBoundsOnScreen(START_SIDE_BOUNDS) }
61 endSideContent = spy(FrameLayout(context)).apply { setBoundsOnScreen(END_SIDE_BOUNDS) }
62
63 boundsProvider =
64 StatusBarBoundsProvider(setOf(boundsChangeListener), startSideContent, endSideContent)
65 }
66
67 @Test
68 fun visibleStartSideBounds_returnsBoundsFromStartSideContentView() {
69 assertThat(boundsProvider.visibleStartSideBounds).isEqualTo(START_SIDE_BOUNDS)
70 }
71
72 @Test
73 fun visibleEndSideBounds_returnsBoundsFromEndSideContentView() {
74 assertThat(boundsProvider.visibleEndSideBounds).isEqualTo(END_SIDE_BOUNDS)
75 }
76
77 @Test
78 fun startBoundsChange_afterStart_notifiesListener() {
79 boundsProvider.start()
80 val newBounds = Rect(START_SIDE_BOUNDS).apply { left += 1 }
81
82 startSideContent.setBoundsOnScreen(newBounds)
83
84 verify(boundsChangeListener).onStatusBarBoundsChanged()
85 }
86
87 @Test
88 fun startBoundsChange_beforeStart_doesNotNotifyListener() {
89 val newBounds = Rect(START_SIDE_BOUNDS).apply { left += 1 }
90
91 startSideContent.setBoundsOnScreen(newBounds)
92
93 verify(boundsChangeListener, never()).onStatusBarBoundsChanged()
94 }
95
96 @Test
97 fun startBoundsChange_afterStop_doesNotNotifyListener() {
98 boundsProvider.start()
99 boundsProvider.stop()
100 val newBounds = Rect(START_SIDE_BOUNDS).apply { left += 1 }
101
102 startSideContent.setBoundsOnScreen(newBounds)
103
104 verify(boundsChangeListener, never()).onStatusBarBoundsChanged()
105 }
106
107 @Test
108 fun startLayoutChange_afterStart_boundsOnScreenSame_doesNotNotifyListener() {
109 boundsProvider.start()
110 val newBounds = Rect(START_SIDE_BOUNDS).apply { left += 1 }
111
112 startSideContent.layout(newBounds)
113
114 verify(boundsChangeListener, never()).onStatusBarBoundsChanged()
115 }
116
117 @Test
118 fun endBoundsChange_afterStart_notifiesListener() {
119 boundsProvider.start()
120 val newBounds = Rect(START_SIDE_BOUNDS).apply { right += 1 }
121
122 endSideContent.setBoundsOnScreen(newBounds)
123
124 verify(boundsChangeListener).onStatusBarBoundsChanged()
125 }
126
127 @Test
128 fun endBoundsChange_beforeStart_doesNotNotifyListener() {
129 val newBounds = Rect(START_SIDE_BOUNDS).apply { right += 1 }
130
131 endSideContent.setBoundsOnScreen(newBounds)
132
133 verify(boundsChangeListener, never()).onStatusBarBoundsChanged()
134 }
135
136 @Test
137 fun endBoundsChange_afterStop_doesNotNotifyListener() {
138 boundsProvider.start()
139 boundsProvider.stop()
140 val newBounds = Rect(START_SIDE_BOUNDS).apply { right += 1 }
141
142 endSideContent.setBoundsOnScreen(newBounds)
143
144 verify(boundsChangeListener, never()).onStatusBarBoundsChanged()
145 }
146
147 @Test
148 fun endLayoutChange_afterStart_boundsOnScreenSame_doesNotNotifyListener() {
149 boundsProvider.start()
150 val newBounds = Rect(START_SIDE_BOUNDS).apply { right += 1 }
151
152 endSideContent.layout(newBounds)
153
154 verify(boundsChangeListener, never()).onStatusBarBoundsChanged()
155 }
156 }
157
Viewnull158 private fun View.setBoundsOnScreen(bounds: Rect) {
159 doAnswer { invocation ->
160 val boundsOutput = invocation.arguments[0] as Rect
161 boundsOutput.set(bounds)
162 return@doAnswer Unit
163 }
164 .`when`(this)
165 .getBoundsOnScreen(any())
166 layout(bounds.left, bounds.top, bounds.right, bounds.bottom)
167 }
168
layoutnull169 private fun View.layout(rect: Rect) {
170 layout(rect.left, rect.top, rect.right, rect.bottom)
171 }
172