Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxControllerRobotTest.kt 0 → 100644 +142 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.letterbox import android.content.Context import android.graphics.Rect import android.view.SurfaceControl import com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn import com.android.wm.shell.compatui.letterbox.LetterboxMatchers.asAnyMode import org.mockito.kotlin.any import org.mockito.kotlin.clearInvocations import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.times import org.mockito.kotlin.verify /** * Robot to test [LetterboxController] implementations. */ open class LetterboxControllerRobotTest( ctx: Context, controllerBuilder: (LetterboxSurfaceBuilder) -> LetterboxController ) { companion object { @JvmStatic private val DISPLAY_ID = 1 @JvmStatic private val TASK_ID = 20 } private val letterboxConfiguration: LetterboxConfiguration private val surfaceBuilder: LetterboxSurfaceBuilder private val letterboxController: LetterboxController private val transaction: SurfaceControl.Transaction private val parentLeash: SurfaceControl init { letterboxConfiguration = LetterboxConfiguration(ctx) surfaceBuilder = LetterboxSurfaceBuilder(letterboxConfiguration) letterboxController = controllerBuilder(surfaceBuilder) transaction = getTransactionMock() parentLeash = mock<SurfaceControl>() spyOn(surfaceBuilder) } fun sendCreateSurfaceRequest( displayId: Int = DISPLAY_ID, taskId: Int = TASK_ID ) = letterboxController.createLetterboxSurface( key = LetterboxKey(displayId, taskId), transaction = transaction, parentLeash = parentLeash ) fun sendDestroySurfaceRequest( displayId: Int = DISPLAY_ID, taskId: Int = TASK_ID ) = letterboxController.destroyLetterboxSurface( key = LetterboxKey(displayId, taskId), transaction = transaction ) fun sendUpdateSurfaceVisibilityRequest( displayId: Int = DISPLAY_ID, taskId: Int = TASK_ID, visible: Boolean ) = letterboxController.updateLetterboxSurfaceVisibility( key = LetterboxKey(displayId, taskId), transaction = transaction, visible = visible ) fun sendUpdateSurfaceBoundsRequest( displayId: Int = DISPLAY_ID, taskId: Int = TASK_ID, taskBounds: Rect, activityBounds: Rect ) = letterboxController.updateLetterboxSurfaceBounds( key = LetterboxKey(displayId, taskId), transaction = transaction, taskBounds = taskBounds, activityBounds = activityBounds ) fun checkSurfaceBuilderInvoked(times: Int = 1, name: String = "", callSite: String = "") { verify(surfaceBuilder, times(times)).createSurface( eq(transaction), eq(parentLeash), name.asAnyMode(), callSite.asAnyMode(), any() ) } fun checkTransactionRemovedInvoked(times: Int = 1) { verify(transaction, times(times)).remove(any()) } fun checkVisibilityUpdated(times: Int = 1, expectedVisibility: Boolean) { verify(transaction, times(times)).setVisibility(any(), eq(expectedVisibility)) } fun checkSurfacePositionUpdated( times: Int = 1, expectedX: Float = -1f, expectedY: Float = -1f ) { verify(transaction, times(times)).setPosition( any(), expectedX.asAnyMode(), expectedY.asAnyMode() ) } fun checkSurfaceSizeUpdated(times: Int = 1, expectedWidth: Int = -1, expectedHeight: Int = -1) { verify(transaction, times(times)).setWindowCrop( any(), expectedWidth.asAnyMode(), expectedHeight.asAnyMode() ) } fun resetTransitionTest() { clearInvocations(transaction) } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilderTest.kt +1 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import org.junit.runner.RunWith import org.mockito.ArgumentMatchers import org.mockito.Mockito.verify import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.times Loading Loading @@ -85,9 +84,7 @@ class LetterboxSurfaceBuilderTest : ShellTestCase() { init { letterboxConfiguration = LetterboxConfiguration(ctx) letterboxSurfaceBuilder = LetterboxSurfaceBuilder(letterboxConfiguration) tx = org.mockito.kotlin.mock<SurfaceControl.Transaction>() doReturn(tx).`when`(tx).setLayer(anyOrNull(), anyOrNull()) doReturn(tx).`when`(tx).setColorSpaceAgnostic(anyOrNull(), anyOrNull()) tx = getTransactionMock() parentLeash = org.mockito.kotlin.mock<SurfaceControl>() surfaceBuilder = SurfaceControl.Builder() spyOn(surfaceBuilder) Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxTestUtils.kt +27 −0 Original line number Diff line number Diff line Loading @@ -16,9 +16,36 @@ package com.android.wm.shell.compatui.letterbox import android.view.SurfaceControl import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.times import org.mockito.verification.VerificationMode /** * @return A [SurfaceControl.Transaction] mock supporting chaining for some operations. Please * add other operations if needed. */ fun getTransactionMock(): SurfaceControl.Transaction = mock<SurfaceControl.Transaction>().apply { doReturn(this).`when`(this).setLayer(anyOrNull(), anyOrNull()) doReturn(this).`when`(this).setColorSpaceAgnostic(anyOrNull(), anyOrNull()) doReturn(this).`when`(this).setPosition(anyOrNull(), any(), any()) doReturn(this).`when`(this).setWindowCrop(anyOrNull(), any(), any()) } // Utility to make verification mode depending on a [Boolean]. fun Boolean.asMode(): VerificationMode = if (this) times(1) else never() // Utility matchers to use for the main types as Mockito [VerificationMode]. object LetterboxMatchers { fun Int.asAnyMode() = asAnyMode { this < 0 } fun Float.asAnyMode() = asAnyMode { this < 0f } fun String.asAnyMode() = asAnyMode { this.isEmpty() } } private inline fun <reified T : Any> T.asAnyMode(condition: () -> Boolean) = (if (condition()) any() else eq(this)) libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/MultiSurfaceLetterboxControllerTest.kt 0 → 100644 +155 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.letterbox import android.graphics.Rect import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.wm.shell.ShellTestCase import java.util.function.Consumer import org.junit.Test import org.junit.runner.RunWith /** * Tests for [MultiSurfaceLetterboxController]. * * Build/Install/Run: * atest WMShellUnitTests:MultiSurfaceLetterboxControllerTest */ @RunWith(AndroidTestingRunner::class) @SmallTest class MultiSurfaceLetterboxControllerTest : ShellTestCase() { @Test fun `When creation is requested the surfaces are created if not present`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked(times = 4) } } @Test fun `When creation is requested multiple times the surfaces are created once`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked(times = 4) } } @Test fun `Different surfaces are created for every key`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest(displayId = 2) r.sendCreateSurfaceRequest(displayId = 2, taskId = 2) r.sendCreateSurfaceRequest(displayId = 2) r.sendCreateSurfaceRequest(displayId = 2, taskId = 2) r.checkSurfaceBuilderInvoked(times = 12) } } @Test fun `Created surface are removed once`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked(times = 4) r.sendDestroySurfaceRequest() r.sendDestroySurfaceRequest() r.sendDestroySurfaceRequest() r.checkTransactionRemovedInvoked(times = 4) } } @Test fun `Only existing surfaces receive visibility update`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendUpdateSurfaceVisibilityRequest(visible = true) r.sendUpdateSurfaceVisibilityRequest(visible = true, displayId = 20) r.checkVisibilityUpdated(times = 4, expectedVisibility = true) } } @Test fun `Only existing surfaces receive taskBounds update`() { runTestScenario { r -> r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 2000, 1000), activityBounds = Rect(500, 0, 1500, 1000) ) r.checkSurfacePositionUpdated(times = 0) r.checkSurfaceSizeUpdated(times = 0) r.sendCreateSurfaceRequest() // Pillarbox. r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 2000, 1000), activityBounds = Rect(500, 0, 1500, 1000) ) // The Left and Top surfaces. r.checkSurfacePositionUpdated(times = 2, expectedX = 0f, expectedY = 0f) // The Right surface. r.checkSurfacePositionUpdated(times = 1, expectedX = 1500f, expectedY = 0f) // The Bottom surface. r.checkSurfacePositionUpdated(times = 1, expectedX = 0f, expectedY = 1000f) // Left and Right surface. r.checkSurfaceSizeUpdated(times = 2, expectedWidth = 500, expectedHeight = 1000) // Top and Button. r.checkSurfaceSizeUpdated(times = 2, expectedWidth = 2000, expectedHeight = 0) r.resetTransitionTest() // Letterbox. r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 1000, 2000), activityBounds = Rect(0, 500, 1000, 1500) ) // Top and Left surfaces. r.checkSurfacePositionUpdated(times = 2, expectedX = 0f, expectedY = 0f) // Bottom surface. r.checkSurfacePositionUpdated(times = 1, expectedX = 0f, expectedY = 1500f) // Right surface. r.checkSurfacePositionUpdated(times = 1, expectedX = 1000f, expectedY = 0f) // Left and Right surfaces. r.checkSurfaceSizeUpdated(times = 2, expectedWidth = 0, expectedHeight = 2000) // Top and Button surfaces, r.checkSurfaceSizeUpdated(times = 2, expectedWidth = 1000, expectedHeight = 500) } } /** * Runs a test scenario providing a Robot. */ fun runTestScenario(consumer: Consumer<LetterboxControllerRobotTest>) { val robot = LetterboxControllerRobotTest(mContext, { sb -> MultiSurfaceLetterboxController(sb) }) consumer.accept(robot) } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/SingleSurfaceLetterboxControllerTest.kt 0 → 100644 +128 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.letterbox import android.graphics.Rect import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.wm.shell.ShellTestCase import java.util.function.Consumer import org.junit.Test import org.junit.runner.RunWith /** * Tests for [SingleSurfaceLetterboxController]. * * Build/Install/Run: * atest WMShellUnitTests:SingleSurfaceLetterboxControllerTest */ @RunWith(AndroidTestingRunner::class) @SmallTest class SingleSurfaceLetterboxControllerTest : ShellTestCase() { @Test fun `When creation is requested the surface is created if not present`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked() } } @Test fun `When creation is requested multiple times the surface is created once`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked(times = 1) } } @Test fun `A different surface is created for every key`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest(displayId = 2) r.sendCreateSurfaceRequest(displayId = 2, taskId = 2) r.sendCreateSurfaceRequest(displayId = 2) r.sendCreateSurfaceRequest(displayId = 2, taskId = 2) r.checkSurfaceBuilderInvoked(times = 3) } } @Test fun `Created surface is removed once`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked() r.sendDestroySurfaceRequest() r.sendDestroySurfaceRequest() r.sendDestroySurfaceRequest() r.checkTransactionRemovedInvoked() } } @Test fun `Only existing surfaces receive visibility update`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendUpdateSurfaceVisibilityRequest(visible = true) r.sendUpdateSurfaceVisibilityRequest(visible = true, displayId = 20) r.checkVisibilityUpdated(expectedVisibility = true) } } @Test fun `Only existing surfaces receive taskBounds update`() { runTestScenario { r -> r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 2000, 1000), activityBounds = Rect(500, 0, 1500, 1000) ) r.checkSurfacePositionUpdated(times = 0) r.checkSurfaceSizeUpdated(times = 0) r.resetTransitionTest() r.sendCreateSurfaceRequest() r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 2000, 1000), activityBounds = Rect(500, 0, 1500, 1000) ) r.checkSurfacePositionUpdated(times = 1, expectedX = 0f, expectedY = 0f) r.checkSurfaceSizeUpdated(times = 1, expectedWidth = 2000, expectedHeight = 1000) } } /** * Runs a test scenario providing a Robot. */ fun runTestScenario(consumer: Consumer<LetterboxControllerRobotTest>) { val robot = LetterboxControllerRobotTest(mContext, { sb -> SingleSurfaceLetterboxController(sb) }) consumer.accept(robot) } } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxControllerRobotTest.kt 0 → 100644 +142 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.letterbox import android.content.Context import android.graphics.Rect import android.view.SurfaceControl import com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn import com.android.wm.shell.compatui.letterbox.LetterboxMatchers.asAnyMode import org.mockito.kotlin.any import org.mockito.kotlin.clearInvocations import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.times import org.mockito.kotlin.verify /** * Robot to test [LetterboxController] implementations. */ open class LetterboxControllerRobotTest( ctx: Context, controllerBuilder: (LetterboxSurfaceBuilder) -> LetterboxController ) { companion object { @JvmStatic private val DISPLAY_ID = 1 @JvmStatic private val TASK_ID = 20 } private val letterboxConfiguration: LetterboxConfiguration private val surfaceBuilder: LetterboxSurfaceBuilder private val letterboxController: LetterboxController private val transaction: SurfaceControl.Transaction private val parentLeash: SurfaceControl init { letterboxConfiguration = LetterboxConfiguration(ctx) surfaceBuilder = LetterboxSurfaceBuilder(letterboxConfiguration) letterboxController = controllerBuilder(surfaceBuilder) transaction = getTransactionMock() parentLeash = mock<SurfaceControl>() spyOn(surfaceBuilder) } fun sendCreateSurfaceRequest( displayId: Int = DISPLAY_ID, taskId: Int = TASK_ID ) = letterboxController.createLetterboxSurface( key = LetterboxKey(displayId, taskId), transaction = transaction, parentLeash = parentLeash ) fun sendDestroySurfaceRequest( displayId: Int = DISPLAY_ID, taskId: Int = TASK_ID ) = letterboxController.destroyLetterboxSurface( key = LetterboxKey(displayId, taskId), transaction = transaction ) fun sendUpdateSurfaceVisibilityRequest( displayId: Int = DISPLAY_ID, taskId: Int = TASK_ID, visible: Boolean ) = letterboxController.updateLetterboxSurfaceVisibility( key = LetterboxKey(displayId, taskId), transaction = transaction, visible = visible ) fun sendUpdateSurfaceBoundsRequest( displayId: Int = DISPLAY_ID, taskId: Int = TASK_ID, taskBounds: Rect, activityBounds: Rect ) = letterboxController.updateLetterboxSurfaceBounds( key = LetterboxKey(displayId, taskId), transaction = transaction, taskBounds = taskBounds, activityBounds = activityBounds ) fun checkSurfaceBuilderInvoked(times: Int = 1, name: String = "", callSite: String = "") { verify(surfaceBuilder, times(times)).createSurface( eq(transaction), eq(parentLeash), name.asAnyMode(), callSite.asAnyMode(), any() ) } fun checkTransactionRemovedInvoked(times: Int = 1) { verify(transaction, times(times)).remove(any()) } fun checkVisibilityUpdated(times: Int = 1, expectedVisibility: Boolean) { verify(transaction, times(times)).setVisibility(any(), eq(expectedVisibility)) } fun checkSurfacePositionUpdated( times: Int = 1, expectedX: Float = -1f, expectedY: Float = -1f ) { verify(transaction, times(times)).setPosition( any(), expectedX.asAnyMode(), expectedY.asAnyMode() ) } fun checkSurfaceSizeUpdated(times: Int = 1, expectedWidth: Int = -1, expectedHeight: Int = -1) { verify(transaction, times(times)).setWindowCrop( any(), expectedWidth.asAnyMode(), expectedHeight.asAnyMode() ) } fun resetTransitionTest() { clearInvocations(transaction) } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilderTest.kt +1 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import org.junit.runner.RunWith import org.mockito.ArgumentMatchers import org.mockito.Mockito.verify import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.times Loading Loading @@ -85,9 +84,7 @@ class LetterboxSurfaceBuilderTest : ShellTestCase() { init { letterboxConfiguration = LetterboxConfiguration(ctx) letterboxSurfaceBuilder = LetterboxSurfaceBuilder(letterboxConfiguration) tx = org.mockito.kotlin.mock<SurfaceControl.Transaction>() doReturn(tx).`when`(tx).setLayer(anyOrNull(), anyOrNull()) doReturn(tx).`when`(tx).setColorSpaceAgnostic(anyOrNull(), anyOrNull()) tx = getTransactionMock() parentLeash = org.mockito.kotlin.mock<SurfaceControl>() surfaceBuilder = SurfaceControl.Builder() spyOn(surfaceBuilder) Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxTestUtils.kt +27 −0 Original line number Diff line number Diff line Loading @@ -16,9 +16,36 @@ package com.android.wm.shell.compatui.letterbox import android.view.SurfaceControl import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.times import org.mockito.verification.VerificationMode /** * @return A [SurfaceControl.Transaction] mock supporting chaining for some operations. Please * add other operations if needed. */ fun getTransactionMock(): SurfaceControl.Transaction = mock<SurfaceControl.Transaction>().apply { doReturn(this).`when`(this).setLayer(anyOrNull(), anyOrNull()) doReturn(this).`when`(this).setColorSpaceAgnostic(anyOrNull(), anyOrNull()) doReturn(this).`when`(this).setPosition(anyOrNull(), any(), any()) doReturn(this).`when`(this).setWindowCrop(anyOrNull(), any(), any()) } // Utility to make verification mode depending on a [Boolean]. fun Boolean.asMode(): VerificationMode = if (this) times(1) else never() // Utility matchers to use for the main types as Mockito [VerificationMode]. object LetterboxMatchers { fun Int.asAnyMode() = asAnyMode { this < 0 } fun Float.asAnyMode() = asAnyMode { this < 0f } fun String.asAnyMode() = asAnyMode { this.isEmpty() } } private inline fun <reified T : Any> T.asAnyMode(condition: () -> Boolean) = (if (condition()) any() else eq(this))
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/MultiSurfaceLetterboxControllerTest.kt 0 → 100644 +155 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.letterbox import android.graphics.Rect import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.wm.shell.ShellTestCase import java.util.function.Consumer import org.junit.Test import org.junit.runner.RunWith /** * Tests for [MultiSurfaceLetterboxController]. * * Build/Install/Run: * atest WMShellUnitTests:MultiSurfaceLetterboxControllerTest */ @RunWith(AndroidTestingRunner::class) @SmallTest class MultiSurfaceLetterboxControllerTest : ShellTestCase() { @Test fun `When creation is requested the surfaces are created if not present`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked(times = 4) } } @Test fun `When creation is requested multiple times the surfaces are created once`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked(times = 4) } } @Test fun `Different surfaces are created for every key`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest(displayId = 2) r.sendCreateSurfaceRequest(displayId = 2, taskId = 2) r.sendCreateSurfaceRequest(displayId = 2) r.sendCreateSurfaceRequest(displayId = 2, taskId = 2) r.checkSurfaceBuilderInvoked(times = 12) } } @Test fun `Created surface are removed once`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked(times = 4) r.sendDestroySurfaceRequest() r.sendDestroySurfaceRequest() r.sendDestroySurfaceRequest() r.checkTransactionRemovedInvoked(times = 4) } } @Test fun `Only existing surfaces receive visibility update`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendUpdateSurfaceVisibilityRequest(visible = true) r.sendUpdateSurfaceVisibilityRequest(visible = true, displayId = 20) r.checkVisibilityUpdated(times = 4, expectedVisibility = true) } } @Test fun `Only existing surfaces receive taskBounds update`() { runTestScenario { r -> r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 2000, 1000), activityBounds = Rect(500, 0, 1500, 1000) ) r.checkSurfacePositionUpdated(times = 0) r.checkSurfaceSizeUpdated(times = 0) r.sendCreateSurfaceRequest() // Pillarbox. r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 2000, 1000), activityBounds = Rect(500, 0, 1500, 1000) ) // The Left and Top surfaces. r.checkSurfacePositionUpdated(times = 2, expectedX = 0f, expectedY = 0f) // The Right surface. r.checkSurfacePositionUpdated(times = 1, expectedX = 1500f, expectedY = 0f) // The Bottom surface. r.checkSurfacePositionUpdated(times = 1, expectedX = 0f, expectedY = 1000f) // Left and Right surface. r.checkSurfaceSizeUpdated(times = 2, expectedWidth = 500, expectedHeight = 1000) // Top and Button. r.checkSurfaceSizeUpdated(times = 2, expectedWidth = 2000, expectedHeight = 0) r.resetTransitionTest() // Letterbox. r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 1000, 2000), activityBounds = Rect(0, 500, 1000, 1500) ) // Top and Left surfaces. r.checkSurfacePositionUpdated(times = 2, expectedX = 0f, expectedY = 0f) // Bottom surface. r.checkSurfacePositionUpdated(times = 1, expectedX = 0f, expectedY = 1500f) // Right surface. r.checkSurfacePositionUpdated(times = 1, expectedX = 1000f, expectedY = 0f) // Left and Right surfaces. r.checkSurfaceSizeUpdated(times = 2, expectedWidth = 0, expectedHeight = 2000) // Top and Button surfaces, r.checkSurfaceSizeUpdated(times = 2, expectedWidth = 1000, expectedHeight = 500) } } /** * Runs a test scenario providing a Robot. */ fun runTestScenario(consumer: Consumer<LetterboxControllerRobotTest>) { val robot = LetterboxControllerRobotTest(mContext, { sb -> MultiSurfaceLetterboxController(sb) }) consumer.accept(robot) } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/SingleSurfaceLetterboxControllerTest.kt 0 → 100644 +128 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.compatui.letterbox import android.graphics.Rect import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.wm.shell.ShellTestCase import java.util.function.Consumer import org.junit.Test import org.junit.runner.RunWith /** * Tests for [SingleSurfaceLetterboxController]. * * Build/Install/Run: * atest WMShellUnitTests:SingleSurfaceLetterboxControllerTest */ @RunWith(AndroidTestingRunner::class) @SmallTest class SingleSurfaceLetterboxControllerTest : ShellTestCase() { @Test fun `When creation is requested the surface is created if not present`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked() } } @Test fun `When creation is requested multiple times the surface is created once`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked(times = 1) } } @Test fun `A different surface is created for every key`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest() r.sendCreateSurfaceRequest(displayId = 2) r.sendCreateSurfaceRequest(displayId = 2, taskId = 2) r.sendCreateSurfaceRequest(displayId = 2) r.sendCreateSurfaceRequest(displayId = 2, taskId = 2) r.checkSurfaceBuilderInvoked(times = 3) } } @Test fun `Created surface is removed once`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.checkSurfaceBuilderInvoked() r.sendDestroySurfaceRequest() r.sendDestroySurfaceRequest() r.sendDestroySurfaceRequest() r.checkTransactionRemovedInvoked() } } @Test fun `Only existing surfaces receive visibility update`() { runTestScenario { r -> r.sendCreateSurfaceRequest() r.sendUpdateSurfaceVisibilityRequest(visible = true) r.sendUpdateSurfaceVisibilityRequest(visible = true, displayId = 20) r.checkVisibilityUpdated(expectedVisibility = true) } } @Test fun `Only existing surfaces receive taskBounds update`() { runTestScenario { r -> r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 2000, 1000), activityBounds = Rect(500, 0, 1500, 1000) ) r.checkSurfacePositionUpdated(times = 0) r.checkSurfaceSizeUpdated(times = 0) r.resetTransitionTest() r.sendCreateSurfaceRequest() r.sendUpdateSurfaceBoundsRequest( taskBounds = Rect(0, 0, 2000, 1000), activityBounds = Rect(500, 0, 1500, 1000) ) r.checkSurfacePositionUpdated(times = 1, expectedX = 0f, expectedY = 0f) r.checkSurfaceSizeUpdated(times = 1, expectedWidth = 2000, expectedHeight = 1000) } } /** * Runs a test scenario providing a Robot. */ fun runTestScenario(consumer: Consumer<LetterboxControllerRobotTest>) { val robot = LetterboxControllerRobotTest(mContext, { sb -> SingleSurfaceLetterboxController(sb) }) consumer.accept(robot) } }