Loading packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayComponentPerDisplayRepositoryTest.kt 0 → 100644 +59 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.display.data.repository import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.isActive import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @SmallTest class DisplayComponentPerDisplayRepositoryTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val testScope = kosmos.testScope private val underTest = DisplayComponentInstanceProvider(kosmos.fakeSysuiDisplayComponentFactory) @Test fun createInstance_activeByDefault() = testScope.runTest { val scopeForDisplay = underTest.createInstance(displayId = 1)!!.displayCoroutineScope assertThat(scopeForDisplay.isActive).isTrue() } @Test fun destroyInstance_afterDisplayRemoved_scopeIsCancelled() = testScope.runTest { val component = underTest.createInstance(displayId = 1) val scope = component!!.displayCoroutineScope underTest.destroyInstance(component) assertThat(scope.isActive).isFalse() } } packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayScopeRepositoryInstanceProviderTest.kt +11 −8 Original line number Diff line number Diff line Loading @@ -16,11 +16,11 @@ package com.android.systemui.display.data.repository import android.view.Display import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos Loading @@ -36,28 +36,31 @@ class DisplayScopeRepositoryInstanceProviderTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val testScope = kosmos.testScope private val displaySubcomponentRepository = kosmos.displaySubcomponentPerDisplayRepository private val underTest = DisplayScopeRepositoryInstanceProvider( kosmos.applicationCoroutineScope, kosmos.testDispatcher, displaySubcomponentRepository, ) @Test fun createInstance_activeByDefault() = testScope.runTest { val scopeForDisplay = underTest.createInstance(displayId = 1) displaySubcomponentRepository.add(displayId = 1, kosmos.createFakeDisplaySubcomponent()) val scopeForDisplay = underTest.createInstance(displayId = 1)!! assertThat(scopeForDisplay.isActive).isTrue() } @Test fun destroyInstance_afterDisplayRemoved_scopeIsCancelled() = fun createInstance_forDefaultDisplay_returnsConstructorParam() = testScope.runTest { val scopeForDisplay = underTest.createInstance(displayId = 1) val scopeForDisplay = underTest.createInstance(displayId = Display.DEFAULT_DISPLAY)!! underTest.destroyInstance(scopeForDisplay) assertThat(scopeForDisplay.isActive).isFalse() assertThat(scopeForDisplay).isEqualTo(kosmos.applicationCoroutineScope) } // no test for destruction, as it's not handled by this class. The scope is meant to be // destroyed by the PerDisplayRepository<SystemUIDisplaySubcomponent> } packages/SystemUI/src/com/android/systemui/dagger/PerDisplayRepositoriesModule.kt +4 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.dagger import com.android.app.displaylib.DefaultDisplayOnlyInstanceRepositoryImpl import com.android.app.displaylib.PerDisplayInstanceRepositoryImpl import com.android.app.displaylib.PerDisplayRepository import com.android.systemui.display.data.repository.DisplayComponentRepository import com.android.systemui.display.data.repository.PerDisplayCoroutineScopeRepositoryModule import com.android.systemui.model.SysUIStateInstanceProvider import com.android.systemui.model.SysUiState Loading @@ -27,7 +28,9 @@ import dagger.Module import dagger.Provides /** This module is meant to contain all the code to create the various [PerDisplayRepository<>]. */ @Module(includes = [PerDisplayCoroutineScopeRepositoryModule::class]) @Module( includes = [PerDisplayCoroutineScopeRepositoryModule::class, DisplayComponentRepository::class] ) class PerDisplayRepositoriesModule { @SysUISingleton Loading packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +2 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import com.android.systemui.demomode.dagger.DemoModeModule; import com.android.systemui.deviceentry.DeviceEntryModule; import com.android.systemui.display.DisplayModule; import com.android.app.displaylib.PerDisplayRepository; import com.android.systemui.display.dagger.SystemUIDisplaySubcomponent; import com.android.systemui.doze.dagger.DozeComponent; import com.android.systemui.dreams.dagger.DreamModule; import com.android.systemui.flags.FeatureFlags; Loading Loading @@ -299,6 +300,7 @@ import javax.inject.Named; NavigationBarComponent.class, NotificationRowComponent.class, WindowRootViewComponent.class, SystemUIDisplaySubcomponent.class, }) public abstract class SystemUIModule { Loading packages/SystemUI/src/com/android/systemui/display/dagger/SystemUIDisplaySubcomponent.kt +3 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.display.dagger import com.android.systemui.display.dagger.SystemUIDisplaySubcomponent.PerDisplaySingleton import dagger.BindsInstance import dagger.Subcomponent import javax.inject.Qualifier Loading @@ -31,10 +32,11 @@ import kotlinx.coroutines.CoroutineScope * cancelled in the background, so any teardown logic should be threadsafe. Cancelling on the main * thread is not feasible as it would cause jank. */ @PerDisplaySingleton @Subcomponent(modules = [PerDisplayCommonModule::class]) interface SystemUIDisplaySubcomponent { @DisplayAware val displayCoroutineScope: CoroutineScope @get:DisplayAware val displayCoroutineScope: CoroutineScope @Subcomponent.Factory interface Factory { Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayComponentPerDisplayRepositoryTest.kt 0 → 100644 +59 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.display.data.repository import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.isActive import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @SmallTest class DisplayComponentPerDisplayRepositoryTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val testScope = kosmos.testScope private val underTest = DisplayComponentInstanceProvider(kosmos.fakeSysuiDisplayComponentFactory) @Test fun createInstance_activeByDefault() = testScope.runTest { val scopeForDisplay = underTest.createInstance(displayId = 1)!!.displayCoroutineScope assertThat(scopeForDisplay.isActive).isTrue() } @Test fun destroyInstance_afterDisplayRemoved_scopeIsCancelled() = testScope.runTest { val component = underTest.createInstance(displayId = 1) val scope = component!!.displayCoroutineScope underTest.destroyInstance(component) assertThat(scope.isActive).isFalse() } }
packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayScopeRepositoryInstanceProviderTest.kt +11 −8 Original line number Diff line number Diff line Loading @@ -16,11 +16,11 @@ package com.android.systemui.display.data.repository import android.view.Display import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos Loading @@ -36,28 +36,31 @@ class DisplayScopeRepositoryInstanceProviderTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val testScope = kosmos.testScope private val displaySubcomponentRepository = kosmos.displaySubcomponentPerDisplayRepository private val underTest = DisplayScopeRepositoryInstanceProvider( kosmos.applicationCoroutineScope, kosmos.testDispatcher, displaySubcomponentRepository, ) @Test fun createInstance_activeByDefault() = testScope.runTest { val scopeForDisplay = underTest.createInstance(displayId = 1) displaySubcomponentRepository.add(displayId = 1, kosmos.createFakeDisplaySubcomponent()) val scopeForDisplay = underTest.createInstance(displayId = 1)!! assertThat(scopeForDisplay.isActive).isTrue() } @Test fun destroyInstance_afterDisplayRemoved_scopeIsCancelled() = fun createInstance_forDefaultDisplay_returnsConstructorParam() = testScope.runTest { val scopeForDisplay = underTest.createInstance(displayId = 1) val scopeForDisplay = underTest.createInstance(displayId = Display.DEFAULT_DISPLAY)!! underTest.destroyInstance(scopeForDisplay) assertThat(scopeForDisplay.isActive).isFalse() assertThat(scopeForDisplay).isEqualTo(kosmos.applicationCoroutineScope) } // no test for destruction, as it's not handled by this class. The scope is meant to be // destroyed by the PerDisplayRepository<SystemUIDisplaySubcomponent> }
packages/SystemUI/src/com/android/systemui/dagger/PerDisplayRepositoriesModule.kt +4 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.dagger import com.android.app.displaylib.DefaultDisplayOnlyInstanceRepositoryImpl import com.android.app.displaylib.PerDisplayInstanceRepositoryImpl import com.android.app.displaylib.PerDisplayRepository import com.android.systemui.display.data.repository.DisplayComponentRepository import com.android.systemui.display.data.repository.PerDisplayCoroutineScopeRepositoryModule import com.android.systemui.model.SysUIStateInstanceProvider import com.android.systemui.model.SysUiState Loading @@ -27,7 +28,9 @@ import dagger.Module import dagger.Provides /** This module is meant to contain all the code to create the various [PerDisplayRepository<>]. */ @Module(includes = [PerDisplayCoroutineScopeRepositoryModule::class]) @Module( includes = [PerDisplayCoroutineScopeRepositoryModule::class, DisplayComponentRepository::class] ) class PerDisplayRepositoriesModule { @SysUISingleton Loading
packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +2 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import com.android.systemui.demomode.dagger.DemoModeModule; import com.android.systemui.deviceentry.DeviceEntryModule; import com.android.systemui.display.DisplayModule; import com.android.app.displaylib.PerDisplayRepository; import com.android.systemui.display.dagger.SystemUIDisplaySubcomponent; import com.android.systemui.doze.dagger.DozeComponent; import com.android.systemui.dreams.dagger.DreamModule; import com.android.systemui.flags.FeatureFlags; Loading Loading @@ -299,6 +300,7 @@ import javax.inject.Named; NavigationBarComponent.class, NotificationRowComponent.class, WindowRootViewComponent.class, SystemUIDisplaySubcomponent.class, }) public abstract class SystemUIModule { Loading
packages/SystemUI/src/com/android/systemui/display/dagger/SystemUIDisplaySubcomponent.kt +3 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.display.dagger import com.android.systemui.display.dagger.SystemUIDisplaySubcomponent.PerDisplaySingleton import dagger.BindsInstance import dagger.Subcomponent import javax.inject.Qualifier Loading @@ -31,10 +32,11 @@ import kotlinx.coroutines.CoroutineScope * cancelled in the background, so any teardown logic should be threadsafe. Cancelling on the main * thread is not feasible as it would cause jank. */ @PerDisplaySingleton @Subcomponent(modules = [PerDisplayCommonModule::class]) interface SystemUIDisplaySubcomponent { @DisplayAware val displayCoroutineScope: CoroutineScope @get:DisplayAware val displayCoroutineScope: CoroutineScope @Subcomponent.Factory interface Factory { Loading