• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2025 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.wm.shell.shared.bubbles
18 
19 import android.content.Context
20 import android.graphics.Insets
21 import android.graphics.Rect
22 import androidx.test.core.app.ApplicationProvider.getApplicationContext
23 import androidx.test.ext.junit.runners.AndroidJUnit4
24 import androidx.test.filters.SmallTest
25 import com.android.wm.shell.shared.bubbles.DragZoneFactory.DesktopWindowModeChecker
26 import com.android.wm.shell.shared.bubbles.DragZoneFactory.SplitScreenModeChecker
27 import com.android.wm.shell.shared.bubbles.DragZoneFactory.SplitScreenModeChecker.SplitScreenMode
28 import com.google.common.truth.Truth.assertThat
29 import org.junit.Test
30 import org.junit.runner.RunWith
31 
32 private typealias DragZoneVerifier = (dragZone: DragZone) -> Unit
33 
34 @SmallTest
35 @RunWith(AndroidJUnit4::class)
36 /** Unit tests for [DragZoneFactory]. */
37 class DragZoneFactoryTest {
38 
39     private val context = getApplicationContext<Context>()
40     private lateinit var dragZoneFactory: DragZoneFactory
41     private val tabletPortrait =
42         DeviceConfig(
43             windowBounds = Rect(0, 0, 1000, 2000),
44             isLargeScreen = true,
45             isSmallTablet = false,
46             isLandscape = false,
47             isRtl = false,
48             insets = Insets.of(0, 0, 0, 0)
49         )
50     private val tabletLandscape =
51         tabletPortrait.copy(windowBounds = Rect(0, 0, 2000, 1000), isLandscape = true)
52     private val foldablePortrait =
53         tabletPortrait.copy(windowBounds = Rect(0, 0, 800, 900), isSmallTablet = true)
54     private val foldableLandscape =
55         foldablePortrait.copy(windowBounds = Rect(0, 0, 900, 800), isLandscape = true)
56     private var splitScreenMode = SplitScreenMode.NONE
57     private val splitScreenModeChecker = SplitScreenModeChecker { splitScreenMode }
58     private var isDesktopWindowModeSupported = true
59     private val desktopWindowModeChecker = DesktopWindowModeChecker { isDesktopWindowModeSupported }
60 
61     @Test
62     fun dragZonesForBubbleBar_tablet() {
63         dragZoneFactory =
64             DragZoneFactory(
65                 context,
66                 tabletPortrait,
67                 splitScreenModeChecker,
68                 desktopWindowModeChecker
69             )
70         val dragZones =
71             dragZoneFactory.createSortedDragZones(DraggedObject.BubbleBar(BubbleBarLocation.LEFT))
72         val expectedZones: List<DragZoneVerifier> =
73             listOf(
74                 verifyInstance<DragZone.Dismiss>(),
75                 verifyInstance<DragZone.Bubble.Left>(),
76                 verifyInstance<DragZone.Bubble.Right>(),
77             )
78         assertThat(dragZones).hasSize(expectedZones.size)
79         dragZones.zip(expectedZones).forEach { (zone, instanceVerifier) -> instanceVerifier(zone) }
80     }
81 
82     @Test
83     fun dragZonesForBubble_tablet_portrait() {
84         dragZoneFactory =
85             DragZoneFactory(
86                 context,
87                 tabletPortrait,
88                 splitScreenModeChecker,
89                 desktopWindowModeChecker
90             )
91         val dragZones =
92             dragZoneFactory.createSortedDragZones(DraggedObject.Bubble(BubbleBarLocation.LEFT))
93         val expectedZones: List<DragZoneVerifier> =
94             listOf(
95                 verifyInstance<DragZone.Dismiss>(),
96                 verifyInstance<DragZone.Bubble.Left>(),
97                 verifyInstance<DragZone.Bubble.Right>(),
98                 verifyInstance<DragZone.FullScreen>(),
99                 verifyInstance<DragZone.DesktopWindow>(),
100                 verifyInstance<DragZone.Split.Top>(),
101                 verifyInstance<DragZone.Split.Bottom>(),
102             )
103         assertThat(dragZones).hasSize(expectedZones.size)
104         dragZones.zip(expectedZones).forEach { (zone, instanceVerifier) -> instanceVerifier(zone) }
105     }
106 
107     @Test
108     fun dragZonesForBubble_tablet_landscape() {
109         dragZoneFactory =
110             DragZoneFactory(
111                 context,
112                 tabletLandscape,
113                 splitScreenModeChecker,
114                 desktopWindowModeChecker
115             )
116         val dragZones =
117             dragZoneFactory.createSortedDragZones(DraggedObject.Bubble(BubbleBarLocation.LEFT))
118         val expectedZones: List<DragZoneVerifier> =
119             listOf(
120                 verifyInstance<DragZone.Dismiss>(),
121                 verifyInstance<DragZone.Bubble.Left>(),
122                 verifyInstance<DragZone.Bubble.Right>(),
123                 verifyInstance<DragZone.FullScreen>(),
124                 verifyInstance<DragZone.DesktopWindow>(),
125                 verifyInstance<DragZone.Split.Left>(),
126                 verifyInstance<DragZone.Split.Right>(),
127             )
128         assertThat(dragZones).hasSize(expectedZones.size)
129         dragZones.zip(expectedZones).forEach { (zone, instanceVerifier) -> instanceVerifier(zone) }
130     }
131 
132     @Test
133     fun dragZonesForBubble_foldable_portrait() {
134         dragZoneFactory =
135             DragZoneFactory(
136                 context,
137                 foldablePortrait,
138                 splitScreenModeChecker,
139                 desktopWindowModeChecker
140             )
141         val dragZones =
142             dragZoneFactory.createSortedDragZones(DraggedObject.Bubble(BubbleBarLocation.LEFT))
143         val expectedZones: List<DragZoneVerifier> =
144             listOf(
145                 verifyInstance<DragZone.Dismiss>(),
146                 verifyInstance<DragZone.Bubble.Left>(),
147                 verifyInstance<DragZone.Bubble.Right>(),
148                 verifyInstance<DragZone.FullScreen>(),
149                 verifyInstance<DragZone.Split.Left>(),
150                 verifyInstance<DragZone.Split.Right>(),
151             )
152         assertThat(dragZones).hasSize(expectedZones.size)
153         dragZones.zip(expectedZones).forEach { (zone, instanceVerifier) -> instanceVerifier(zone) }
154     }
155 
156     @Test
157     fun dragZonesForBubble_foldable_landscape() {
158         dragZoneFactory =
159             DragZoneFactory(
160                 context,
161                 foldableLandscape,
162                 splitScreenModeChecker,
163                 desktopWindowModeChecker
164             )
165         val dragZones =
166             dragZoneFactory.createSortedDragZones(DraggedObject.Bubble(BubbleBarLocation.LEFT))
167         val expectedZones: List<DragZoneVerifier> =
168             listOf(
169                 verifyInstance<DragZone.Dismiss>(),
170                 verifyInstance<DragZone.Bubble.Left>(),
171                 verifyInstance<DragZone.Bubble.Right>(),
172                 verifyInstance<DragZone.FullScreen>(),
173                 verifyInstance<DragZone.Split.Top>(),
174                 verifyInstance<DragZone.Split.Bottom>(),
175             )
176         assertThat(dragZones).hasSize(expectedZones.size)
177         dragZones.zip(expectedZones).forEach { (zone, instanceVerifier) -> instanceVerifier(zone) }
178     }
179 
180     @Test
181     fun dragZonesForExpandedView_tablet_portrait() {
182         dragZoneFactory =
183             DragZoneFactory(
184                 context,
185                 tabletPortrait,
186                 splitScreenModeChecker,
187                 desktopWindowModeChecker
188             )
189         val dragZones =
190             dragZoneFactory.createSortedDragZones(
191                 DraggedObject.ExpandedView(BubbleBarLocation.LEFT)
192             )
193         val expectedZones: List<DragZoneVerifier> =
194             listOf(
195                 verifyInstance<DragZone.Dismiss>(),
196                 verifyInstance<DragZone.FullScreen>(),
197                 verifyInstance<DragZone.DesktopWindow>(),
198                 verifyInstance<DragZone.Split.Top>(),
199                 verifyInstance<DragZone.Split.Bottom>(),
200                 verifyInstance<DragZone.Bubble.Left>(),
201                 verifyInstance<DragZone.Bubble.Right>(),
202             )
203         assertThat(dragZones).hasSize(expectedZones.size)
204         dragZones.zip(expectedZones).forEach { (zone, instanceVerifier) -> instanceVerifier(zone) }
205     }
206 
207     @Test
208     fun dragZonesForExpandedView_tablet_landscape() {
209         dragZoneFactory =
210             DragZoneFactory(
211                 context,
212                 tabletLandscape,
213                 splitScreenModeChecker,
214                 desktopWindowModeChecker
215             )
216         val dragZones =
217             dragZoneFactory.createSortedDragZones(
218                 DraggedObject.ExpandedView(BubbleBarLocation.LEFT)
219             )
220         val expectedZones: List<DragZoneVerifier> =
221             listOf(
222                 verifyInstance<DragZone.Dismiss>(),
223                 verifyInstance<DragZone.FullScreen>(),
224                 verifyInstance<DragZone.DesktopWindow>(),
225                 verifyInstance<DragZone.Split.Left>(),
226                 verifyInstance<DragZone.Split.Right>(),
227                 verifyInstance<DragZone.Bubble.Left>(),
228                 verifyInstance<DragZone.Bubble.Right>(),
229             )
230         assertThat(dragZones).hasSize(expectedZones.size)
231         dragZones.zip(expectedZones).forEach { (zone, instanceVerifier) -> instanceVerifier(zone) }
232     }
233 
234     @Test
235     fun dragZonesForExpandedView_foldable_portrait() {
236         dragZoneFactory =
237             DragZoneFactory(
238                 context,
239                 foldablePortrait,
240                 splitScreenModeChecker,
241                 desktopWindowModeChecker
242             )
243         val dragZones =
244             dragZoneFactory.createSortedDragZones(
245                 DraggedObject.ExpandedView(BubbleBarLocation.LEFT)
246             )
247         val expectedZones: List<DragZoneVerifier> =
248             listOf(
249                 verifyInstance<DragZone.Dismiss>(),
250                 verifyInstance<DragZone.FullScreen>(),
251                 verifyInstance<DragZone.Split.Left>(),
252                 verifyInstance<DragZone.Split.Right>(),
253                 verifyInstance<DragZone.Bubble.Left>(),
254                 verifyInstance<DragZone.Bubble.Right>(),
255             )
256         assertThat(dragZones).hasSize(expectedZones.size)
257         dragZones.zip(expectedZones).forEach { (zone, instanceVerifier) -> instanceVerifier(zone) }
258     }
259 
260     @Test
261     fun dragZonesForExpandedView_foldable_landscape() {
262         dragZoneFactory =
263             DragZoneFactory(
264                 context,
265                 foldableLandscape,
266                 splitScreenModeChecker,
267                 desktopWindowModeChecker
268             )
269         val dragZones =
270             dragZoneFactory.createSortedDragZones(
271                 DraggedObject.ExpandedView(BubbleBarLocation.LEFT)
272             )
273         val expectedZones: List<DragZoneVerifier> =
274             listOf(
275                 verifyInstance<DragZone.Dismiss>(),
276                 verifyInstance<DragZone.FullScreen>(),
277                 verifyInstance<DragZone.Split.Top>(),
278                 verifyInstance<DragZone.Split.Bottom>(),
279                 verifyInstance<DragZone.Bubble.Left>(),
280                 verifyInstance<DragZone.Bubble.Right>(),
281             )
282         assertThat(dragZones).hasSize(expectedZones.size)
283         dragZones.zip(expectedZones).forEach { (zone, instanceVerifier) -> instanceVerifier(zone) }
284     }
285 
286     @Test
287     fun dragZonesForBubble_desktopModeDisabled() {
288         isDesktopWindowModeSupported = false
289         dragZoneFactory =
290             DragZoneFactory(
291                 context,
292                 foldableLandscape,
293                 splitScreenModeChecker,
294                 desktopWindowModeChecker
295             )
296         val dragZones =
297             dragZoneFactory.createSortedDragZones(DraggedObject.Bubble(BubbleBarLocation.LEFT))
298         assertThat(dragZones.filterIsInstance<DragZone.DesktopWindow>()).isEmpty()
299     }
300 
301     @Test
302     fun dragZonesForExpandedView_desktopModeDisabled() {
303         isDesktopWindowModeSupported = false
304         dragZoneFactory =
305             DragZoneFactory(
306                 context,
307                 foldableLandscape,
308                 splitScreenModeChecker,
309                 desktopWindowModeChecker
310             )
311         val dragZones =
312             dragZoneFactory.createSortedDragZones(
313                 DraggedObject.ExpandedView(BubbleBarLocation.LEFT)
314             )
315         assertThat(dragZones.filterIsInstance<DragZone.DesktopWindow>()).isEmpty()
316     }
317 
318     @Test
319     fun dragZonesForBubble_splitScreenModeUnsupported() {
320         splitScreenMode = SplitScreenMode.UNSUPPORTED
321         dragZoneFactory =
322             DragZoneFactory(
323                 context,
324                 foldableLandscape,
325                 splitScreenModeChecker,
326                 desktopWindowModeChecker
327             )
328         val dragZones =
329             dragZoneFactory.createSortedDragZones(DraggedObject.Bubble(BubbleBarLocation.LEFT))
330         assertThat(dragZones.filterIsInstance<DragZone.Split>()).isEmpty()
331     }
332 
333     @Test
334     fun dragZonesForExpandedView_splitScreenModeUnsupported() {
335         splitScreenMode = SplitScreenMode.UNSUPPORTED
336         dragZoneFactory =
337             DragZoneFactory(
338                 context,
339                 foldableLandscape,
340                 splitScreenModeChecker,
341                 desktopWindowModeChecker
342             )
343         val dragZones =
344             dragZoneFactory.createSortedDragZones(
345                 DraggedObject.ExpandedView(BubbleBarLocation.LEFT)
346             )
347         assertThat(dragZones.filterIsInstance<DragZone.Split>()).isEmpty()
348     }
349 
350     private inline fun <reified T> verifyInstance(): DragZoneVerifier = { dragZone ->
351         assertThat(dragZone).isInstanceOf(T::class.java)
352     }
353 }
354