summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilder.kt59
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/SingleSurfaceLetterboxController.kt29
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilderTest.kt146
3 files changed, 212 insertions, 22 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilder.kt
new file mode 100644
index 000000000000..e88d91f3956c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilder.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.view.SurfaceControl
+import com.android.wm.shell.dagger.WMSingleton
+import javax.inject.Inject
+
+/**
+ * Component responsible for the actual creation of the Letterbox surfaces.
+ */
+@WMSingleton
+class LetterboxSurfaceBuilder @Inject constructor(
+ private val letterboxConfiguration: LetterboxConfiguration
+) {
+
+ companion object {
+ /*
+ * Letterbox surfaces need to stay below the activity layer which is 0.
+ */
+ // TODO(b/378673153): Consider adding this to [TaskConstants].
+ @JvmStatic
+ private val TASK_CHILD_LAYER_LETTERBOX_BACKGROUND = -1000
+ }
+
+ fun createSurface(
+ tx: SurfaceControl.Transaction,
+ parentLeash: SurfaceControl,
+ surfaceName: String,
+ callSite: String,
+ surfaceBuilder: SurfaceControl.Builder = SurfaceControl.Builder()
+ ) = surfaceBuilder
+ .setName(surfaceName)
+ .setHidden(true)
+ .setColorLayer()
+ .setParent(parentLeash)
+ .setCallsite(callSite)
+ .build().apply {
+ tx.setLayer(
+ this,
+ TASK_CHILD_LAYER_LETTERBOX_BACKGROUND
+ ).setColorSpaceAgnostic(this, true)
+ .setColor(this, letterboxConfiguration.getBackgroundColorRgbArray())
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/SingleSurfaceLetterboxController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/SingleSurfaceLetterboxController.kt
index d918b87be799..f21a7272287e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/SingleSurfaceLetterboxController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/SingleSurfaceLetterboxController.kt
@@ -29,17 +29,10 @@ import javax.inject.Inject
*/
@WMSingleton
class SingleSurfaceLetterboxController @Inject constructor(
- private val letterboxConfiguration: LetterboxConfiguration
+ private val letterboxBuilder: LetterboxSurfaceBuilder
) : LetterboxController {
companion object {
- /*
- * Letterbox surfaces need to stay below the activity layer which is 0.
- */
- // TODO(b/378673153): Consider adding this to [TaskConstants].
- @JvmStatic
- private val TASK_CHILD_LAYER_LETTERBOX_BACKGROUND = -1000
-
@JvmStatic
private val TAG = "LetterboxController"
}
@@ -55,20 +48,12 @@ class SingleSurfaceLetterboxController @Inject constructor(
parentLeash: SurfaceControl
) {
letterboxMap.runOnItem(key, onMissed = { k, m ->
- m[k] =
- SurfaceControl.Builder()
- .setName("ShellLetterboxSurface-$key")
- .setHidden(true)
- .setColorLayer()
- .setParent(parentLeash)
- .setCallsite("LetterboxController-createLetterboxSurface")
- .build().apply {
- transaction.setLayer(
- this,
- TASK_CHILD_LAYER_LETTERBOX_BACKGROUND
- ).setColorSpaceAgnostic(this, true)
- .setColor(this, letterboxConfiguration.getBackgroundColorRgbArray())
- }
+ m[k] = letterboxBuilder.createSurface(
+ transaction,
+ parentLeash,
+ surfaceName = "ShellLetterboxSurface-$key",
+ callSite = "LetterboxController-createLetterboxSurface"
+ )
})
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilderTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilderTest.kt
new file mode 100644
index 000000000000..68d9bf9b926f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxSurfaceBuilderTest.kt
@@ -0,0 +1,146 @@
+/*
+ * 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.testing.AndroidTestingRunner
+import android.view.SurfaceControl
+import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn
+import com.android.wm.shell.ShellTestCase
+import java.util.function.Consumer
+import org.junit.Test
+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.never
+import org.mockito.kotlin.times
+import org.mockito.verification.VerificationMode
+
+/**
+ * Tests for [LetterboxSurfaceBuilder].
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:LetterboxSurfaceBuilderTest
+ */
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class LetterboxSurfaceBuilderTest : ShellTestCase() {
+
+ @Test
+ fun `When surface is created mandatory methods are invoked`() {
+ runTestScenario { r ->
+ r.invokeBuilder()
+
+ r.checkNameIsSet(expected = true)
+ r.checkCallSiteIsSet(expected = true)
+ r.checkSurfaceIsHidden(invoked = true, isHidden = true)
+ r.checkColorLayerIsSet(expected = true)
+ r.checkParentLeashIsSet(expected = true)
+ r.checkSetLayerIsInvoked(expected = true)
+ r.checkColorSpaceAgnosticIsSet(expected = true, value = true)
+ r.checkColorIsSetFromLetterboxConfiguration(expected = true)
+ }
+ }
+
+ /**
+ * Runs a test scenario providing a Robot.
+ */
+ fun runTestScenario(consumer: Consumer<LetterboxSurfaceBuilderRobotTest>) {
+ val robot = LetterboxSurfaceBuilderRobotTest(mContext)
+ consumer.accept(robot)
+ }
+
+ class LetterboxSurfaceBuilderRobotTest(val ctx: Context) {
+
+ private val letterboxConfiguration: LetterboxConfiguration
+ private val letterboxSurfaceBuilder: LetterboxSurfaceBuilder
+ private val tx: SurfaceControl.Transaction
+ private val parentLeash: SurfaceControl
+ private val surfaceBuilder: SurfaceControl.Builder
+
+ companion object {
+ @JvmStatic
+ val TEST_SURFACE_NAME = "SurfaceForTest"
+
+ @JvmStatic
+ val TEST_SURFACE_CALL_SITE = "CallSiteForTest"
+ }
+
+ 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())
+ parentLeash = org.mockito.kotlin.mock<SurfaceControl>()
+ surfaceBuilder = SurfaceControl.Builder()
+ spyOn(surfaceBuilder)
+ }
+
+ fun invokeBuilder() {
+ letterboxSurfaceBuilder.createSurface(
+ tx,
+ parentLeash,
+ TEST_SURFACE_NAME,
+ TEST_SURFACE_CALL_SITE,
+ surfaceBuilder
+ )
+ }
+
+ fun checkNameIsSet(expected: Boolean) {
+ verify(surfaceBuilder, expected.asMode())
+ .setName(TEST_SURFACE_NAME)
+ }
+
+ fun checkCallSiteIsSet(expected: Boolean) {
+ verify(surfaceBuilder, expected.asMode())
+ .setCallsite(TEST_SURFACE_CALL_SITE)
+ }
+
+ fun checkSurfaceIsHidden(invoked: Boolean, isHidden: Boolean) {
+ verify(surfaceBuilder, invoked.asMode())
+ .setHidden(isHidden)
+ }
+
+ fun checkColorLayerIsSet(expected: Boolean) {
+ verify(surfaceBuilder, expected.asMode()).setColorLayer()
+ }
+
+ fun checkParentLeashIsSet(expected: Boolean) {
+ verify(surfaceBuilder, expected.asMode()).setParent(parentLeash)
+ }
+
+ fun checkSetLayerIsInvoked(expected: Boolean) {
+ verify(tx, expected.asMode()).setLayer(anyOrNull(), ArgumentMatchers.anyInt())
+ }
+
+ fun checkColorSpaceAgnosticIsSet(expected: Boolean, value: Boolean) {
+ verify(tx, expected.asMode()).setColorSpaceAgnostic(anyOrNull(), eq(value))
+ }
+
+ fun checkColorIsSetFromLetterboxConfiguration(expected: Boolean) {
+ val components = letterboxConfiguration.getBackgroundColorRgbArray()
+ verify(tx, expected.asMode()).setColor(anyOrNull(), eq(components))
+ }
+
+ private fun Boolean.asMode(): VerificationMode = if (this) times(1) else never()
+ }
+}