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