[Letterbox][Status Bar] Re-fetch background info on wallpaper changes

The letterbox background color is a dynamic color that changes when the
wallpaper changes.
This color is used to pick between the dark/light status bar icons.

Test: LetterboxBackgroundProviderTest.kt
Test: Manually
Fixes: 242048484
Change-Id: I0be40127270371212f0d574f01874742f3b95d02
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProvider.kt
index 96b9aca..2763750 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProvider.kt
@@ -17,11 +17,14 @@
 package com.android.systemui.statusbar.phone
 
 import android.annotation.ColorInt
+import android.app.WallpaperManager
 import android.graphics.Color
+import android.os.Handler
 import android.os.RemoteException
 import android.view.IWindowManager
 import com.android.systemui.Dumpable
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
 import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
@@ -37,6 +40,8 @@
     private val windowManager: IWindowManager,
     @Background private val backgroundExecutor: Executor,
     private val dumpManager: DumpManager,
+    private val wallpaperManager: WallpaperManager,
+    @Main private val mainHandler: Handler,
 ) : CentralSurfacesComponent.Startable, Dumpable {
 
     @ColorInt
@@ -46,9 +51,18 @@
     var isLetterboxBackgroundMultiColored: Boolean = false
         private set
 
+    private val wallpaperColorsListener =
+        WallpaperManager.OnColorsChangedListener { _, _ ->
+            fetchBackgroundColorInfo()
+        }
+
     override fun start() {
         dumpManager.registerDumpable(javaClass.simpleName, this)
+        fetchBackgroundColorInfo()
+        wallpaperManager.addOnColorsChangedListener(wallpaperColorsListener, mainHandler)
+    }
 
+    private fun fetchBackgroundColorInfo() {
         // Using a background executor, as binder calls to IWindowManager are blocking
         backgroundExecutor.execute {
             try {
@@ -62,6 +76,7 @@
 
     override fun stop() {
         dumpManager.unregisterDumpable(javaClass.simpleName)
+        wallpaperManager.removeOnColorsChangedListener(wallpaperColorsListener)
     }
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
index 44325dd..a2828d33 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
@@ -16,19 +16,28 @@
 
 package com.android.systemui.statusbar.phone
 
+import android.app.WallpaperManager
+import android.app.WallpaperManager.OnColorsChangedListener
 import android.graphics.Color
+import android.os.Handler
+import android.os.Looper
 import android.testing.AndroidTestingRunner
 import android.view.IWindowManager
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Expect
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.doAnswer
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
 
@@ -38,17 +47,41 @@
 
     private val fakeSystemClock = FakeSystemClock()
     private val fakeExecutor = FakeExecutor(fakeSystemClock)
+    private val mainHandler = Handler(Looper.getMainLooper())
+
+    @get:Rule var expect: Expect = Expect.create()
 
     @Mock private lateinit var windowManager: IWindowManager
     @Mock private lateinit var dumpManager: DumpManager
+    @Mock private lateinit var wallpaperManager: WallpaperManager
 
     private lateinit var provider: LetterboxBackgroundProvider
 
+    private var wallpaperColorsListener: OnColorsChangedListener? = null
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        provider = LetterboxBackgroundProvider(windowManager, fakeExecutor, dumpManager)
+        setUpWallpaperManager()
+        provider =
+            LetterboxBackgroundProvider(
+                windowManager, fakeExecutor, dumpManager, wallpaperManager, mainHandler)
+    }
+
+    private fun setUpWallpaperManager() {
+        doAnswer { invocation ->
+                wallpaperColorsListener = invocation.arguments[0] as OnColorsChangedListener
+                return@doAnswer Unit
+            }
+            .`when`(wallpaperManager)
+            .addOnColorsChangedListener(any(), eq(mainHandler))
+        doAnswer {
+                wallpaperColorsListener = null
+                return@doAnswer Unit
+            }
+            .`when`(wallpaperManager)
+            .removeOnColorsChangedListener(any(OnColorsChangedListener::class.java))
     }
 
     @Test
@@ -76,6 +109,31 @@
     }
 
     @Test
+    fun letterboxBackgroundColor_returnsValueFromWindowManagerOnlyOnce() {
+        whenever(windowManager.letterboxBackgroundColorInArgb).thenReturn(Color.RED)
+        provider.start()
+        fakeExecutor.runAllReady()
+        expect.that(provider.letterboxBackgroundColor).isEqualTo(Color.RED)
+
+        whenever(windowManager.letterboxBackgroundColorInArgb).thenReturn(Color.GREEN)
+        fakeExecutor.runAllReady()
+        expect.that(provider.letterboxBackgroundColor).isEqualTo(Color.RED)
+    }
+
+    @Test
+    fun letterboxBackgroundColor_afterWallpaperChanges_returnsUpdatedColor() {
+        whenever(windowManager.letterboxBackgroundColorInArgb).thenReturn(Color.RED)
+        provider.start()
+        fakeExecutor.runAllReady()
+
+        whenever(windowManager.letterboxBackgroundColorInArgb).thenReturn(Color.GREEN)
+        wallpaperColorsListener!!.onColorsChanged(null, 0)
+        fakeExecutor.runAllReady()
+
+        assertThat(provider.letterboxBackgroundColor).isEqualTo(Color.GREEN)
+    }
+
+    @Test
     fun isLetterboxBackgroundMultiColored_defaultValue_returnsFalse() {
         assertThat(provider.isLetterboxBackgroundMultiColored).isEqualTo(false)
     }