Merge "[5/n] Create LetterboxConfiguration component" into main
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxConfiguration.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxConfiguration.kt
new file mode 100644
index 0000000..3bcbf13
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxConfiguration.kt
@@ -0,0 +1,83 @@
+/*
+ * 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.annotation.ColorRes
+import android.content.Context
+import android.graphics.Color
+import com.android.internal.R
+import com.android.wm.shell.dagger.WMSingleton
+import javax.inject.Inject
+
+/**
+ * Contains configuration properties for the letterbox implementation in Shell.
+ */
+@WMSingleton
+class LetterboxConfiguration @Inject constructor(
+ private val context: Context
+) {
+
+ // TODO(b/370940685): Integrate CommandHandler in LetterboxConfiguration.
+ private var letterboxBackgroundColorOverride: Color? = Color.valueOf(Color.YELLOW)
+
+ // Color resource id for the solid color letterbox background type.
+ private var letterboxBackgroundColorResourceIdOverride: Int? = null
+
+ /**
+ * Sets color of letterbox background which is used when using the solid background mode.
+ */
+ fun setLetterboxBackgroundColor(color: Color) {
+ letterboxBackgroundColorOverride = color
+ }
+
+ /**
+ * Sets color ID of letterbox background which is used when using the solid background mode.
+ */
+ fun setLetterboxBackgroundColorResourceId(@ColorRes colorId: Int) {
+ letterboxBackgroundColorResourceIdOverride = colorId
+ }
+
+ /**
+ * Gets color of letterbox background which is used when the solid color mode is active.
+ */
+ fun getLetterboxBackgroundColor(): Color {
+ if (letterboxBackgroundColorOverride != null) {
+ return letterboxBackgroundColorOverride!!
+ }
+ val colorId = if (letterboxBackgroundColorResourceIdOverride != null) {
+ letterboxBackgroundColorResourceIdOverride
+ } else {
+ R.color.config_letterboxBackgroundColor
+ }
+ // Query color dynamically because material colors extracted from wallpaper are updated
+ // when wallpaper is changed.
+ return Color.valueOf(context.getResources().getColor(colorId!!, /* theme */null))
+ }
+
+ /**
+ * Resets color of letterbox background to the default.
+ */
+ fun resetLetterboxBackgroundColor() {
+ letterboxBackgroundColorOverride = null
+ letterboxBackgroundColorResourceIdOverride = null
+ }
+
+ /**
+ * The background color for the Letterbox.
+ */
+ fun getBackgroundColorRgbArray(): FloatArray = getLetterboxBackgroundColor().components
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxController.kt
index 406823d..0ac7aff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxController.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.compatui.letterbox
-import android.graphics.Color
import android.graphics.Rect
import android.view.SurfaceControl
import com.android.internal.protolog.ProtoLog
@@ -28,7 +27,9 @@
* Component responsible for handling the lifecycle of the letterbox surfaces.
*/
@WMSingleton
-class LetterboxController @Inject constructor() {
+class LetterboxController @Inject constructor(
+ private val letterboxConfiguration: LetterboxConfiguration
+) {
companion object {
/*
@@ -64,8 +65,7 @@
this,
TASK_CHILD_LAYER_LETTERBOX_BACKGROUND
).setColorSpaceAgnostic(this, true)
- // TODO(b/370940063): Implement LetterboxConfiguration
- .setColor(this, Color.valueOf(Color.YELLOW).components)
+ .setColor(this, letterboxConfiguration.getBackgroundColorRgbArray())
}
)
})
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxConfigurationTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxConfigurationTest.kt
new file mode 100644
index 0000000..75025d90
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxConfigurationTest.kt
@@ -0,0 +1,160 @@
+/*
+ * 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.annotation.ColorRes
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.Color
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn
+import com.android.internal.R
+import com.android.wm.shell.ShellTestCase
+import java.util.function.Consumer
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+
+/**
+ * Tests for [LetterboxConfiguration].
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:LetterboxConfigurationTest
+ */
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class LetterboxConfigurationTest : ShellTestCase() {
+
+ companion object {
+ @JvmStatic
+ val COLOR_WHITE = Color.valueOf(Color.WHITE)
+ @JvmStatic
+ val COLOR_RED = Color.valueOf(Color.RED)
+ @JvmStatic
+ val COLOR_BLACK = Color.valueOf(Color.BLACK)
+ @JvmStatic
+ val COLOR_WHITE_RESOURCE_ID = android.R.color.white
+ @JvmStatic
+ val COLOR_BLACK_RESOURCE_ID = android.R.color.black
+ }
+
+ @Test
+ fun `default background color is used if override is not set`() {
+ runTestScenario { r ->
+ r.setDefaultBackgroundColorId(COLOR_WHITE_RESOURCE_ID)
+ r.loadConfiguration()
+ r.checkBackgroundColor(COLOR_WHITE)
+ }
+ }
+
+ @Test
+ fun `overridden background color is used if set`() {
+ runTestScenario { r ->
+ r.setDefaultBackgroundColorId(COLOR_WHITE_RESOURCE_ID)
+ r.loadConfiguration()
+ r.overrideBackgroundColor(COLOR_RED)
+ r.checkBackgroundColor(COLOR_RED)
+ }
+ }
+
+ @Test
+ fun `overridden background color resource is used if set without override`() {
+ runTestScenario { r ->
+ r.setDefaultBackgroundColorId(COLOR_WHITE_RESOURCE_ID)
+ r.loadConfiguration()
+ r.overrideBackgroundColorId(COLOR_BLACK_RESOURCE_ID)
+ r.checkBackgroundColor(COLOR_BLACK)
+ }
+ }
+
+ @Test
+ fun `overridden background color has precedence over color id`() {
+ runTestScenario { r ->
+ r.setDefaultBackgroundColorId(COLOR_WHITE_RESOURCE_ID)
+ r.loadConfiguration()
+ r.overrideBackgroundColor(COLOR_RED)
+ r.overrideBackgroundColorId(COLOR_BLACK_RESOURCE_ID)
+ r.checkBackgroundColor(COLOR_RED)
+ }
+ }
+
+ @Test
+ fun `reset background color`() {
+ runTestScenario { r ->
+ r.setDefaultBackgroundColorId(COLOR_WHITE_RESOURCE_ID)
+ r.loadConfiguration()
+ r.overrideBackgroundColor(COLOR_RED)
+ r.checkBackgroundColor(COLOR_RED)
+
+ r.resetBackgroundColor()
+ r.checkBackgroundColor(COLOR_WHITE)
+
+ r.overrideBackgroundColorId(COLOR_BLACK_RESOURCE_ID)
+ r.checkBackgroundColor(COLOR_BLACK)
+
+ r.resetBackgroundColor()
+ r.checkBackgroundColor(COLOR_WHITE)
+ }
+ }
+
+ /**
+ * Runs a test scenario providing a Robot.
+ */
+ fun runTestScenario(consumer: Consumer<LetterboxConfigurationRobotTest>) {
+ val robot = LetterboxConfigurationRobotTest(mContext)
+ consumer.accept(robot)
+ }
+
+ class LetterboxConfigurationRobotTest(private val ctx: Context) {
+
+ private val resources: Resources
+ private lateinit var letterboxConfig: LetterboxConfiguration
+
+ init {
+ resources = ctx.resources
+ spyOn(resources)
+ }
+
+ fun setDefaultBackgroundColorId(@ColorRes colorId: Int) {
+ doReturn(colorId).`when`(resources)
+ .getColor(R.color.config_letterboxBackgroundColor, null)
+ }
+
+ fun loadConfiguration() {
+ letterboxConfig = LetterboxConfiguration(ctx)
+ }
+
+ fun overrideBackgroundColor(color: Color) {
+ letterboxConfig.setLetterboxBackgroundColor(color)
+ }
+
+ fun resetBackgroundColor() {
+ letterboxConfig.resetLetterboxBackgroundColor()
+ }
+
+ fun overrideBackgroundColorId(@ColorRes colorId: Int) {
+ letterboxConfig.setLetterboxBackgroundColorResourceId(colorId)
+ }
+
+ fun checkBackgroundColor(expected: Color) {
+ val colorComponents = letterboxConfig.getBackgroundColorRgbArray()
+ val expectedComponents = expected.components
+ assert(expectedComponents.contentEquals(colorComponents))
+ }
+ }
+}