Loading packages/SystemUI/aconfig/systemui.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -2040,3 +2040,14 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "remember_view_model_off_main_thread" namespace: "systemui" description: "View-models are remembered off the main thread" bug: "421000550" metadata { purpose: PURPOSE_BUGFIX } } packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/ConnectedDisplaysStatusBarNotificationIconViewStoreTest.kt +2 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.display.domain.interactor.displayWindowPropertiesInteractor import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.statusbar.RankingBuilder Loading Loading @@ -57,6 +58,7 @@ class ConnectedDisplaysStatusBarNotificationIconViewStoreTest : SysuiTestCase() kosmos.iconManager, kosmos.displayWindowPropertiesInteractor, kosmos.notifPipeline, kosmos.testDispatcher, ) private val notifCollectionListeners = mutableListOf<NotifCollectionListener>() Loading packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt +20 −2 Original line number Diff line number Diff line Loading @@ -20,9 +20,14 @@ import android.view.View import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import com.android.app.tracing.coroutines.launchTraced as launch import com.android.app.tracing.coroutines.launchTraced import com.android.app.tracing.coroutines.traceCoroutine import com.android.systemui.Flags.rememberViewModelOffMainThread import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlinx.coroutines.CoroutineScope import com.android.app.tracing.coroutines.launchTraced as launch import kotlinx.coroutines.Dispatchers /** * Returns a remembered view-model of the type [T]. If the returned instance is also an Loading @@ -39,11 +44,24 @@ import com.android.app.tracing.coroutines.launchTraced as launch fun <T> rememberViewModel( traceName: String, key: Any = Unit, context: CoroutineContext = EmptyCoroutineContext, factory: () -> T, ): T { val instance = remember(key) { factory() } if (instance is Activatable) { LaunchedEffect(instance) { traceCoroutine(traceName) { instance.activate() } } LaunchedEffect(instance) { launchTraced( spanName = traceName, context = when { context != EmptyCoroutineContext -> context rememberViewModelOffMainThread() -> Dispatchers.Default else -> coroutineContext }, ) { instance.activate() } } } return instance } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/ConnectedDisplaysStatusBarNotificationIconViewStore.kt +14 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import android.util.Log import com.android.dream.lowlight.dagger.qualifiers.Main import com.android.systemui.display.domain.interactor.DisplayWindowPropertiesInteractor import com.android.systemui.lifecycle.Activatable import com.android.systemui.statusbar.StatusBarIconView Loading @@ -30,8 +31,10 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.withContext /** [IconViewStore] for the status bar on multiple displays. */ class ConnectedDisplaysStatusBarNotificationIconViewStore Loading @@ -42,6 +45,7 @@ constructor( private val iconManager: IconManager, private val displayWindowPropertiesInteractor: DisplayWindowPropertiesInteractor, private val notifPipeline: NotifPipeline, @Main private val mainDispatcher: CoroutineDispatcher, ) : IconViewStore, Activatable { private val cachedIcons = ConcurrentHashMap<String, StatusBarIconView>() Loading Loading @@ -79,6 +83,10 @@ constructor( } override suspend fun activate() = coroutineScope { // In case activate is being invoked off the main thread, make sure to switch to the main // thread to do the work here as some of the downstream calls assert they've been called on // the main thread. withContext(mainDispatcher) { start() try { awaitCancellation() Loading @@ -86,6 +94,7 @@ constructor( stop() } } } private fun start() { notifPipeline.addCollectionListener(notifCollectionListener) Loading Loading
packages/SystemUI/aconfig/systemui.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -2040,3 +2040,14 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "remember_view_model_off_main_thread" namespace: "systemui" description: "View-models are remembered off the main thread" bug: "421000550" metadata { purpose: PURPOSE_BUGFIX } }
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/ConnectedDisplaysStatusBarNotificationIconViewStoreTest.kt +2 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.display.domain.interactor.displayWindowPropertiesInteractor import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.statusbar.RankingBuilder Loading Loading @@ -57,6 +58,7 @@ class ConnectedDisplaysStatusBarNotificationIconViewStoreTest : SysuiTestCase() kosmos.iconManager, kosmos.displayWindowPropertiesInteractor, kosmos.notifPipeline, kosmos.testDispatcher, ) private val notifCollectionListeners = mutableListOf<NotifCollectionListener>() Loading
packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt +20 −2 Original line number Diff line number Diff line Loading @@ -20,9 +20,14 @@ import android.view.View import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import com.android.app.tracing.coroutines.launchTraced as launch import com.android.app.tracing.coroutines.launchTraced import com.android.app.tracing.coroutines.traceCoroutine import com.android.systemui.Flags.rememberViewModelOffMainThread import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlinx.coroutines.CoroutineScope import com.android.app.tracing.coroutines.launchTraced as launch import kotlinx.coroutines.Dispatchers /** * Returns a remembered view-model of the type [T]. If the returned instance is also an Loading @@ -39,11 +44,24 @@ import com.android.app.tracing.coroutines.launchTraced as launch fun <T> rememberViewModel( traceName: String, key: Any = Unit, context: CoroutineContext = EmptyCoroutineContext, factory: () -> T, ): T { val instance = remember(key) { factory() } if (instance is Activatable) { LaunchedEffect(instance) { traceCoroutine(traceName) { instance.activate() } } LaunchedEffect(instance) { launchTraced( spanName = traceName, context = when { context != EmptyCoroutineContext -> context rememberViewModelOffMainThread() -> Dispatchers.Default else -> coroutineContext }, ) { instance.activate() } } } return instance } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/ConnectedDisplaysStatusBarNotificationIconViewStore.kt +14 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import android.util.Log import com.android.dream.lowlight.dagger.qualifiers.Main import com.android.systemui.display.domain.interactor.DisplayWindowPropertiesInteractor import com.android.systemui.lifecycle.Activatable import com.android.systemui.statusbar.StatusBarIconView Loading @@ -30,8 +31,10 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.withContext /** [IconViewStore] for the status bar on multiple displays. */ class ConnectedDisplaysStatusBarNotificationIconViewStore Loading @@ -42,6 +45,7 @@ constructor( private val iconManager: IconManager, private val displayWindowPropertiesInteractor: DisplayWindowPropertiesInteractor, private val notifPipeline: NotifPipeline, @Main private val mainDispatcher: CoroutineDispatcher, ) : IconViewStore, Activatable { private val cachedIcons = ConcurrentHashMap<String, StatusBarIconView>() Loading Loading @@ -79,6 +83,10 @@ constructor( } override suspend fun activate() = coroutineScope { // In case activate is being invoked off the main thread, make sure to switch to the main // thread to do the work here as some of the downstream calls assert they've been called on // the main thread. withContext(mainDispatcher) { start() try { awaitCancellation() Loading @@ -86,6 +94,7 @@ constructor( stop() } } } private fun start() { notifPipeline.addCollectionListener(notifCollectionListener) Loading