1 /*
2  * 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.decor
18 
19 import android.graphics.Color
20 import android.testing.AndroidTestingRunner
21 import android.testing.TestableLooper.RunWithLooper
22 import android.view.DisplayCutout
23 import android.view.Surface
24 import android.view.View
25 import androidx.test.filters.SmallTest
26 import com.android.systemui.R
27 import com.android.systemui.SysuiTestCase
28 import org.junit.Assert
29 import org.junit.Before
30 import org.junit.Test
31 import org.junit.runner.RunWith
32 import org.mockito.Mockito.never
33 import org.mockito.Mockito.spy
34 import org.mockito.Mockito.times
35 import org.mockito.Mockito.verify
36 
37 @RunWith(AndroidTestingRunner::class)
38 @RunWithLooper(setAsMainLooper = true)
39 @SmallTest
40 class OverlayWindowTest : SysuiTestCase() {
41 
42     companion object {
43         private val TEST_DECOR_VIEW_ID_1 = R.id.privacy_dot_top_left_container
44         private val TEST_DECOR_VIEW_ID_2 = R.id.privacy_dot_bottom_left_container
45         private val TEST_DECOR_VIEW_ID_3 = R.id.privacy_dot_bottom_right_container
46     }
47 
48     private lateinit var overlay: OverlayWindow
49     private lateinit var decorProvider1: DecorProvider
50     private lateinit var decorProvider2: DecorProvider
51     private lateinit var decorProvider3: DecorProvider
52 
53     @Before
54     fun setUp() {
55         decorProvider1 = spy(
56             PrivacyDotCornerDecorProviderImpl(
57                 viewId = TEST_DECOR_VIEW_ID_1,
58                 alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
59                 alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
60                 layoutId = R.layout.privacy_dot_top_left
61             )
62         )
63         decorProvider2 = spy(
64             PrivacyDotCornerDecorProviderImpl(
65                 viewId = TEST_DECOR_VIEW_ID_2,
66                 alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
67                 alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
68                 layoutId = R.layout.privacy_dot_bottom_left
69             )
70         )
71         decorProvider3 = spy(
72             PrivacyDotCornerDecorProviderImpl(
73                 viewId = TEST_DECOR_VIEW_ID_3,
74                 alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
75                 alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
76                 layoutId = R.layout.privacy_dot_bottom_right
77             )
78         )
79         overlay = OverlayWindow(mContext)
80     }
81 
82     @Test
83     fun testAddProvider() {
84         @Surface.Rotation val rotation = Surface.ROTATION_270
85         overlay.addDecorProvider(decorProvider1, rotation, Color.BLACK)
86         overlay.addDecorProvider(decorProvider2, rotation, Color.YELLOW)
87 
88         verify(decorProvider1, times(1)).inflateView(
89                 mContext, overlay.rootView, rotation, Color.BLACK
90         )
91         verify(decorProvider2, times(1)).inflateView(
92                 mContext, overlay.rootView, rotation, Color.YELLOW
93         )
94 
95         val view1FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
96         Assert.assertNotNull(view1FoundFromRootView)
97         Assert.assertEquals(view1FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_1))
98         val view2FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_2)
99         Assert.assertNotNull(view2FoundFromRootView)
100         Assert.assertEquals(view2FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_2))
101     }
102 
103     @Test
104     fun testRemoveView() {
105         overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
106         overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
107         overlay.removeView(TEST_DECOR_VIEW_ID_1)
108 
109         val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
110         Assert.assertNull(viewFoundFromRootView)
111         Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
112     }
113 
114     @Test
115     fun testOnReloadResAndMeasureWithoutIds() {
116         overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
117         overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
118 
119         overlay.onReloadResAndMeasure(
120             reloadToken = 1,
121             rotation = Surface.ROTATION_90,
122             tintColor = Color.BLACK,
123             displayUniqueId = null
124         )
125         verify(decorProvider1, times(1)).onReloadResAndMeasure(
126                 overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, Color.BLACK, null
127         )
128         verify(decorProvider2, times(1)).onReloadResAndMeasure(
129                 overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, Color.BLACK, null
130         )
131     }
132 
133     @Test
134     fun testOnReloadResAndMeasureWithIds() {
135         overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
136         overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
137 
138         overlay.onReloadResAndMeasure(
139             filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
140             reloadToken = 1,
141             rotation = Surface.ROTATION_90,
142             tintColor = Color.BLACK,
143             displayUniqueId = null
144         )
145         verify(decorProvider1, never()).onReloadResAndMeasure(
146                 overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, Color.BLACK, null
147         )
148         verify(decorProvider2, times(1)).onReloadResAndMeasure(
149                 overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, Color.BLACK, null
150         )
151     }
152 
153     @Test
154     fun testRemoveRedundantViewsWithNullParameter() {
155         overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
156         overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
157 
158         overlay.removeRedundantViews(null)
159 
160         Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
161         Assert.assertNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1))
162         Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_2))
163         Assert.assertNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_2))
164     }
165 
166     @Test
167     fun testRemoveRedundantViewsWith2Providers() {
168         overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270, Color.BLACK)
169         overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270, Color.BLACK)
170 
171         overlay.removeRedundantViews(
172             IntArray(2).apply {
173                 this[0] = TEST_DECOR_VIEW_ID_3
174                 this[1] = TEST_DECOR_VIEW_ID_1
175             }
176         )
177 
178         Assert.assertNotNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
179         Assert.assertNotNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1))
180         Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_2))
181         Assert.assertNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_2))
182     }
183 
184     @Test
185     fun testHasSameProviders() {
186         Assert.assertTrue(overlay.hasSameProviders(emptyList()))
187         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1)))
188         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
189         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
190 
191         overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0, Color.BLACK)
192         Assert.assertFalse(overlay.hasSameProviders(emptyList()))
193         Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider1)))
194         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
195         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
196 
197         overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0, Color.BLACK)
198         Assert.assertFalse(overlay.hasSameProviders(emptyList()))
199         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1)))
200         Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
201         Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
202     }
203 }
204