diff options
13 files changed, 26 insertions, 239 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayInstanceRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayInstanceRepositoryImplTest.kt index 6c7783ae44e1..28b9e733be94 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayInstanceRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/PerDisplayInstanceRepositoryImplTest.kt @@ -19,6 +19,7 @@ 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.app.displaylib.PerDisplayInstanceRepositoryImpl import com.android.systemui.SysuiTestCase import com.android.systemui.dump.dumpManager import com.android.systemui.kosmos.testScope diff --git a/packages/SystemUI/src/com/android/systemui/common/domain/interactor/SysUIStateDisplaysInteractor.kt b/packages/SystemUI/src/com/android/systemui/common/domain/interactor/SysUIStateDisplaysInteractor.kt index 9db7b50905f8..1301fb87069e 100644 --- a/packages/SystemUI/src/com/android/systemui/common/domain/interactor/SysUIStateDisplaysInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/common/domain/interactor/SysUIStateDisplaysInteractor.kt @@ -17,9 +17,9 @@ package com.android.systemui.common.domain.interactor import android.util.Log +import com.android.app.displaylib.PerDisplayRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.display.data.repository.DisplayRepository -import com.android.systemui.display.data.repository.PerDisplayRepository import com.android.systemui.model.StateChange import com.android.systemui.model.SysUiState import javax.inject.Inject diff --git a/packages/SystemUI/src/com/android/systemui/dagger/PerDisplayRepositoriesModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/PerDisplayRepositoriesModule.kt index 39708a743c23..3520439fda88 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/PerDisplayRepositoriesModule.kt +++ b/packages/SystemUI/src/com/android/systemui/dagger/PerDisplayRepositoriesModule.kt @@ -16,9 +16,9 @@ package com.android.systemui.dagger -import com.android.systemui.display.data.repository.DefaultDisplayOnlyInstanceRepositoryImpl -import com.android.systemui.display.data.repository.PerDisplayInstanceRepositoryImpl -import com.android.systemui.display.data.repository.PerDisplayRepository +import com.android.app.displaylib.DefaultDisplayOnlyInstanceRepositoryImpl +import com.android.app.displaylib.PerDisplayInstanceRepositoryImpl +import com.android.app.displaylib.PerDisplayRepository import com.android.systemui.model.SysUIStateInstanceProvider import com.android.systemui.model.SysUiState import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index f08126af0a7a..854c610a3bd3 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -65,7 +65,7 @@ import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.demomode.dagger.DemoModeModule; import com.android.systemui.deviceentry.DeviceEntryModule; import com.android.systemui.display.DisplayModule; -import com.android.systemui.display.data.repository.PerDisplayRepository; +import com.android.app.displaylib.PerDisplayRepository; import com.android.systemui.doze.dagger.DozeComponent; import com.android.systemui.dreams.dagger.DreamModule; import com.android.systemui.flags.FeatureFlags; diff --git a/packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt b/packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt index f3316958f01d..908d0aafb2b9 100644 --- a/packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt +++ b/packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt @@ -18,7 +18,9 @@ package com.android.systemui.display import android.hardware.display.DisplayManager import android.os.Handler +import com.android.app.displaylib.DisplayLibBackground import com.android.app.displaylib.DisplayLibComponent +import com.android.app.displaylib.PerDisplayRepository import com.android.app.displaylib.createDisplayLibComponent import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton @@ -34,7 +36,6 @@ import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepos import com.android.systemui.display.data.repository.FocusedDisplayRepository import com.android.systemui.display.data.repository.FocusedDisplayRepositoryImpl import com.android.systemui.display.data.repository.PerDisplayRepoDumpHelper -import com.android.systemui.display.data.repository.PerDisplayRepository import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractorImpl import com.android.systemui.display.domain.interactor.DisplayWindowPropertiesInteractorModule @@ -85,6 +86,10 @@ interface DisplayModule { @Binds fun dumpRegistrationLambda(helper: PerDisplayRepoDumpHelper): PerDisplayRepository.InitCallback + @Binds + @DisplayLibBackground + fun bindDisplayLibBackground(@Background bgScope: CoroutineScope): CoroutineScope + companion object { @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/FakePerDisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/FakePerDisplayRepository.kt index a56710ee3772..86c9d84c27b1 100644 --- a/packages/SystemUI/src/com/android/systemui/display/data/repository/FakePerDisplayRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/FakePerDisplayRepository.kt @@ -16,6 +16,9 @@ package com.android.systemui.display.data.repository +import com.android.app.displaylib.PerDisplayRepository + +// TODO b/401305290 - move to displaylib class FakePerDisplayRepository<T> : PerDisplayRepository<T> { private val instances = mutableMapOf<Int, T>() diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepoDumpHelper.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepoDumpHelper.kt index 212d55612935..efbae5d04caf 100644 --- a/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepoDumpHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepoDumpHelper.kt @@ -16,6 +16,7 @@ package com.android.systemui.display.data.repository +import com.android.app.displaylib.PerDisplayRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager import com.android.systemui.dump.DumpableFromToString diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepository.kt deleted file mode 100644 index 7e00c60dc43a..000000000000 --- a/packages/SystemUI/src/com/android/systemui/display/data/repository/PerDisplayRepository.kt +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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 android.util.Log -import android.view.Display -import com.android.app.tracing.coroutines.launchTraced as launch -import com.android.app.tracing.traceSection -import com.android.systemui.dagger.qualifiers.Background -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import java.util.concurrent.ConcurrentHashMap -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collectLatest - -/** - * Used to create instances of type `T` for a specific display. - * - * This is useful for resources or objects that need to be managed independently for each connected - * display (e.g., UI state, rendering contexts, or display-specific configurations). - * - * Note that in most cases this can be implemented by a simple `@AssistedFactory` with `displayId` - * parameter - * - * ```kotlin - * class SomeType @AssistedInject constructor(@Assisted displayId: Int,..) - * @AssistedFactory - * interface Factory { - * fun create(displayId: Int): SomeType - * } - * } - * ``` - * - * Then it can be used to create a [PerDisplayRepository] as follows: - * ```kotlin - * // Injected: - * val repositoryFactory: PerDisplayRepositoryImpl.Factory - * val instanceFactory: PerDisplayRepositoryImpl.Factory - * // repository creation: - * repositoryFactory.create(instanceFactory::create) - * ``` - * - * @see PerDisplayRepository For how to retrieve and manage instances created by this factory. - */ -fun interface PerDisplayInstanceProvider<T> { - /** Creates an instance for a display. */ - fun createInstance(displayId: Int): T? -} - -/** - * Extends [PerDisplayInstanceProvider], adding support for destroying the instance. - * - * This is useful for releasing resources associated with a display when it is disconnected or when - * the per-display instance is no longer needed. - */ -interface PerDisplayInstanceProviderWithTeardown<T> : PerDisplayInstanceProvider<T> { - /** Destroys a previously created instance of `T` forever. */ - fun destroyInstance(instance: T) -} - -/** - * Provides access to per-display instances of type `T`. - * - * Acts as a repository, managing the caching and retrieval of instances created by a - * [PerDisplayInstanceProvider]. It ensures that only one instance of `T` exists per display ID. - */ -interface PerDisplayRepository<T> { - /** Gets the cached instance or create a new one for a given display. */ - operator fun get(displayId: Int): T? - - /** Debug name for this repository, mainly for tracing and logging. */ - val debugName: String - - /** - * Callback to run when a given repository is initialized. - * - * This allows the caller to perform custom logic when the repository is ready to be used, e.g. - * register to dumpManager. - * - * Note that the instance is *leaked* outside of this class, so it should only be done when - * repository is meant to live as long as the caller. In systemUI this is ok because the - * repository lives as long as the process itself. - */ - interface InitCallback { - fun onInit(debugName: String, instance: Any) - } -} - -/** - * Default implementation of [PerDisplayRepository]. - * - * This class manages a cache of per-display instances of type `T`, creating them using a provided - * [PerDisplayInstanceProvider] and optionally tearing them down using a - * [PerDisplayInstanceProviderWithTeardown] when displays are disconnected. - * - * It listens to the [DisplayRepository] to detect when displays are added or removed, and - * automatically manages the lifecycle of the per-display instances. - * - * Note that this is a [PerDisplayStoreImpl] 2.0 that doesn't require [CoreStartable] bindings, - * providing all args in the constructor. - */ -class PerDisplayInstanceRepositoryImpl<T> -@AssistedInject -constructor( - @Assisted override val debugName: String, - @Assisted private val instanceProvider: PerDisplayInstanceProvider<T>, - @Background private val backgroundApplicationScope: CoroutineScope, - private val displayRepository: DisplayRepository, - private val initCallback: PerDisplayRepository.InitCallback, -) : PerDisplayRepository<T> { - - private val perDisplayInstances = ConcurrentHashMap<Int, T?>() - - init { - backgroundApplicationScope.launch("$debugName#start") { start() } - } - - private suspend fun start() { - initCallback.onInit(debugName, this) - displayRepository.displayIds.collectLatest { displayIds -> - val toRemove = perDisplayInstances.keys - displayIds - toRemove.forEach { displayId -> - Log.d(TAG, "<$debugName> destroying instance for displayId=$displayId.") - perDisplayInstances.remove(displayId)?.let { instance -> - (instanceProvider as? PerDisplayInstanceProviderWithTeardown)?.destroyInstance( - instance - ) - } - } - } - } - - override fun get(displayId: Int): T? { - if (displayRepository.getDisplay(displayId) == null) { - Log.e(TAG, "<$debugName: Display with id $displayId doesn't exist.") - return null - } - - // If it doesn't exist, create it and put it in the map. - return perDisplayInstances.computeIfAbsent(displayId) { key -> - Log.d(TAG, "<$debugName> creating instance for displayId=$key, as it wasn't available.") - val instance = - traceSection({ "creating instance of $debugName for displayId=$key" }) { - instanceProvider.createInstance(key) - } - if (instance == null) { - Log.e( - TAG, - "<$debugName> returning null because createInstance($key) returned null.", - ) - } - instance - } - } - - @AssistedFactory - interface Factory<T> { - fun create( - debugName: String, - instanceProvider: PerDisplayInstanceProvider<T>, - ): PerDisplayInstanceRepositoryImpl<T> - } - - companion object { - private const val TAG = "PerDisplayInstanceRepo" - } - - override fun toString(): String { - return "PerDisplayInstanceRepositoryImpl(" + - "debugName='$debugName', instances=$perDisplayInstances)" - } -} - -/** - * Provides an instance of a given class **only** for the default display, even if asked for another - * display. - * - * This is useful in case of **flag refactors**: it can be provided instead of an instance of - * [PerDisplayInstanceRepositoryImpl] when a flag related to multi display refactoring is off. - * - * Note that this still requires all instances to be provided by a [PerDisplayInstanceProvider]. If - * you want to provide an existing instance instead for the default display, either implement it in - * a custom [PerDisplayInstanceProvider] (e.g. inject it in the constructor and return it if the - * displayId is zero), or use [SingleInstanceRepositoryImpl]. - */ -class DefaultDisplayOnlyInstanceRepositoryImpl<T>( - override val debugName: String, - private val instanceProvider: PerDisplayInstanceProvider<T>, -) : PerDisplayRepository<T> { - private val lazyDefaultDisplayInstance by lazy { - instanceProvider.createInstance(Display.DEFAULT_DISPLAY) - } - - override fun get(displayId: Int): T? = lazyDefaultDisplayInstance -} - -/** - * Always returns [instance] for any display. - * - * This can be used to provide a single instance based on a flag value during a refactor. Similar to - * [DefaultDisplayOnlyInstanceRepositoryImpl], but also avoids creating the - * [PerDisplayInstanceProvider]. This is useful when you want to provide an existing instance only, - * without even instantiating a [PerDisplayInstanceProvider]. - */ -class SingleInstanceRepositoryImpl<T>(override val debugName: String, private val instance: T) : - PerDisplayRepository<T> { - override fun get(displayId: Int): T? = instance -} diff --git a/packages/SystemUI/src/com/android/systemui/model/SysUiState.kt b/packages/SystemUI/src/com/android/systemui/model/SysUiState.kt index e99ee7ddb919..7f42ed3ee33c 100644 --- a/packages/SystemUI/src/com/android/systemui/model/SysUiState.kt +++ b/packages/SystemUI/src/com/android/systemui/model/SysUiState.kt @@ -17,9 +17,9 @@ package com.android.systemui.model import android.util.Log import android.view.Display +import com.android.app.displaylib.PerDisplayInstanceProviderWithTeardown import com.android.systemui.Dumpable import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.display.data.repository.PerDisplayInstanceProviderWithTeardown import com.android.systemui.dump.DumpManager import com.android.systemui.model.SysUiState.SysUiStateCallback import com.android.systemui.shared.system.QuickStepContract diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarPerDisplayConfigurationStateRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarPerDisplayConfigurationStateRepository.kt index 3168a22c56ad..cb1002a83179 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarPerDisplayConfigurationStateRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarPerDisplayConfigurationStateRepository.kt @@ -17,14 +17,14 @@ package com.android.systemui.statusbar.data.repository import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR +import com.android.app.displaylib.PerDisplayInstanceProvider +import com.android.app.displaylib.PerDisplayInstanceRepositoryImpl +import com.android.app.displaylib.PerDisplayRepository +import com.android.app.displaylib.SingleInstanceRepositoryImpl import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.common.ui.ConfigurationStateImpl import com.android.systemui.dagger.SysUISingleton import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository -import com.android.systemui.display.data.repository.PerDisplayInstanceProvider -import com.android.systemui.display.data.repository.PerDisplayInstanceRepositoryImpl -import com.android.systemui.display.data.repository.PerDisplayRepository -import com.android.systemui.display.data.repository.SingleInstanceRepositoryImpl import com.android.systemui.statusbar.core.StatusBarConnectedDisplays import dagger.Lazy import dagger.Module @@ -39,7 +39,6 @@ constructor( private val statusBarConfigurationControllerStore: StatusBarConfigurationControllerStore, private val factory: ConfigurationStateImpl.Factory, ) : PerDisplayInstanceProvider<ConfigurationState> { - override fun createInstance(displayId: Int): ConfigurationState? { val displayWindowProperties = displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) ?: return null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt index 147a5afea306..619d48f8ba81 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerStatusBarViewBinder.kt @@ -18,9 +18,9 @@ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import android.view.Display import androidx.lifecycle.lifecycleScope +import com.android.app.displaylib.PerDisplayRepository import com.android.app.tracing.traceSection import com.android.systemui.common.ui.ConfigurationState -import com.android.systemui.display.data.repository.PerDisplayRepository import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.notification.collection.NotifCollection import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder.IconViewStore diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt index 338e4bec7aa2..122e6a507cbf 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt @@ -16,6 +16,7 @@ package com.android.systemui.display.data.repository import android.view.Display +import com.android.app.displaylib.DisplayRepository.PendingDisplay import com.android.systemui.dagger.SysUISingleton import com.android.systemui.util.mockito.mock import dagger.Binds @@ -26,7 +27,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -import com.android.app.displaylib.DisplayRepository.PendingDisplay import org.mockito.Mockito.`when` as whenever /** Creates a mock display. */ @@ -50,8 +50,7 @@ fun createPendingDisplay(id: Int = 0): PendingDisplay = class FakeDisplayRepository @Inject constructor() : DisplayRepository { private val flow = MutableStateFlow<Set<Display>>(emptySet()) private val displayIdFlow = MutableStateFlow<Set<Int>>(emptySet()) - private val pendingDisplayFlow = - MutableSharedFlow<PendingDisplay?>(replay = 1) + private val pendingDisplayFlow = MutableSharedFlow<PendingDisplay?>(replay = 1) private val displayAdditionEventFlow = MutableSharedFlow<Display?>(replay = 0) private val displayRemovalEventFlow = MutableSharedFlow<Int>(replay = 0) private val displayIdsWithSystemDecorationsFlow = MutableStateFlow<Set<Int>>(emptySet()) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/PerDisplayStoreKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/PerDisplayStoreKosmos.kt index 5ab3b3de49f4..4b516e9c74bc 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/PerDisplayStoreKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/PerDisplayStoreKosmos.kt @@ -16,6 +16,8 @@ package com.android.systemui.display.data.repository +import com.android.app.displaylib.PerDisplayInstanceProviderWithTeardown +import com.android.app.displaylib.PerDisplayInstanceRepositoryImpl import com.android.systemui.dump.dumpManager import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope |