diff options
50 files changed, 501 insertions, 189 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayWindowPropertiesRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayWindowPropertiesRepositoryImplTest.kt index f68a1b5a17e9..eae5728f586d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayWindowPropertiesRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayWindowPropertiesRepositoryImplTest.kt @@ -16,7 +16,7 @@ package com.android.systemui.display.data.repository -import android.content.testableContext +import android.content.Context import android.platform.test.annotations.EnableFlags import android.view.Display import android.view.layoutInflater @@ -24,6 +24,7 @@ import android.view.mockWindowManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.SysuiTestableContext import com.android.systemui.display.shared.model.DisplayWindowProperties import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testScope @@ -36,8 +37,12 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito.doAnswer +import org.mockito.kotlin.any import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.whenever @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) @RunWith(AndroidJUnit4::class) @@ -48,7 +53,8 @@ class DisplayWindowPropertiesRepositoryImplTest : SysuiTestCase() { private val fakeDisplayRepository = kosmos.displayRepository private val testScope = kosmos.testScope - private val applicationContext = kosmos.testableContext + private val applicationContext = spy(context) + private val applicationWindowManager = kosmos.mockWindowManager private val applicationLayoutInflater = kosmos.layoutInflater @@ -64,6 +70,22 @@ class DisplayWindowPropertiesRepositoryImplTest : SysuiTestCase() { } @Before + fun setUpContext() { + doAnswer { createContextForDisplay(it.arguments[0] as Display) } + .whenever(applicationContext) + .createWindowContext(any(), any(), any()) + } + + private fun createContextForDisplay(display: Display): Context { + if (display.displayId == BEING_REMOVED_DISPLAY_ID) { + // Simulate what happens when a display is being removed. + // Return a context with the same display id as the original context. + return mContext + } + return SysuiTestableContext(mContext).also { it.display = display } + } + + @Before fun start() { repo.start() } @@ -72,6 +94,7 @@ class DisplayWindowPropertiesRepositoryImplTest : SysuiTestCase() { fun addDisplays() = runBlocking { fakeDisplayRepository.addDisplay(createDisplay(DEFAULT_DISPLAY_ID)) fakeDisplayRepository.addDisplay(createDisplay(NON_DEFAULT_DISPLAY_ID)) + fakeDisplayRepository.addDisplay(createDisplay(BEING_REMOVED_DISPLAY_ID)) } @Test @@ -94,7 +117,7 @@ class DisplayWindowPropertiesRepositoryImplTest : SysuiTestCase() { @Test fun get_nonDefaultDisplayId_returnsNewStatusBarContext() = testScope.runTest { - val displayContext = repo.get(NON_DEFAULT_DISPLAY_ID, WINDOW_TYPE_FOO) + val displayContext = repo.get(NON_DEFAULT_DISPLAY_ID, WINDOW_TYPE_FOO)!! assertThat(displayContext.context).isNotSameInstanceAs(applicationContext) } @@ -102,7 +125,7 @@ class DisplayWindowPropertiesRepositoryImplTest : SysuiTestCase() { @Test fun get_nonDefaultDisplayId_returnsNewWindowManager() = testScope.runTest { - val displayContext = repo.get(NON_DEFAULT_DISPLAY_ID, WINDOW_TYPE_FOO) + val displayContext = repo.get(NON_DEFAULT_DISPLAY_ID, WINDOW_TYPE_FOO)!! assertThat(displayContext.windowManager).isNotSameInstanceAs(applicationWindowManager) } @@ -110,7 +133,7 @@ class DisplayWindowPropertiesRepositoryImplTest : SysuiTestCase() { @Test fun get_nonDefaultDisplayId_returnsNewLayoutInflater() = testScope.runTest { - val displayContext = repo.get(NON_DEFAULT_DISPLAY_ID, WINDOW_TYPE_FOO) + val displayContext = repo.get(NON_DEFAULT_DISPLAY_ID, WINDOW_TYPE_FOO)!! assertThat(displayContext.layoutInflater).isNotSameInstanceAs(applicationLayoutInflater) } @@ -154,17 +177,26 @@ class DisplayWindowPropertiesRepositoryImplTest : SysuiTestCase() { .isNotSameInstanceAs(displayContext) } - @Test(expected = IllegalArgumentException::class) - fun get_nonExistingDisplayId_throws() = - testScope.runTest { repo.get(NON_EXISTING_DISPLAY_ID, WINDOW_TYPE_FOO) } + @Test + fun get_nonExistingDisplayId_returnsNull() = + testScope.runTest { + assertThat(repo.get(NON_EXISTING_DISPLAY_ID, WINDOW_TYPE_FOO)).isNull() + } + + @Test + fun get_displayBeingRemoved_returnsNull() = + testScope.runTest { + assertThat(repo.get(BEING_REMOVED_DISPLAY_ID, WINDOW_TYPE_FOO)).isNull() + } private fun createDisplay(displayId: Int) = - mock<Display> { on { getDisplayId() } doReturn displayId } + mock<Display> { on { getDisplayId() } doReturn (displayId) } companion object { private const val DEFAULT_DISPLAY_ID = Display.DEFAULT_DISPLAY private const val NON_DEFAULT_DISPLAY_ID = DEFAULT_DISPLAY_ID + 1 private const val NON_EXISTING_DISPLAY_ID = DEFAULT_DISPLAY_ID + 2 + private const val BEING_REMOVED_DISPLAY_ID = DEFAULT_DISPLAY_ID + 4 private const val WINDOW_TYPE_FOO = 123 private const val WINDOW_TYPE_BAR = 321 } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayStoreImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayStoreImplTest.kt index 6a0781b3580f..73957eb488d0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayStoreImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayStoreImplTest.kt @@ -80,9 +80,9 @@ class PerDisplayStoreImplTest : SysuiTestCase() { assertThat(store.forDisplay(NON_DEFAULT_DISPLAY_ID)).isNotSameInstanceAs(instance) } - @Test(expected = IllegalArgumentException::class) - fun forDisplay_nonExistingDisplayId_throws() = - testScope.runTest { store.forDisplay(NON_EXISTING_DISPLAY_ID) } + @Test + fun forDisplay_nonExistingDisplayId_returnsNull() = + testScope.runTest { assertThat(store.forDisplay(NON_EXISTING_DISPLAY_ID)).isNull() } @Test fun forDisplay_afterDisplayRemoved_onDisplayRemovalActionInvoked() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt index 009b33b9f808..3515c5649ca0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarInitializerTest.kt @@ -26,10 +26,12 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.fragments.FragmentHostManager import com.android.systemui.kosmos.useUnconfinedTestDispatcher +import com.android.systemui.plugins.fakeDarkIconDispatcher import com.android.systemui.statusbar.data.repository.fakeStatusBarModePerDisplayRepository import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment import com.android.systemui.statusbar.phone.fragment.dagger.HomeStatusBarComponent import com.android.systemui.statusbar.pipeline.shared.ui.composable.StatusBarRootFactory +import com.android.systemui.statusbar.policy.statusBarConfigurationController import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.statusbar.window.StatusBarWindowControllerStore import com.android.systemui.testKosmos @@ -77,6 +79,8 @@ class StatusBarInitializerTest : SysuiTestCase() { componentFactory = mock(HomeStatusBarComponent.Factory::class.java), creationListeners = setOf(), statusBarModePerDisplayRepository = statusBarModePerDisplayRepository, + darkIconDispatcher = kosmos.fakeDarkIconDispatcher, + statusBarConfigurationController = kosmos.statusBarConfigurationController, ) @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreImplTest.kt index 18eef33813f6..884c35c3457d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreImplTest.kt @@ -51,7 +51,7 @@ class LightBarControllerStoreImplTest : SysuiTestCase() { @Test fun forDisplay_startsInstance() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! verify(instance).start() } @@ -59,7 +59,7 @@ class LightBarControllerStoreImplTest : SysuiTestCase() { @Test fun beforeDisplayRemoved_doesNotStopInstances() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! verify(instance, never()).stop() } @@ -67,7 +67,7 @@ class LightBarControllerStoreImplTest : SysuiTestCase() { @Test fun displayRemoved_stopsInstance() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayDarkIconDispatcherStoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayDarkIconDispatcherStoreTest.kt index a2c3c66f4448..f37648a639df 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayDarkIconDispatcherStoreTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayDarkIconDispatcherStoreTest.kt @@ -56,7 +56,7 @@ class MultiDisplayDarkIconDispatcherStoreTest : SysuiTestCase() { @Test fun beforeDisplayRemoved_doesNotStopInstances() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! verify(instance, never()).stop() } @@ -64,7 +64,7 @@ class MultiDisplayDarkIconDispatcherStoreTest : SysuiTestCase() { @Test fun displayRemoved_stopsInstance() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayStatusBarContentInsetsProviderStoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayStatusBarContentInsetsProviderStoreTest.kt index 4a26fdf20e6e..e0a1f273aa44 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayStatusBarContentInsetsProviderStoreTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayStatusBarContentInsetsProviderStoreTest.kt @@ -51,7 +51,7 @@ class MultiDisplayStatusBarContentInsetsProviderStoreTest : SysuiTestCase() { @Test fun forDisplay_startsInstances() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! verify(instance).start() } @@ -59,7 +59,7 @@ class MultiDisplayStatusBarContentInsetsProviderStoreTest : SysuiTestCase() { @Test fun beforeDisplayRemoved_doesNotStopInstances() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! verify(instance, never()).stop() } @@ -67,7 +67,7 @@ class MultiDisplayStatusBarContentInsetsProviderStoreTest : SysuiTestCase() { @Test fun displayRemoved_stopsInstance() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayStatusBarModeRepositoryStoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayStatusBarModeRepositoryStoreTest.kt index a9920ec5e29b..11fd902fc50c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayStatusBarModeRepositoryStoreTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/MultiDisplayStatusBarModeRepositoryStoreTest.kt @@ -53,7 +53,7 @@ class MultiDisplayStatusBarModeRepositoryStoreTest : SysuiTestCase() { @Test fun forDisplay_startsInstance() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! verify(instance).start() } @@ -61,7 +61,7 @@ class MultiDisplayStatusBarModeRepositoryStoreTest : SysuiTestCase() { @Test fun displayRemoved_stopsInstance() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStoreImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStoreImplTest.kt index e65c04c45382..3cc592c94678 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStoreImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStoreImplTest.kt @@ -56,7 +56,7 @@ class SystemEventChipAnimationControllerStoreImplTest : SysuiTestCase() { @Test fun beforeDisplayRemoved_doesNotStopInstances() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! verify(instance, never()).stop() } @@ -64,7 +64,7 @@ class SystemEventChipAnimationControllerStoreImplTest : SysuiTestCase() { @Test fun displayRemoved_stopsInstance() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt index be20bc1bf9d4..d86c6efce284 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt @@ -225,7 +225,7 @@ class NotificationIconContainerStatusBarViewModelTest(flags: FlagsParameterizati val displayId = 123 darkIconRepository.darkState(displayId).value = SysuiDarkIconDispatcher.DarkChange(emptyList(), 0f, 0xAABBCC) - val iconColors by collectLastValue(underTest.iconColors(displayId)) + val iconColors by collectLastValue(underTest.iconColors(displayId)!!) assertThat(iconColors).isNotNull() assertThat(iconColors!!.tint).isEqualTo(0xAABBCC) @@ -241,7 +241,7 @@ class NotificationIconContainerStatusBarViewModelTest(flags: FlagsParameterizati val displayId = 321 darkIconRepository.darkState(displayId).value = SysuiDarkIconDispatcher.DarkChange(listOf(Rect(0, 0, 5, 5)), 0f, 0xAABBCC) - val iconColors by collectLastValue(underTest.iconColors(displayId)) + val iconColors by collectLastValue(underTest.iconColors(displayId)!!) val staticDrawableColor = iconColors?.staticDrawableColor(Rect(6, 6, 7, 7)) assertThat(staticDrawableColor).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT) } @@ -252,7 +252,7 @@ class NotificationIconContainerStatusBarViewModelTest(flags: FlagsParameterizati val displayId = 987 darkIconRepository.darkState(displayId).value = SysuiDarkIconDispatcher.DarkChange(listOf(Rect(0, 0, 5, 5)), 0f, 0xAABBCC) - val iconColors by collectLastValue(underTest.iconColors(displayId)) + val iconColors by collectLastValue(underTest.iconColors(displayId)!!) assertThat(iconColors!!.staticDrawableColor(Rect(6, 6, 7, 7))) .isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt index 90506a1b9a7f..d16372611e88 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt @@ -56,7 +56,7 @@ class MultiDisplayAutoHideControllerStoreTest : SysuiTestCase() { @Test fun beforeDisplayRemoved_doesNotStopInstances() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! verify(instance, never()).stop() } @@ -64,7 +64,7 @@ class MultiDisplayAutoHideControllerStoreTest : SysuiTestCase() { @Test fun displayRemoved_stopsInstance() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt index 2d9880a48f80..659d91a95aa8 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt @@ -39,7 +39,7 @@ class LightsOutInteractorTest : SysuiTestCase() { fun isLowProfile_lightsOutStatusBarMode_false() = runTest { statusBarModeRepository.defaultDisplay.statusBarMode.value = StatusBarMode.LIGHTS_OUT - val actual by collectLastValue(interactor.isLowProfile(DISPLAY_ID)) + val actual by collectLastValue(interactor.isLowProfile(DISPLAY_ID)!!) assertThat(actual).isTrue() } @@ -49,7 +49,7 @@ class LightsOutInteractorTest : SysuiTestCase() { statusBarModeRepository.defaultDisplay.statusBarMode.value = StatusBarMode.LIGHTS_OUT_TRANSPARENT - val actual by collectLastValue(interactor.isLowProfile(DISPLAY_ID)) + val actual by collectLastValue(interactor.isLowProfile(DISPLAY_ID)!!) assertThat(actual).isTrue() } @@ -58,7 +58,7 @@ class LightsOutInteractorTest : SysuiTestCase() { fun isLowProfile_transparentStatusBarMode_false() = runTest { statusBarModeRepository.defaultDisplay.statusBarMode.value = StatusBarMode.TRANSPARENT - val actual by collectLastValue(interactor.isLowProfile(DISPLAY_ID)) + val actual by collectLastValue(interactor.isLowProfile(DISPLAY_ID)!!) assertThat(actual).isFalse() } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/MultiDisplayStatusBarWindowControllerStoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/MultiDisplayStatusBarWindowControllerStoreTest.kt index 7a9d0179b239..769f012bfdf7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/MultiDisplayStatusBarWindowControllerStoreTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/MultiDisplayStatusBarWindowControllerStoreTest.kt @@ -53,7 +53,7 @@ class MultiDisplayStatusBarWindowControllerStoreTest : SysuiTestCase() { @Test fun beforeDisplayRemoved_doesNotStopInstances() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! verify(instance, never()).stop() } @@ -61,7 +61,7 @@ class MultiDisplayStatusBarWindowControllerStoreTest : SysuiTestCase() { @Test fun displayRemoved_stopsInstance() = testScope.runTest { - val instance = underTest.forDisplay(DEFAULT_DISPLAY) + val instance = underTest.forDisplay(DEFAULT_DISPLAY)!! fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY) diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayWindowPropertiesRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayWindowPropertiesRepository.kt index f310b30c1a81..3390640fa6c6 100644 --- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayWindowPropertiesRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayWindowPropertiesRepository.kt @@ -18,6 +18,8 @@ package com.android.systemui.display.data.repository import android.annotation.SuppressLint import android.content.Context +import android.os.Bundle +import android.util.Log import android.view.Display import android.view.LayoutInflater import android.view.WindowManager @@ -39,14 +41,13 @@ import kotlinx.coroutines.CoroutineScope interface DisplayWindowPropertiesRepository { /** - * Returns a [DisplayWindowProperties] instance for a given display id and window type. - * - * @throws IllegalArgumentException if no display with the given display id exists. + * Returns a [DisplayWindowProperties] instance for a given display id and window type, or null + * if no display with the given display id exists. */ fun get( displayId: Int, @WindowManager.LayoutParams.WindowType windowType: Int, - ): DisplayWindowProperties + ): DisplayWindowProperties? } @SysUISingleton @@ -72,12 +73,10 @@ constructor( override fun get( displayId: Int, @WindowManager.LayoutParams.WindowType windowType: Int, - ): DisplayWindowProperties { - val display = - displayRepository.getDisplay(displayId) - ?: throw IllegalArgumentException("Display with id $displayId doesn't exist") + ): DisplayWindowProperties? { + val display = displayRepository.getDisplay(displayId) ?: return null return properties.get(displayId, windowType) - ?: create(display, windowType).also { properties.put(displayId, windowType, it) } + ?: create(display, windowType)?.also { properties.put(displayId, windowType, it) } } override fun start() { @@ -88,7 +87,7 @@ constructor( } } - private fun create(display: Display, windowType: Int): DisplayWindowProperties { + private fun create(display: Display, windowType: Int): DisplayWindowProperties? { val displayId = display.displayId return if (displayId == Display.DEFAULT_DISPLAY) { // For the default display, we can just reuse the global/application properties. @@ -102,6 +101,14 @@ constructor( ) } else { val context = createWindowContext(display, windowType) + if (context.displayId != display.displayId) { + Log.e( + TAG, + "Returning null because the new context doesn't have the desired display id " + + "${display.displayId}. Display was already removed.", + ) + return null + } @SuppressLint("NonInjectedService") // Need to manually get the service val windowManager = context.getSystemService(WindowManager::class.java) as WindowManager val layoutInflater = LayoutInflater.from(context) @@ -110,11 +117,15 @@ constructor( } private fun createWindowContext(display: Display, windowType: Int): Context = - globalContext.createWindowContext(display, windowType, /* options= */ null).also { + globalContext.createWindowContext(display, windowType, /* options= */ Bundle.EMPTY).also { it.setTheme(R.style.Theme_SystemUI) } override fun dump(pw: PrintWriter, args: Array<out String>) { pw.write("perDisplayContexts: $properties") } + + private companion object { + const val TAG = "DisplayWindowPropsRepo" + } } diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayStore.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayStore.kt index 711534f9dbf0..564588c159bd 100644 --- a/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayStore.kt +++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayStore.kt @@ -16,6 +16,7 @@ package com.android.systemui.display.data.repository +import android.util.Log import android.view.Display import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.CoreStartable @@ -36,12 +37,10 @@ interface PerDisplayStore<T> { val defaultDisplay: T /** - * Returns an instance for a specific display id. - * - * @throws IllegalArgumentException if [displayId] doesn't match the id of any existing - * displays. + * Returns an instance for a specific display id, or null if [displayId] doesn't match the id of + * any existing displays. */ - fun forDisplay(displayId: Int): T + fun forDisplay(displayId: Int): T? } abstract class PerDisplayStoreImpl<T>( @@ -58,7 +57,7 @@ abstract class PerDisplayStoreImpl<T>( * Note that the id of the default display is [Display.DEFAULT_DISPLAY]. */ override val defaultDisplay: T - get() = forDisplay(Display.DEFAULT_DISPLAY) + get() = forDisplay(Display.DEFAULT_DISPLAY)!! /** * Returns an instance for a specific display id. @@ -66,16 +65,30 @@ abstract class PerDisplayStoreImpl<T>( * @throws IllegalArgumentException if [displayId] doesn't match the id of any existing * displays. */ - override fun forDisplay(displayId: Int): T { + override fun forDisplay(displayId: Int): T? { if (displayRepository.getDisplay(displayId) == null) { - throw IllegalArgumentException("Display with id $displayId doesn't exist.") + Log.e(TAG, "<${instanceClass.simpleName}>: Display with id $displayId doesn't exist.") + return null } - return perDisplayInstances.computeIfAbsent(displayId) { - createInstanceForDisplay(displayId) + synchronized(perDisplayInstances) { + val existingInstance = perDisplayInstances[displayId] + if (existingInstance != null) { + return existingInstance + } + val newInstance = createInstanceForDisplay(displayId) + if (newInstance == null) { + Log.e( + TAG, + "<${instanceClass.simpleName}> returning null because createInstanceForDisplay($displayId) returned null.", + ) + } else { + perDisplayInstances[displayId] = newInstance + } + return newInstance } } - protected abstract fun createInstanceForDisplay(displayId: Int): T + protected abstract fun createInstanceForDisplay(displayId: Int): T? override fun start() { val instanceType = instanceClass.simpleName @@ -98,6 +111,10 @@ abstract class PerDisplayStoreImpl<T>( override fun dump(pw: PrintWriter, args: Array<out String>) { pw.println(perDisplayInstances) } + + private companion object { + const val TAG = "PerDisplayStore" + } } class SingleDisplayStore<T>(defaultInstance: T) : PerDisplayStore<T> { diff --git a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/DisplayWindowPropertiesInteractor.kt b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/DisplayWindowPropertiesInteractor.kt index 22e467bd5e3c..99c9ca98bae9 100644 --- a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/DisplayWindowPropertiesInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/DisplayWindowPropertiesInteractor.kt @@ -33,7 +33,7 @@ interface DisplayWindowPropertiesInteractor { * * @throws IllegalArgumentException if no display with the given display id exists. */ - fun getForStatusBar(displayId: Int): DisplayWindowProperties + fun getForStatusBar(displayId: Int): DisplayWindowProperties? } @SysUISingleton @@ -42,7 +42,7 @@ class DisplayWindowPropertiesInteractorImpl constructor(private val repo: DisplayWindowPropertiesRepository) : DisplayWindowPropertiesInteractor { - override fun getForStatusBar(displayId: Int): DisplayWindowProperties { + override fun getForStatusBar(displayId: Int): DisplayWindowProperties? { return repo.get(displayId, TYPE_STATUS_BAR) } } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java index c895732f79f6..f9df67661b49 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java @@ -720,9 +720,24 @@ public class NavigationBar extends ViewController<NavigationBarView> implements if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mView); - mViewCaptureAwareWindowManager.addView(mFrame, - getBarLayoutParams(mContext.getResources().getConfiguration().windowConfiguration - .getRotation())); + try { + mViewCaptureAwareWindowManager.addView( + mFrame, + getBarLayoutParams( + mContext.getResources() + .getConfiguration() + .windowConfiguration + .getRotation())); + } catch (WindowManager.InvalidDisplayException e) { + // Wrapping this in a try/catch to avoid crashes when a display is instantly removed + // after being added, and initialization hasn't finished yet. + Log.e( + TAG, + "Unable to add view to WindowManager. Display with id " + + mDisplayId + + " does not exist anymore", + e); + } mDisplayId = mContext.getDisplayId(); mIsOnDefaultDisplay = mDisplayId == mDisplayTracker.getDefaultDisplayId(); @@ -764,6 +779,15 @@ public class NavigationBar extends ViewController<NavigationBarView> implements Trace.beginSection("NavigationBar#removeViewImmediate"); try { mViewCaptureAwareWindowManager.removeViewImmediate(mView.getRootView()); + } catch (IllegalArgumentException e) { + // Wrapping this in a try/catch to avoid crashes when a display is instantly removed + // after being added, and initialization hasn't finished yet. + // When that happens, adding the View to WindowManager fails, and therefore removing + // it here will fail too, since it wasn't added in the first place. + Log.e( + TAG, + "Failed to removed view from WindowManager. The View wasn't attached.", + e); } finally { Trace.endSection(); } @@ -859,7 +883,15 @@ public class NavigationBar extends ViewController<NavigationBarView> implements if (mOrientationHandle != null) { resetSecondaryHandle(); getBarTransitions().removeDarkIntensityListener(mOrientationHandleIntensityListener); - mViewCaptureAwareWindowManager.removeView(mOrientationHandle); + try { + mViewCaptureAwareWindowManager.removeView(mOrientationHandle); + } catch (IllegalArgumentException e) { + // Wrapping this in a try/catch to avoid crashes when a display is instantly removed + // after being added, and initialization hasn't finished yet. + // When that happens, adding the View to WindowManager fails, and therefore removing + // it here will fail too, since it wasn't added in the first place. + Log.e(TAG, "Trying to remove a View that is not attached", e); + } mOrientationHandle.getViewTreeObserver().removeOnGlobalLayoutListener( mOrientationHandleGlobalLayoutListener); } @@ -930,7 +962,18 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mOrientationParams.setTitle("SecondaryHomeHandle" + mContext.getDisplayId()); mOrientationParams.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT; - mViewCaptureAwareWindowManager.addView(mOrientationHandle, mOrientationParams); + try { + mViewCaptureAwareWindowManager.addView(mOrientationHandle, mOrientationParams); + } catch (WindowManager.InvalidDisplayException e) { + // Wrapping this in a try/catch to avoid crashes when a display is instantly removed + // after being added, and initialization hasn't finished yet. + Log.e( + TAG, + "Unable to add view to WindowManager. Display with id " + + mDisplayId + + " does not exist anymore", + e); + } mOrientationHandle.setVisibility(View.GONE); logNavbarOrientation("initSecondaryHomeHandleForRotation"); diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDialogContextInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDialogContextInteractor.kt index 201dc0339a0a..4edba2785e89 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDialogContextInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDialogContextInteractor.kt @@ -77,7 +77,17 @@ constructor( private fun getContextOrDefault(displayId: Int): Context { return try { traceSection({ "Getting dialog context for displayId=$displayId" }) { - displayWindowPropertyRepository.get().get(displayId, DIALOG_WINDOW_TYPE).context + val displayWindowProperties = + displayWindowPropertyRepository.get().get(displayId, DIALOG_WINDOW_TYPE) + if (displayWindowProperties == null) { + Log.e( + TAG, + "DisplayWindowPropertiesRepository returned null for display $displayId. Returning default one", + ) + defaultContext + } else { + displayWindowProperties.context + } } } catch (e: Exception) { // This can happen if the display was disconnected in the meantime. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/CommandQueueInitializer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/CommandQueueInitializer.kt index d24eddaf321f..d25ca285c53b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/core/CommandQueueInitializer.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/CommandQueueInitializer.kt @@ -72,7 +72,7 @@ constructor( private fun initializeStatusBarForDisplay(displayId: Int, result: RegisterStatusBarResult) { if ((result.mTransientBarTypes and WindowInsets.Type.statusBars()) != 0) { - statusBarModeRepository.forDisplay(displayId).showTransient() + statusBarModeRepository.forDisplay(displayId)?.showTransient() } val commandQueueCallbacks = commandQueueCallbacksLazy.get() commandQueueCallbacks.onSystemBarAttributesChanged( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarter.kt index 9e9a38e87924..b057fb0433fe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarter.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/MultiDisplayStatusBarStarter.kt @@ -89,21 +89,26 @@ constructor( } private fun createAndStartOrchestratorForDisplay(displayId: Int) { + val statusBarModeRepository = statusBarModeRepositoryStore.forDisplay(displayId) ?: return + val statusBarInitializer = initializerStore.forDisplay(displayId) ?: return + val statusBarWindowController = + statusBarWindowControllerStore.forDisplay(displayId) ?: return + val autoHideController = autoHideControllerStore.forDisplay(displayId) ?: return statusBarOrchestratorFactory .create( displayId, displayScopeRepository.scopeForDisplay(displayId), statusBarWindowStateRepositoryStore.forDisplay(displayId), - statusBarModeRepositoryStore.forDisplay(displayId), - initializerStore.forDisplay(displayId), - statusBarWindowControllerStore.forDisplay(displayId), - autoHideControllerStore.forDisplay(displayId), + statusBarModeRepository, + statusBarInitializer, + statusBarWindowController, + autoHideController, ) .start() } private fun createAndStartInitializerForDisplay(displayId: Int) { - statusBarInitializerStore.forDisplay(displayId).start() + statusBarInitializerStore.forDisplay(displayId)?.start() } private fun startPrivacyDotForDisplay(displayId: Int) { @@ -111,6 +116,6 @@ constructor( // For the default display, privacy dot is started via ScreenDecorations return } - privacyDotWindowControllerStore.forDisplay(displayId).start() + privacyDotWindowControllerStore.forDisplay(displayId)?.start() } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt index 4c54fc49e536..1e127ee054e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt @@ -20,9 +20,11 @@ import android.view.ViewGroup import androidx.annotation.VisibleForTesting import com.android.systemui.CoreStartable import com.android.systemui.fragments.FragmentHostManager +import com.android.systemui.plugins.DarkIconDispatcher import com.android.systemui.res.R import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewInitializedListener import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewUpdatedListener +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController import com.android.systemui.statusbar.data.repository.StatusBarModePerDisplayRepository import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions import com.android.systemui.statusbar.phone.PhoneStatusBarView @@ -34,7 +36,6 @@ import com.android.systemui.statusbar.window.StatusBarWindowController import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import java.lang.IllegalStateException import javax.inject.Provider /** @@ -75,6 +76,8 @@ interface StatusBarInitializer : CoreStartable { fun create( statusBarWindowController: StatusBarWindowController, statusBarModePerDisplayRepository: StatusBarModePerDisplayRepository, + statusBarConfigurationController: StatusBarConfigurationController, + darkIconDispatcher: DarkIconDispatcher, ): StatusBarInitializer } } @@ -84,6 +87,8 @@ class StatusBarInitializerImpl constructor( @Assisted private val statusBarWindowController: StatusBarWindowController, @Assisted private val statusBarModePerDisplayRepository: StatusBarModePerDisplayRepository, + @Assisted private val statusBarConfigurationController: StatusBarConfigurationController, + @Assisted private val darkIconDispatcher: DarkIconDispatcher, private val collapsedStatusBarFragmentProvider: Provider<CollapsedStatusBarFragment>, private val statusBarRootFactory: StatusBarRootFactory, private val componentFactory: HomeStatusBarComponent.Factory, @@ -131,23 +136,32 @@ constructor( -> val phoneStatusBarView = cv.findViewById<PhoneStatusBarView>(R.id.status_bar) component = - componentFactory.create(phoneStatusBarView).also { component -> - // CollapsedStatusBarFragment used to be responsible initializing - component.init() - - statusBarViewUpdatedListener?.onStatusBarViewUpdated( - component.phoneStatusBarViewController, - component.phoneStatusBarTransitions, + componentFactory + .create( + phoneStatusBarView, + statusBarConfigurationController, + statusBarWindowController, + darkIconDispatcher, ) - - if (StatusBarConnectedDisplays.isEnabled) { - statusBarModePerDisplayRepository.onStatusBarViewInitialized(component) - } else { - creationListeners.forEach { listener -> - listener.onStatusBarViewInitialized(component) + .also { component -> + // CollapsedStatusBarFragment used to be responsible initializing + component.init() + + statusBarViewUpdatedListener?.onStatusBarViewUpdated( + component.phoneStatusBarViewController, + component.phoneStatusBarTransitions, + ) + + if (StatusBarConnectedDisplays.isEnabled) { + statusBarModePerDisplayRepository.onStatusBarViewInitialized( + component + ) + } else { + creationListeners.forEach { listener -> + listener.onStatusBarViewInitialized(component) + } } } - } } // Add the new compose view to the hierarchy because we don't use fragment transactions @@ -163,9 +177,11 @@ constructor( CollapsedStatusBarFragment.TAG, object : FragmentHostManager.FragmentListener { override fun onFragmentViewCreated(tag: String, fragment: Fragment) { - component = - (fragment as CollapsedStatusBarFragment).homeStatusBarComponent - ?: throw IllegalStateException() + val statusBarFragment = fragment as CollapsedStatusBarFragment + if (statusBarFragment.homeStatusBarComponent == null) { + return + } + component = fragment.homeStatusBarComponent statusBarViewUpdatedListener?.onStatusBarViewUpdated( component!!.phoneStatusBarViewController, component!!.phoneStatusBarTransitions, @@ -195,6 +211,8 @@ constructor( override fun create( statusBarWindowController: StatusBarWindowController, statusBarModePerDisplayRepository: StatusBarModePerDisplayRepository, + statusBarConfigurationController: StatusBarConfigurationController, + darkIconDispatcher: DarkIconDispatcher, ): StatusBarInitializerImpl } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializerStore.kt index 4f815c1f0b31..de6cd072afd7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializerStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializerStore.kt @@ -22,6 +22,8 @@ import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.display.data.repository.PerDisplayStore import com.android.systemui.display.data.repository.PerDisplayStoreImpl import com.android.systemui.display.data.repository.SingleDisplayStore +import com.android.systemui.statusbar.data.repository.DarkIconDispatcherStore +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationControllerStore import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore import com.android.systemui.statusbar.window.StatusBarWindowControllerStore import javax.inject.Inject @@ -39,6 +41,8 @@ constructor( private val factory: StatusBarInitializer.Factory, private val statusBarWindowControllerStore: StatusBarWindowControllerStore, private val statusBarModeRepositoryStore: StatusBarModeRepositoryStore, + private val statusBarConfigurationControllerStore: StatusBarConfigurationControllerStore, + private val darkIconDispatcherStore: DarkIconDispatcherStore, ) : StatusBarInitializerStore, PerDisplayStoreImpl<StatusBarInitializer>(backgroundApplicationScope, displayRepository) { @@ -47,10 +51,19 @@ constructor( StatusBarConnectedDisplays.assertInNewMode() } - override fun createInstanceForDisplay(displayId: Int): StatusBarInitializer { + override fun createInstanceForDisplay(displayId: Int): StatusBarInitializer? { + val statusBarWindowController = + statusBarWindowControllerStore.forDisplay(displayId) ?: return null + val statusBarModePerDisplayRepository = + statusBarModeRepositoryStore.forDisplay(displayId) ?: return null + val statusBarConfigurationController = + statusBarConfigurationControllerStore.forDisplay(displayId) ?: return null + val darkIconDispatcher = darkIconDispatcherStore.forDisplay(displayId) ?: return null return factory.create( - statusBarWindowController = statusBarWindowControllerStore.forDisplay(displayId), - statusBarModePerDisplayRepository = statusBarModeRepositoryStore.forDisplay(displayId), + statusBarWindowController, + statusBarModePerDisplayRepository, + statusBarConfigurationController, + darkIconDispatcher, ) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/DarkIconDispatcherStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/DarkIconDispatcherStore.kt index 8183a487cee2..041f3c816149 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/DarkIconDispatcherStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/DarkIconDispatcherStore.kt @@ -65,8 +65,9 @@ constructor( StatusBarConnectedDisplays.assertInNewMode() } - override fun createInstanceForDisplay(displayId: Int): SysuiDarkIconDispatcher { - val properties = displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) + override fun createInstanceForDisplay(displayId: Int): SysuiDarkIconDispatcher? { + val properties = + displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) ?: return null return factory.create(displayId, properties.context) } @@ -103,7 +104,7 @@ constructor(private val store: SysuiDarkIconDispatcherStore) : DarkIconDispatche override val defaultDisplay: DarkIconDispatcher get() = store.defaultDisplay - override fun forDisplay(displayId: Int): DarkIconDispatcher = store.forDisplay(displayId) + override fun forDisplay(displayId: Int): DarkIconDispatcher? = store.forDisplay(displayId) } @Module diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/LightBarControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/LightBarControllerStore.kt index e4987555833b..c629d10b90b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/LightBarControllerStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/LightBarControllerStore.kt @@ -49,13 +49,16 @@ constructor( LightBarControllerStore, PerDisplayStoreImpl<LightBarController>(backgroundApplicationScope, displayRepository) { - override fun createInstanceForDisplay(displayId: Int): LightBarController { + override fun createInstanceForDisplay(displayId: Int): LightBarController? { + val darkIconDispatcher = darkIconDispatcherStore.forDisplay(displayId) ?: return null + val statusBarModePerDisplayRepository = + statusBarModeRepositoryStore.forDisplay(displayId) ?: return null return factory .create( displayId, displayScopeRepository.scopeForDisplay(displayId), - darkIconDispatcherStore.forDisplay(displayId), - statusBarModeRepositoryStore.forDisplay(displayId), + darkIconDispatcher, + statusBarModePerDisplayRepository, ) .also { it.start() } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/PrivacyDotViewControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/PrivacyDotViewControllerStore.kt index bd61c44e3d9b..d48c94bd0893 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/PrivacyDotViewControllerStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/PrivacyDotViewControllerStore.kt @@ -52,11 +52,14 @@ constructor( PrivacyDotViewControllerStore, PerDisplayStoreImpl<PrivacyDotViewController>(backgroundApplicationScope, displayRepository) { - override fun createInstanceForDisplay(displayId: Int): PrivacyDotViewController { + override fun createInstanceForDisplay(displayId: Int): PrivacyDotViewController? { + val configurationController = + statusBarConfigurationControllerStore.forDisplay(displayId) ?: return null + val contentInsetsProvider = contentInsetsProviderStore.forDisplay(displayId) ?: return null return factory.create( displayScopeRepository.scopeForDisplay(displayId), - statusBarConfigurationControllerStore.forDisplay(displayId), - contentInsetsProviderStore.forDisplay(displayId), + configurationController, + contentInsetsProvider, ) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/PrivacyDotWindowControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/PrivacyDotWindowControllerStore.kt index a1f56552629b..086cc99957ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/PrivacyDotWindowControllerStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/PrivacyDotWindowControllerStore.kt @@ -58,15 +58,18 @@ constructor( StatusBarConnectedDisplays.assertInNewMode() } - override fun createInstanceForDisplay(displayId: Int): PrivacyDotWindowController { + override fun createInstanceForDisplay(displayId: Int): PrivacyDotWindowController? { if (displayId == Display.DEFAULT_DISPLAY) { throw IllegalArgumentException("This class should only be used for connected displays") } val displayWindowProperties = displayWindowPropertiesRepository.get(displayId, TYPE_NAVIGATION_BAR_PANEL) + ?: return null + val privacyDotViewController = + privacyDotViewControllerStore.forDisplay(displayId) ?: return null return windowControllerFactory.create( displayId = displayId, - privacyDotViewController = privacyDotViewControllerStore.forDisplay(displayId), + privacyDotViewController = privacyDotViewController, viewCaptureAwareWindowManager = viewCaptureAwareWindowManagerFactory.create(displayWindowProperties.windowManager), inflater = displayWindowProperties.layoutInflater, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarConfigurationControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarConfigurationControllerStore.kt index 6cf2c73a7138..38cea832ad76 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarConfigurationControllerStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarConfigurationControllerStore.kt @@ -62,9 +62,9 @@ constructor( StatusBarConnectedDisplays.assertInNewMode() } - override fun createInstanceForDisplay(displayId: Int): StatusBarConfigurationController { + override fun createInstanceForDisplay(displayId: Int): StatusBarConfigurationController? { val displayWindowProperties = - displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) + displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) ?: return null return configurationControllerFactory.create(displayWindowProperties.context) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarContentInsetsProviderStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarContentInsetsProviderStore.kt index e471b12c1d58..554c46f6c219 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarContentInsetsProviderStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarContentInsetsProviderStore.kt @@ -59,13 +59,17 @@ constructor( displayRepository, ) { - override fun createInstanceForDisplay(displayId: Int): StatusBarContentInsetsProvider { - val context = displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR).context + override fun createInstanceForDisplay(displayId: Int): StatusBarContentInsetsProvider? { + val displayWindowProperties = + displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) ?: return null + val context = displayWindowProperties.context + val configurationController = + statusBarConfigurationControllerStore.forDisplay(displayId) ?: return null val cameraProtectionLoader = cameraProtectionLoaderFactory.create(context) return factory .create( context, - statusBarConfigurationControllerStore.forDisplay(displayId), + configurationController, sysUICutoutProviderFactory.create(context, cameraProtectionLoader), ) .also { it.start() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStore.kt index 7760f58805c9..ffc125539521 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/SystemEventChipAnimationControllerStore.kt @@ -62,11 +62,17 @@ constructor( StatusBarConnectedDisplays.assertInNewMode() } - override fun createInstanceForDisplay(displayId: Int): SystemEventChipAnimationController { + override fun createInstanceForDisplay(displayId: Int): SystemEventChipAnimationController? { + val displayWindowProperties = + displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) ?: return null + val statusBarWindowController = + statusBarWindowControllerStore.forDisplay(displayId) ?: return null + val contentInsetsProvider = + statusBarContentInsetsProviderStore.forDisplay(displayId) ?: return null return factory.create( - displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR).context, - statusBarWindowControllerStore.forDisplay(displayId), - statusBarContentInsetsProviderStore.forDisplay(displayId), + displayWindowProperties.context, + statusBarWindowController, + contentInsetsProvider, ) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/MultiDisplaySystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/MultiDisplaySystemEventChipAnimationController.kt index f2bb7b16439d..4b9721ea4fe5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/MultiDisplaySystemEventChipAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/MultiDisplaySystemEventChipAnimationController.kt @@ -72,5 +72,5 @@ constructor( } private fun controllersForAllDisplays() = - displayRepository.displays.value.map { controllerStore.forDisplay(it.displayId) } + displayRepository.displays.value.mapNotNull { controllerStore.forDisplay(it.displayId) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotWindowController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotWindowController.kt index 9928ac67f185..f7799bb75ae0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotWindowController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotWindowController.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.events +import android.util.Log import android.view.Display import android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM import android.view.DisplayCutout.BOUNDS_POSITION_LEFT @@ -23,6 +24,7 @@ import android.view.DisplayCutout.BOUNDS_POSITION_RIGHT import android.view.DisplayCutout.BOUNDS_POSITION_TOP import android.view.LayoutInflater import android.view.View +import android.view.WindowManager.InvalidDisplayException import android.view.WindowManager.LayoutParams.WRAP_CONTENT import android.widget.FrameLayout import com.android.app.viewcapture.ViewCaptureAwareWindowManager @@ -97,7 +99,17 @@ constructor( // PrivacyDotViewController expects the dot view to have a FrameLayout parent. val rootView = FrameLayout(context) rootView.addView(this) - viewCaptureAwareWindowManager.addView(rootView, params) + try { + // Wrapping this in a try/catch to avoid crashes when a display is instantly removed + // after being added, and initialization hasn't finished yet. + viewCaptureAwareWindowManager.addView(rootView, params) + } catch (e: InvalidDisplayException) { + Log.e( + TAG, + "Unable to add view to WM. Display with id $displayId does not exist anymore", + e, + ) + } } @AssistedFactory @@ -109,4 +121,8 @@ constructor( inflater: LayoutInflater, ): PrivacyDotWindowController } + + private companion object { + const val TAG = "PrivacyDotWindowController" + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/ConnectedDisplaysStatusBarNotificationIconViewStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/ConnectedDisplaysStatusBarNotificationIconViewStore.kt index 227a1fefb982..eb55856d994b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/ConnectedDisplaysStatusBarNotificationIconViewStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/ConnectedDisplaysStatusBarNotificationIconViewStore.kt @@ -62,8 +62,10 @@ constructor( override fun iconView(key: String): StatusBarIconView? { val entry = notifCollection.getEntry(key) ?: return null + val displayWindowProperties = + displayWindowPropertiesInteractor.getForStatusBar(displayId) ?: return null return cachedIcons.computeIfAbsent(key) { - val context = displayWindowPropertiesInteractor.getForStatusBar(displayId).context + val context = displayWindowProperties.context iconManager.createSbIconView(context, entry) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt index 2ba28a660116..e1032820fb71 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt @@ -68,13 +68,14 @@ constructor( .distinctUntilChanged() /** The colors with which to display the notification icons. */ - fun iconColors(displayId: Int): Flow<NotificationIconColors> = - darkIconInteractor + fun iconColors(displayId: Int): Flow<NotificationIconColors> { + return darkIconInteractor .darkState(displayId) .map { (areas: Collection<Rect>, tint: Int) -> IconColorsImpl(tint, areas) } .flowOn(bgContext) .conflate() .distinctUntilChanged() + } /** [NotificationIconsViewData] indicating which icons to display in the view. */ val icons: Flow<NotificationIconsViewData> = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt index 744f96918eef..2ae38dd488bd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt @@ -47,9 +47,9 @@ constructor( StatusBarConnectedDisplays.assertInNewMode() } - override fun createInstanceForDisplay(displayId: Int): AutoHideController { + override fun createInstanceForDisplay(displayId: Int): AutoHideController? { val displayWindowProperties = - displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) + displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) ?: return null return autoHideControllerFactory.create(displayWindowProperties.context) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarControllerImpl.java index ea67f1cdb60a..ca0c1ac9ce7c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarControllerImpl.java @@ -499,9 +499,9 @@ public class LightBarControllerImpl implements /** Creates a {@link LightBarControllerImpl}. */ LightBarControllerImpl create( int displayId, - CoroutineScope coroutineScope, - DarkIconDispatcher darkIconDispatcher, - StatusBarModePerDisplayRepository statusBarModePerDisplayRepository); + @NonNull CoroutineScope coroutineScope, + @NonNull DarkIconDispatcher darkIconDispatcher, + @NonNull StatusBarModePerDisplayRepository statusBarModePerDisplayRepository); } public static class LegacyFactory implements LightBarController.Factory { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusOverlayHoverListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusOverlayHoverListener.kt index 394502b2d31f..031754db3c57 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusOverlayHoverListener.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusOverlayHoverListener.kt @@ -33,6 +33,7 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.DarkIconDispatcher import com.android.systemui.res.R +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController import com.android.systemui.statusbar.data.repository.StatusBarConfigurationControllerStore import com.android.systemui.statusbar.data.repository.SysuiDarkIconDispatcherStore import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange @@ -54,7 +55,7 @@ constructor( ) { /** Creates listener always using the same light color for overlay */ - fun createListener(view: View) = + fun createListener(view: View): StatusOverlayHoverListener = StatusOverlayHoverListener( view, configurationController, @@ -65,8 +66,10 @@ constructor( /** * Creates listener using [DarkIconDispatcher] to determine light or dark color of the overlay */ - fun createDarkAwareListener(view: View) = - createDarkAwareListener(view, view.darkIconDispatcher.darkChangeFlow()) + fun createDarkAwareListener(view: View): StatusOverlayHoverListener? { + val darkIconDispatcher = view.darkIconDispatcher ?: return null + return createDarkAwareListener(view, darkIconDispatcher.darkChangeFlow()) + } /** * Creates listener using [DarkIconDispatcher] to determine light or dark color of the overlay @@ -78,27 +81,34 @@ constructor( rightHoverMargin: Int = 0, topHoverMargin: Int = 0, bottomHoverMargin: Int = 0, - ) = - createDarkAwareListener( + ): StatusOverlayHoverListener? { + val darkIconDispatcher = view.darkIconDispatcher ?: return null + return createDarkAwareListener( view, - view.darkIconDispatcher.darkChangeFlow(), + darkIconDispatcher.darkChangeFlow(), leftHoverMargin, rightHoverMargin, topHoverMargin, bottomHoverMargin, ) + } /** * Creates listener using provided [DarkChange] producer to determine light or dark color of the * overlay */ - fun createDarkAwareListener(view: View, darkFlow: StateFlow<DarkChange>) = - StatusOverlayHoverListener( + fun createDarkAwareListener( + view: View, + darkFlow: StateFlow<DarkChange>, + ): StatusOverlayHoverListener? { + val configurationController = view.statusBarConfigurationController ?: return null + return StatusOverlayHoverListener( view, - view.statusBarConfigurationController, + configurationController, view.resources, darkFlow.map { toHoverTheme(view, it) }, ) + } private fun createDarkAwareListener( view: View, @@ -107,10 +117,11 @@ constructor( rightHoverMargin: Int = 0, topHoverMargin: Int = 0, bottomHoverMargin: Int = 0, - ) = - StatusOverlayHoverListener( + ): StatusOverlayHoverListener? { + val configurationController = view.statusBarConfigurationController ?: return null + return StatusOverlayHoverListener( view, - view.statusBarConfigurationController, + configurationController, view.resources, darkFlow.map { toHoverTheme(view, it) }, leftHoverMargin, @@ -118,11 +129,12 @@ constructor( topHoverMargin, bottomHoverMargin, ) + } - private val View.statusBarConfigurationController + private val View.statusBarConfigurationController: StatusBarConfigurationController? get() = statusBarConfigurationControllerStore.forDisplay(context.displayId) - private val View.darkIconDispatcher + private val View.darkIconDispatcher: SysuiDarkIconDispatcher? get() = darkIconDispatcherStore.forDisplay(context.displayId) private fun toHoverTheme(view: View, darkChange: DarkChange): HoverTheme { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt index 4f32aaa2654e..037dda91fb00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt @@ -31,8 +31,10 @@ import com.android.systemui.statusbar.core.StatusBarInitializerImpl import com.android.systemui.statusbar.core.StatusBarInitializerStore import com.android.systemui.statusbar.core.StatusBarOrchestrator import com.android.systemui.statusbar.core.StatusBarRootModernization +import com.android.systemui.statusbar.data.repository.DarkIconDispatcherStore import com.android.systemui.statusbar.data.repository.PrivacyDotViewControllerStoreModule import com.android.systemui.statusbar.data.repository.PrivacyDotWindowControllerStoreModule +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationControllerStore import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore import com.android.systemui.statusbar.events.PrivacyDotViewControllerModule import com.android.systemui.statusbar.phone.AutoHideControllerStore @@ -107,10 +109,14 @@ interface StatusBarPhoneModule { implFactory: StatusBarInitializerImpl.Factory, statusBarWindowControllerStore: StatusBarWindowControllerStore, statusBarModeRepositoryStore: StatusBarModeRepositoryStore, + statusBarConfigurationControllerStore: StatusBarConfigurationControllerStore, + darkIconDispatcherStore: DarkIconDispatcherStore, ): StatusBarInitializerImpl { return implFactory.create( statusBarWindowControllerStore.defaultDisplay, statusBarModeRepositoryStore.defaultDisplay, + statusBarConfigurationControllerStore.defaultDisplay, + darkIconDispatcherStore.defaultDisplay, ) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/data/repository/DarkIconRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/data/repository/DarkIconRepository.kt index 49356eba2842..04646549bfdc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/data/repository/DarkIconRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/data/repository/DarkIconRepository.kt @@ -15,12 +15,14 @@ */ package com.android.systemui.statusbar.phone.data.repository +import android.util.Log import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.data.repository.SysuiDarkIconDispatcherStore import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange import dagger.Binds import dagger.Module import javax.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow /** Dark-mode state for tinting icons. */ @@ -33,8 +35,22 @@ class DarkIconRepositoryImpl @Inject constructor(private val darkIconDispatcherStore: SysuiDarkIconDispatcherStore) : DarkIconRepository { - override fun darkState(displayId: Int): StateFlow<DarkChange> = - darkIconDispatcherStore.forDisplay(displayId).darkChangeFlow() + override fun darkState(displayId: Int): StateFlow<DarkChange> { + val perDisplayDakIconDispatcher = darkIconDispatcherStore.forDisplay(displayId) + if (perDisplayDakIconDispatcher == null) { + Log.e( + TAG, + "DarkIconDispatcher for display $displayId is null. Returning flow of " + + "DarkChange.EMPTY", + ) + return MutableStateFlow(DarkChange.EMPTY) + } + return perDisplayDakIconDispatcher.darkChangeFlow() + } + + private companion object { + const val TAG = "DarkIconRepositoryImpl" + } } @Module diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractor.kt index ed8b3e8922f3..b15fffb8dd29 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractor.kt @@ -34,8 +34,8 @@ class LightsOutInteractor @Inject constructor(private val repository: StatusBarModeRepositoryStore) { - fun isLowProfile(displayId: Int): Flow<Boolean> = - repository.forDisplay(displayId).statusBarMode.map { + fun isLowProfile(displayId: Int): Flow<Boolean>? = + repository.forDisplay(displayId)?.statusBarMode?.map { when (it) { StatusBarMode.LIGHTS_OUT, StatusBarMode.LIGHTS_OUT_TRANSPARENT -> true diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index d257288637df..c31e34c50b06 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -47,6 +47,7 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.demomode.DemoMode; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; +import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.res.R; import com.android.systemui.scene.shared.flag.SceneContainerFlag; @@ -59,6 +60,9 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips; import com.android.systemui.statusbar.core.StatusBarConnectedDisplays; import com.android.systemui.statusbar.core.StatusBarRootModernization; +import com.android.systemui.statusbar.data.repository.DarkIconDispatcherStore; +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController; +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationControllerStore; import com.android.systemui.statusbar.disableflags.DisableFlagsLogger; import com.android.systemui.statusbar.events.SystemStatusAnimationCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; @@ -78,6 +82,8 @@ import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarVie import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener; import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.window.StatusBarWindowController; +import com.android.systemui.statusbar.window.StatusBarWindowControllerStore; import com.android.systemui.statusbar.window.StatusBarWindowStateController; import com.android.systemui.statusbar.window.StatusBarWindowStateListener; import com.android.systemui.util.CarrierConfigTracker; @@ -156,6 +162,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final NotificationIconContainerStatusBarViewBinder mNicViewBinder; private final DemoModeController mDemoModeController; + private final StatusBarWindowControllerStore mStatusBarWindowControllerStore; + private final StatusBarConfigurationControllerStore mStatusBarConfigurationControllerStore; + private final DarkIconDispatcherStore mDarkIconDispatcherStore; private List<String> mBlockedIcons = new ArrayList<>(); private Map<Startable, Startable.State> mStartableStates = new ArrayMap<>(); @@ -263,7 +272,10 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue DumpManager dumpManager, StatusBarWindowStateController statusBarWindowStateController, KeyguardUpdateMonitor keyguardUpdateMonitor, - DemoModeController demoModeController) { + DemoModeController demoModeController, + StatusBarWindowControllerStore statusBarWindowControllerStore, + StatusBarConfigurationControllerStore statusBarConfigurationControllerStore, + DarkIconDispatcherStore darkIconDispatcherStore) { mHomeStatusBarComponentFactory = homeStatusBarComponentFactory; mOngoingCallController = ongoingCallController; mAnimationScheduler = animationScheduler; @@ -287,6 +299,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mStatusBarWindowStateController = statusBarWindowStateController; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mDemoModeController = demoModeController; + mStatusBarWindowControllerStore = statusBarWindowControllerStore; + mStatusBarConfigurationControllerStore = statusBarConfigurationControllerStore; + mDarkIconDispatcherStore = darkIconDispatcherStore; } private final DemoMode mDemoModeCallback = new DemoMode() { @@ -337,8 +352,27 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mDumpManager.registerDumpable(getDumpableName(), this); - mHomeStatusBarComponent = mHomeStatusBarComponentFactory.create( - (PhoneStatusBarView) getView()); + int displayId = view.getContext().getDisplayId(); + StatusBarConfigurationController configurationController = + mStatusBarConfigurationControllerStore.forDisplay(displayId); + if (configurationController == null) { + return; + } + StatusBarWindowController statusBarWindowController = + mStatusBarWindowControllerStore.forDisplay(displayId); + if (statusBarWindowController == null) { + return; + } + DarkIconDispatcher darkIconDispatcher = mDarkIconDispatcherStore.forDisplay(displayId); + if (darkIconDispatcher == null) { + return; + } + mHomeStatusBarComponent = + mHomeStatusBarComponentFactory.create( + (PhoneStatusBarView) getView(), + configurationController, + statusBarWindowController, + darkIconDispatcher); mHomeStatusBarComponent.init(); mStartableStates.clear(); for (Startable startable : mHomeStatusBarComponent.getStartables()) { @@ -453,6 +487,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue @Override public void onResume() { super.onResume(); + if (mHomeStatusBarComponent == null) { + return; + } mCommandQueue.addCallback(this); mStatusBarStateController.addCallback(this); initOngoingCallChip(); @@ -468,6 +505,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue @Override public void onPause() { super.onPause(); + if (mHomeStatusBarComponent == null) { + return; + } mCommandQueue.removeCallback(this); mStatusBarStateController.removeCallback(this); if (!StatusBarRootModernization.isEnabled()) { @@ -480,6 +520,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue @Override public void onDestroyView() { super.onDestroyView(); + if (mHomeStatusBarComponent == null) { + return; + } mStatusBarIconController.removeIconGroup(mDarkIconManager); mCarrierConfigTracker.removeCallback(mCarrierConfigCallback); mCarrierConfigTracker.removeDataSubscriptionChangedListener(mDefaultDataListener); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarComponent.java index f8ad0f2324bc..5837752abdaf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarComponent.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarComponent.java @@ -20,6 +20,7 @@ import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.dagger.qualifiers.DisplaySpecific; import com.android.systemui.dagger.qualifiers.RootView; import com.android.systemui.plugins.DarkIconDispatcher; +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController; import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor; import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.LegacyLightsOutNotifController; @@ -29,6 +30,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarViewController; import com.android.systemui.statusbar.phone.StatusBarBoundsProvider; import com.android.systemui.statusbar.phone.StatusBarDemoMode; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; +import com.android.systemui.statusbar.window.StatusBarWindowController; import dagger.BindsInstance; import dagger.Subcomponent; @@ -57,7 +59,10 @@ public interface HomeStatusBarComponent { interface Factory { /** */ HomeStatusBarComponent create( - @BindsInstance @RootView PhoneStatusBarView phoneStatusBarView); + @BindsInstance @RootView PhoneStatusBarView phoneStatusBarView, + @BindsInstance StatusBarConfigurationController configurationController, + @BindsInstance StatusBarWindowController statusBarWindowController, + @BindsInstance @DisplaySpecific DarkIconDispatcher darkIconDispatcher); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarModule.java index 182f8d7e2fd6..6a331b938cf1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/HomeStatusBarModule.java @@ -22,19 +22,14 @@ import android.view.ViewStub; import com.android.systemui.battery.BatteryMeterView; import com.android.systemui.dagger.qualifiers.DisplaySpecific; import com.android.systemui.dagger.qualifiers.RootView; -import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.res.R; import com.android.systemui.statusbar.HeadsUpStatusBarView; -import com.android.systemui.statusbar.data.repository.DarkIconDispatcherStore; -import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController; -import com.android.systemui.statusbar.data.repository.StatusBarConfigurationControllerStore; import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.PhoneStatusBarViewController; import com.android.systemui.statusbar.phone.StatusBarLocation; import com.android.systemui.statusbar.policy.Clock; import com.android.systemui.statusbar.window.StatusBarWindowController; -import com.android.systemui.statusbar.window.StatusBarWindowControllerStore; import dagger.Module; import dagger.Provides; @@ -149,29 +144,4 @@ public interface HomeStatusBarModule { static int displayId(@RootView PhoneStatusBarView view) { return view.getContext().getDisplayId(); } - - /** */ - @Provides - @HomeStatusBarScope - static StatusBarConfigurationController configurationController( - @DisplaySpecific int displayId, StatusBarConfigurationControllerStore store) { - return store.forDisplay(displayId); - } - - /** */ - @Provides - @HomeStatusBarScope - static StatusBarWindowController provideWindowController( - @DisplaySpecific int displayId, StatusBarWindowControllerStore store) { - return store.forDisplay(displayId); - } - - /** */ - @Provides - @HomeStatusBarScope - @DisplaySpecific - static DarkIconDispatcher darkIconDispatcher( - @DisplaySpecific int displayId, DarkIconDispatcherStore store) { - return store.forDisplay(displayId); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt index c3299bbd40e6..7243ba7def58 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt @@ -70,6 +70,8 @@ constructor( ) { fun create(root: ViewGroup, andThen: (ViewGroup) -> Unit): ComposeView { val composeView = ComposeView(root.context) + val darkIconDispatcher = + darkIconDispatcherStore.forDisplay(root.context.displayId) ?: return composeView composeView.apply { setContent { StatusBarRoot( @@ -80,7 +82,7 @@ constructor( darkIconManagerFactory = darkIconManagerFactory, iconController = iconController, ongoingCallController = ongoingCallController, - darkIconDispatcher = darkIconDispatcherStore.forDisplay(root.context.displayId), + darkIconDispatcher = darkIconDispatcher, eventAnimationInteractor = eventAnimationInteractor, onViewCreated = andThen, ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt index dcfbc5d6432d..c9cc17389c17 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt @@ -63,6 +63,7 @@ import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @@ -216,7 +217,7 @@ constructor( } else { combine( notificationsInteractor.areAnyNotificationsPresent, - lightsOutInteractor.isLowProfile(displayId), + lightsOutInteractor.isLowProfile(displayId) ?: flowOf(false), ) { hasNotifications, isLowProfile -> hasNotifications && isLowProfile } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java index 811a2ec44ccc..848e91d6f896 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java @@ -163,7 +163,18 @@ public class StatusBarWindowControllerImpl implements StatusBarWindowController mLp = getBarLayoutParams(mContext.getDisplay().getRotation()); Trace.endSection(); - mWindowManager.addView(mStatusBarWindowView, mLp); + try { + mWindowManager.addView(mStatusBarWindowView, mLp); + } catch (WindowManager.InvalidDisplayException e) { + // Wrapping this in a try/catch to avoid crashes when a display is instantly removed + // after being added, and initialization hasn't finished yet. + Log.e( + TAG, + "Unable to add view to WindowManager. Display with id " + + mContext.getDisplayId() + + " doesn't exist anymore.", + e); + } mLpChanged.copyFrom(mLp); mContentInsetsProvider.addCallback(this::calculateStatusBarLocationsForAllRotations); @@ -176,7 +187,15 @@ public class StatusBarWindowControllerImpl implements StatusBarWindowController public void stop() { StatusBarConnectedDisplays.assertInNewMode(); - mWindowManager.removeView(mStatusBarWindowView); + try { + mWindowManager.removeView(mStatusBarWindowView); + } catch (IllegalArgumentException e) { + // Wrapping this in a try/catch to avoid crashes when a display is instantly removed + // after being added, and initialization hasn't finished yet. + // When that happens, adding the View to WindowManager fails, and therefore removing + // it here will fail too, since it wasn't added in the first place. + Log.e(TAG, "Failed to remove View from WindowManager. View was not attached", e); + } if (StatusBarRootModernization.isEnabled()) { return; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerStore.kt index 74031612f28e..f7688d2feab5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerStore.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerStore.kt @@ -54,19 +54,23 @@ constructor( StatusBarConnectedDisplays.assertInNewMode() } - override fun createInstanceForDisplay(displayId: Int): StatusBarWindowController { + override fun createInstanceForDisplay(displayId: Int): StatusBarWindowController? { val statusBarDisplayContext = displayWindowPropertiesRepository.get( displayId = displayId, windowType = WindowManager.LayoutParams.TYPE_STATUS_BAR, - ) + ) ?: return null + val statusBarConfigurationController = + statusBarConfigurationControllerStore.forDisplay(displayId) ?: return null + val contentInsetsProvider = + statusBarContentInsetsProviderStore.forDisplay(displayId) ?: return null val viewCaptureAwareWindowManager = viewCaptureAwareWindowManagerFactory.create(statusBarDisplayContext.windowManager) return controllerFactory.create( statusBarDisplayContext.context, viewCaptureAwareWindowManager, - statusBarConfigurationControllerStore.forDisplay(displayId), - statusBarContentInsetsProviderStore.forDisplay(displayId), + statusBarConfigurationController, + contentInsetsProvider, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 411c81d13e0b..1fcf02d417e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -36,6 +36,8 @@ import static com.android.systemui.statusbar.phone.CentralSurfaces.MSG_DISMISS_K import static com.google.common.truth.Truth.assertThat; +import static kotlinx.coroutines.flow.FlowKt.flowOf; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; @@ -54,8 +56,6 @@ import static org.mockito.Mockito.when; import static java.util.Collections.emptySet; -import static kotlinx.coroutines.flow.FlowKt.flowOf; - import android.app.ActivityManager; import android.app.IWallpaperManager; import android.app.NotificationManager; @@ -132,6 +132,7 @@ import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.notetask.NoteTaskController; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.ActivityStarter.OnDismissAction; +import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.PluginDependencyProvider; import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -175,6 +176,7 @@ import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.core.StatusBarConnectedDisplays; import com.android.systemui.statusbar.core.StatusBarInitializerImpl; import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository; +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController; import com.android.systemui.statusbar.data.repository.StatusBarModePerDisplayRepository; import com.android.systemui.statusbar.notification.NotifPipelineFlags; import com.android.systemui.statusbar.notification.NotificationActivityStarter; @@ -216,6 +218,10 @@ import com.android.systemui.volume.VolumeComponent; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.startingsurface.StartingSurface; +import dagger.Lazy; + +import kotlinx.coroutines.test.TestScope; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -232,9 +238,6 @@ import java.util.Set; import javax.inject.Provider; -import dagger.Lazy; -import kotlinx.coroutines.test.TestScope; - @SmallTest @RunWith(AndroidJUnit4.class) @RunWithLooper(setAsMainLooper = true) @@ -536,6 +539,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase { new StatusBarInitializerImpl( mStatusBarWindowController, mStatusBarModePerDisplayRepository, + mock(StatusBarConfigurationController.class), + mock(DarkIconDispatcher.class), mCollapsedStatusBarFragmentProvider, mock(StatusBarRootFactory.class), mock(HomeStatusBarComponent.Factory.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index 0b4436755fa5..3a99328fa8ed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -61,6 +62,9 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.OperatorNameViewController; import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips; import com.android.systemui.statusbar.core.StatusBarRootModernization; +import com.android.systemui.statusbar.data.repository.DarkIconDispatcherStore; +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController; +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationControllerStore; import com.android.systemui.statusbar.disableflags.DisableFlagsLogger; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder; @@ -75,6 +79,8 @@ import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeHomeStatu import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeHomeStatusBarViewModel; import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.StatusBarOperatorNameViewModel; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.window.StatusBarWindowController; +import com.android.systemui.statusbar.window.StatusBarWindowControllerStore; import com.android.systemui.statusbar.window.StatusBarWindowStateController; import com.android.systemui.statusbar.window.StatusBarWindowStateListener; import com.android.systemui.util.CarrierConfigTracker; @@ -134,6 +140,12 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { private StatusBarWindowStateController mStatusBarWindowStateController; @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock private StatusBarWindowControllerStore mStatusBarWindowControllerStore; + @Mock private StatusBarWindowController mStatusBarWindowController; + @Mock private StatusBarConfigurationControllerStore mStatusBarConfigurationControllerStore; + @Mock private StatusBarConfigurationController mStatusBarConfigurationController; + @Mock private DarkIconDispatcherStore mDarkIconDispatcherStore; + @Mock private DarkIconDispatcher mDarkIconDispatcher; @Rule public final AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule(this); @@ -145,6 +157,12 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { @Before public void setup() { + when(mStatusBarWindowControllerStore.forDisplay(anyInt())) + .thenReturn(mStatusBarWindowController); + when(mStatusBarConfigurationControllerStore.forDisplay(anyInt())) + .thenReturn(mStatusBarConfigurationController); + when(mDarkIconDispatcherStore.forDisplay(anyInt())).thenReturn(mDarkIconDispatcher); + injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); mDependency.injectMockDependency(DarkIconDispatcher.class); @@ -1276,11 +1294,14 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { mDumpManager, mStatusBarWindowStateController, mKeyguardUpdateMonitor, - mock(DemoModeController.class)); + mock(DemoModeController.class), + mStatusBarWindowControllerStore, + mStatusBarConfigurationControllerStore, + mDarkIconDispatcherStore); } private void setUpDaggerComponent() { - when(mStatusBarFragmentComponentFactory.create(any())) + when(mStatusBarFragmentComponentFactory.create(any(), any(), any(), any())) .thenReturn(mHomeStatusBarComponent); when(mHomeStatusBarComponent.getHeadsUpAppearanceController()) .thenReturn(mHeadsUpAppearanceController); diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java index b8be6aa50015..64d89c5ac8ba 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java @@ -81,6 +81,14 @@ public class SysuiTestableContext extends TestableContext { return super.getDisplay(); } + @Override + public int getDisplayId() { + if (mCustomDisplay != null) { + return mCustomDisplay.getDisplayId(); + } + return super.getDisplayId(); + } + public SysuiTestableContext createDefaultDisplayContext() { Display display = getBaseContext().getSystemService(DisplayManager.class).getDisplays()[0]; return (SysuiTestableContext) createDisplayContext(display); diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/FakeStatusBarInitializerFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/FakeStatusBarInitializerFactory.kt index 50a19a9bc68a..fb2e2a3b76a9 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/FakeStatusBarInitializerFactory.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/FakeStatusBarInitializerFactory.kt @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.core +import com.android.systemui.plugins.DarkIconDispatcher +import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController import com.android.systemui.statusbar.data.repository.StatusBarModePerDisplayRepository import com.android.systemui.statusbar.window.StatusBarWindowController @@ -24,5 +26,7 @@ class FakeStatusBarInitializerFactory() : StatusBarInitializer.Factory { override fun create( statusBarWindowController: StatusBarWindowController, statusBarModePerDisplayRepository: StatusBarModePerDisplayRepository, + statusBarConfigurationController: StatusBarConfigurationController, + darkIconDispatcher: DarkIconDispatcher, ): StatusBarInitializer = FakeStatusBarInitializer() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/StatusBarInitializerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/StatusBarInitializerKosmos.kt index 6e990277df6b..b8dafb23b206 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/StatusBarInitializerKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/core/StatusBarInitializerKosmos.kt @@ -19,7 +19,9 @@ package com.android.systemui.statusbar.core import com.android.systemui.display.data.repository.displayRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.statusbar.data.repository.darkIconDispatcherStore import com.android.systemui.statusbar.data.repository.fakeStatusBarModeRepository +import com.android.systemui.statusbar.data.repository.statusBarConfigurationControllerStore import com.android.systemui.statusbar.window.fakeStatusBarWindowControllerStore val Kosmos.fakeStatusBarInitializer by Kosmos.Fixture { FakeStatusBarInitializer() } @@ -39,6 +41,8 @@ val Kosmos.multiDisplayStatusBarInitializerStore by fakeStatusBarInitializerFactory, fakeStatusBarWindowControllerStore, fakeStatusBarModeRepository, + statusBarConfigurationControllerStore, + darkIconDispatcherStore, ) } |