summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Evan Laird <evanlaird@google.com> 2025-02-03 10:23:21 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-02-03 10:23:21 -0800
commit64739dcd7c5890a7e7a0ad36d2180e6d3a5ee382 (patch)
tree3b3c9b63fb97d4161ef375128858d3133072f483
parent91d57642a70837531f813d147d43b970b4a3449e (diff)
parenta270a4761f809482c19826e09aed2dd033564271 (diff)
Merge changes If79b8f20,I91a033c1,I8927fcfd,I41f0fe27 into main
* changes: [sb] get rid of recomposition on the StatusBarRoot [sb] StatusBarVisibilityChangeListener is now optional [sb] OngoingActivityChipsViewModel to use bg scope [sb] Move flows to bgDispatcher
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewBinder.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt95
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt29
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt6
8 files changed, 84 insertions, 186 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewBinder.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewBinder.kt
index a2ca12c13a3e..5b5681e0faf4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewBinder.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewBinder.kt
@@ -35,7 +35,7 @@ class FakeHomeStatusBarViewBinder : HomeStatusBarViewBinder {
viewModel: HomeStatusBarViewModel,
systemEventChipAnimateIn: ((View) -> Unit)?,
systemEventChipAnimateOut: ((View) -> Unit)?,
- listener: StatusBarVisibilityChangeListener,
+ listener: StatusBarVisibilityChangeListener?,
) {
this.listener = listener
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
index 0223484dae41..4af97c0d33d9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
@@ -52,8 +52,6 @@ class FakeHomeStatusBarViewModel(
override val isHomeStatusBarAllowedByScene = MutableStateFlow(false)
- override val shouldHomeStatusBarBeVisible = MutableStateFlow(false)
-
override val shouldShowOperatorNameView = MutableStateFlow(false)
override val isClockVisible =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
index 46f625fd9ba8..dc355434c00b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
@@ -88,16 +88,13 @@ import com.android.systemui.statusbar.pipeline.shared.domain.interactor.setHomeS
import com.android.systemui.statusbar.pipeline.shared.ui.model.VisibilityModel
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@SmallTest
-@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
class HomeStatusBarViewModelImplTest : SysuiTestCase() {
private val kosmos = testKosmos().useUnconfinedTestDispatcher()
@@ -651,98 +648,6 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
}
@Test
- fun shouldHomeStatusBarBeVisible_keyguardNotGone_noHun_false() =
- kosmos.runTest {
- // Do not transition from keyguard. i.e., we don't call transitionKeyguardToGone()
-
- // Nothing disabled
- fakeDisableFlagsRepository.disableFlags.value =
- DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
-
- val latest by collectLastValue(underTest.shouldHomeStatusBarBeVisible)
- assertThat(latest).isFalse()
- }
-
- @Test
- fun shouldHomeStatusBarBeVisible_keyguardNotGone_hun_true() =
- kosmos.runTest {
- // Keyguard gone
- transitionKeyguardToGone()
-
- // Nothing disabled
- fakeDisableFlagsRepository.disableFlags.value =
- DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
-
- // there is an active HUN
- headsUpNotificationRepository.setNotifications(
- UnconfinedFakeHeadsUpRowRepository(
- key = "key",
- pinnedStatus = MutableStateFlow(PinnedStatus.PinnedByUser),
- )
- )
-
- val latest by collectLastValue(underTest.shouldHomeStatusBarBeVisible)
- assertThat(latest).isTrue()
- }
-
- @Test
- fun shouldHomeStatusBarBeVisible_keyguardGone_noHun_notInCamera_true() =
- kosmos.runTest {
- // Keyguard gone
- transitionKeyguardToGone()
-
- // Nothing disabled
- fakeDisableFlagsRepository.disableFlags.value =
- DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
-
- val latest by collectLastValue(underTest.shouldHomeStatusBarBeVisible)
- assertThat(latest).isTrue()
- }
-
- @Test
- fun shouldHomeStatusBarBeVisible_keyguardGone_hun_notInCamera_true() =
- kosmos.runTest {
- // Keyguard gone
- transitionKeyguardToGone()
-
- // Nothing disabled
- fakeDisableFlagsRepository.disableFlags.value =
- DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
-
- // there is an active HUN
- headsUpNotificationRepository.setNotifications(
- UnconfinedFakeHeadsUpRowRepository(
- key = "key",
- pinnedStatus = MutableStateFlow(PinnedStatus.PinnedByUser),
- )
- )
-
- val latest by collectLastValue(underTest.shouldHomeStatusBarBeVisible)
- assertThat(latest).isTrue()
- }
-
- @Test
- fun shouldHomeStatusBarBeVisible_keyguardGone_noHun_inCamera_false() =
- kosmos.runTest {
- // Keyguard gone
- transitionKeyguardToGone()
-
- // Nothing disabled
- fakeDisableFlagsRepository.disableFlags.value =
- DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
-
- fakeKeyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.OCCLUDED,
- testScope = testScope,
- )
- kosmos.keyguardInteractor.onCameraLaunchDetected(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP)
-
- val latest by collectLastValue(underTest.shouldHomeStatusBarBeVisible)
- assertThat(latest).isFalse()
- }
-
- @Test
fun isClockVisible_allowedByDisableFlags_visible() =
kosmos.runTest {
val latest by collectLastValue(underTest.isClockVisible)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt
index 1451154d25ab..4becc8ccac31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt
@@ -20,7 +20,7 @@ import android.content.res.Configuration
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.statusbar.chips.StatusBarChipLogTags.pad
@@ -56,7 +56,7 @@ import kotlinx.coroutines.flow.stateIn
class OngoingActivityChipsViewModel
@Inject
constructor(
- @Application scope: CoroutineScope,
+ @Background scope: CoroutineScope,
screenRecordChipViewModel: ScreenRecordChipViewModel,
shareToAppChipViewModel: ShareToAppChipViewModel,
castToOtherDeviceChipViewModel: CastToOtherDeviceChipViewModel,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
index bd6906066ac8..acce6426362d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
@@ -67,7 +67,7 @@ interface HomeStatusBarViewBinder {
viewModel: HomeStatusBarViewModel,
systemEventChipAnimateIn: ((View) -> Unit)?,
systemEventChipAnimateOut: ((View) -> Unit)?,
- listener: StatusBarVisibilityChangeListener,
+ listener: StatusBarVisibilityChangeListener?,
)
}
@@ -83,8 +83,22 @@ constructor(
viewModel: HomeStatusBarViewModel,
systemEventChipAnimateIn: ((View) -> Unit)?,
systemEventChipAnimateOut: ((View) -> Unit)?,
- listener: StatusBarVisibilityChangeListener,
+ listener: StatusBarVisibilityChangeListener?,
) {
+ // Set some top-level views to gone before we get started
+ val primaryChipView: View = view.requireViewById(R.id.ongoing_activity_chip_primary)
+ val systemInfoView = view.requireViewById<View>(R.id.status_bar_end_side_content)
+ val clockView = view.requireViewById<View>(R.id.clock)
+ val notificationIconsArea = view.requireViewById<View>(R.id.notificationIcons)
+
+ // CollapsedStatusBarFragment doesn't need this
+ if (StatusBarRootModernization.isEnabled) {
+ primaryChipView.isVisible = false
+ systemInfoView.isVisible = false
+ clockView.isVisible = false
+ notificationIconsArea.isVisible = false
+ }
+
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
val iconViewStore =
@@ -95,15 +109,19 @@ constructor(
} else {
null
}
- launch {
- viewModel.isTransitioningFromLockscreenToOccluded.collect {
- listener.onStatusBarVisibilityMaybeChanged()
+ listener?.let { listener ->
+ launch {
+ viewModel.isTransitioningFromLockscreenToOccluded.collect {
+ listener.onStatusBarVisibilityMaybeChanged()
+ }
}
}
- launch {
- viewModel.transitionFromLockscreenToDreamStartedEvent.collect {
- listener.onTransitionFromLockscreenToDreamStarted()
+ listener?.let { listener ->
+ launch {
+ viewModel.transitionFromLockscreenToDreamStartedEvent.collect {
+ listener.onTransitionFromLockscreenToDreamStarted()
+ }
}
}
@@ -129,9 +147,7 @@ constructor(
if (!StatusBarNotifChips.isEnabled && !StatusBarChipsModernization.isEnabled) {
val primaryChipViewBinding =
- OngoingActivityChipBinder.createBinding(
- view.requireViewById(R.id.ongoing_activity_chip_primary)
- )
+ OngoingActivityChipBinder.createBinding(primaryChipView)
launch {
viewModel.primaryOngoingActivityChip.collect { primaryChipModel ->
OngoingActivityChipBinder.bind(
@@ -155,14 +171,14 @@ constructor(
} else {
when (primaryChipModel) {
is OngoingActivityChipModel.Shown ->
- listener.onOngoingActivityStatusChanged(
+ listener?.onOngoingActivityStatusChanged(
hasPrimaryOngoingActivity = true,
hasSecondaryOngoingActivity = false,
shouldAnimate = true,
)
is OngoingActivityChipModel.Hidden ->
- listener.onOngoingActivityStatusChanged(
+ listener?.onOngoingActivityStatusChanged(
hasPrimaryOngoingActivity = false,
hasSecondaryOngoingActivity = false,
shouldAnimate = primaryChipModel.shouldAnimate,
@@ -177,9 +193,7 @@ constructor(
// Create view bindings here so we don't keep re-fetching child views each time
// the chip model changes.
val primaryChipViewBinding =
- OngoingActivityChipBinder.createBinding(
- view.requireViewById(R.id.ongoing_activity_chip_primary)
- )
+ OngoingActivityChipBinder.createBinding(primaryChipView)
val secondaryChipViewBinding =
OngoingActivityChipBinder.createBinding(
view.requireViewById(R.id.ongoing_activity_chip_secondary)
@@ -205,7 +219,7 @@ constructor(
chips.secondary.toVisibilityModel()
)
} else {
- listener.onOngoingActivityStatusChanged(
+ listener?.onOngoingActivityStatusChanged(
hasPrimaryOngoingActivity =
chips.primary is OngoingActivityChipModel.Shown,
hasSecondaryOngoingActivity =
@@ -231,15 +245,21 @@ constructor(
}
if (SceneContainerFlag.isEnabled) {
- launch {
- viewModel.isHomeStatusBarAllowedByScene.collect {
- listener.onIsHomeStatusBarAllowedBySceneChanged(it)
+ listener?.let { listener ->
+ launch {
+ viewModel.isHomeStatusBarAllowedByScene.collect {
+ listener.onIsHomeStatusBarAllowedBySceneChanged(it)
+ }
}
}
}
if (StatusBarRootModernization.isEnabled) {
+ // TODO(b/393445203): figure out the best story for this stub view. This crashes
+ // if we move it up to the top of [bind]
val operatorNameView = view.requireViewById<View>(R.id.operator_name_frame)
+ operatorNameView.isVisible = false
+
StatusBarOperatorNameViewBinder.bind(
operatorNameView,
viewModel.operatorNameViewModel,
@@ -251,19 +271,14 @@ constructor(
}
}
- val clockView = view.requireViewById<View>(R.id.clock)
launch { viewModel.isClockVisible.collect { clockView.adjustVisibility(it) } }
- val notificationIconsArea = view.requireViewById<View>(R.id.notificationIcons)
launch {
viewModel.isNotificationIconContainerVisible.collect {
notificationIconsArea.adjustVisibility(it)
}
}
- val systemInfoView =
- view.requireViewById<View>(R.id.status_bar_end_side_content)
- // TODO(b/364360986): Also handle operator name view.
launch {
viewModel.systemInfoCombinedVis.collect { (baseVis, animState) ->
// Broadly speaking, the baseVis controls the view.visibility, and
@@ -352,6 +367,9 @@ constructor(
// See CollapsedStatusBarFragment#hide.
private fun View.hide(state: Int = View.INVISIBLE, shouldAnimateChange: Boolean) {
+ if (visibility == View.INVISIBLE || visibility == View.GONE) {
+ return
+ }
val v = this
v.animate().cancel()
if (!shouldAnimateChange) {
@@ -370,6 +388,9 @@ constructor(
// See CollapsedStatusBarFragment#show.
private fun View.show(shouldAnimateChange: Boolean) {
+ if (visibility == View.VISIBLE) {
+ return
+ }
val v = this
v.animate().cancel()
v.visibility = View.VISIBLE
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 9c1171fd1ebc..9d72daf01831 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
@@ -25,16 +25,13 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.viewinterop.AndroidView
-import androidx.core.view.isVisible
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.compose.theme.PlatformTheme
import com.android.keyguard.AlphaOptimizedLinearLayout
import com.android.systemui.plugins.DarkIconDispatcher
@@ -56,7 +53,6 @@ import com.android.systemui.statusbar.phone.ui.DarkIconManager
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarIconBlockListBinder
import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarViewBinder
-import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener
import com.android.systemui.statusbar.pipeline.shared.ui.model.VisibilityModel
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel.HomeStatusBarViewModelFactory
@@ -124,25 +120,6 @@ fun StatusBarRoot(
eventAnimationInteractor: SystemStatusEventAnimationInteractor,
onViewCreated: (ViewGroup) -> Unit,
) {
- // None of these methods are used when [StatusBarRootModernization] is on.
- // This can be deleted once the fragment is gone
- val nopVisibilityChangeListener =
- object : StatusBarVisibilityChangeListener {
- override fun onStatusBarVisibilityMaybeChanged() {}
-
- override fun onTransitionFromLockscreenToDreamStarted() {}
-
- override fun onOngoingActivityStatusChanged(
- hasPrimaryOngoingActivity: Boolean,
- hasSecondaryOngoingActivity: Boolean,
- shouldAnimate: Boolean,
- ) {}
-
- override fun onIsHomeStatusBarAllowedBySceneChanged(
- isHomeStatusBarAllowedByScene: Boolean
- ) {}
- }
-
Box(Modifier.fillMaxSize()) {
// TODO(b/364360986): remove this before rolling the flag forward
if (StatusBarRootModernization.SHOW_DISAMBIGUATION) {
@@ -150,9 +127,6 @@ fun StatusBarRoot(
}
Row(Modifier.fillMaxSize()) {
- val scope = rememberCoroutineScope()
- val visible =
- statusBarViewModel.shouldHomeStatusBarBeVisible.collectAsStateWithLifecycle(false)
AndroidView(
factory = { context ->
val inflater = LayoutInflater.from(context)
@@ -267,32 +241,23 @@ fun StatusBarRoot(
endSideContent.addView(composeView, 0)
}
- scope.launch {
- notificationIconsBinder.bindWhileAttached(
- notificationIconContainer,
- context.displayId,
- )
- }
+ notificationIconsBinder.bindWhileAttached(
+ notificationIconContainer,
+ context.displayId,
+ )
// This binder handles everything else
- scope.launch {
- statusBarViewBinder.bind(
- context.displayId,
- phoneStatusBarView,
- statusBarViewModel,
- eventAnimationInteractor::animateStatusBarContentForChipEnter,
- eventAnimationInteractor::animateStatusBarContentForChipExit,
- nopVisibilityChangeListener,
- )
- }
+ statusBarViewBinder.bind(
+ context.displayId,
+ phoneStatusBarView,
+ statusBarViewModel,
+ eventAnimationInteractor::animateStatusBarContentForChipEnter,
+ eventAnimationInteractor::animateStatusBarContentForChipExit,
+ listener = null,
+ )
onViewCreated(phoneStatusBarView)
phoneStatusBarView
- },
- update = { view ->
- // Show or hide the entire status bar. This is important so that we aren't
- // visible when first inflated
- view.isVisible = visible.value
- },
+ }
)
}
}
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 b116b47929d5..67366bb09f04 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
@@ -19,7 +19,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
import android.annotation.ColorInt
import android.graphics.Rect
import android.view.View
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
@@ -61,6 +61,7 @@ import com.android.systemui.statusbar.pipeline.shared.ui.model.VisibilityModel
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -71,6 +72,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
@@ -85,9 +87,6 @@ import kotlinx.coroutines.flow.stateIn
* so that it's all in one place and easily testable outside of the fragment.
*/
interface HomeStatusBarViewModel {
- /** Should the entire status bar be hidden? */
- val shouldHomeStatusBarBeVisible: Flow<Boolean>
-
/**
* True if the device is currently transitioning from lockscreen to occluded and false
* otherwise.
@@ -193,7 +192,8 @@ constructor(
statusBarPopupChipsViewModel: StatusBarPopupChipsViewModel,
animations: SystemStatusEventAnimationInteractor,
statusBarContentInsetsViewModelStore: StatusBarContentInsetsViewModelStore,
- @Application coroutineScope: CoroutineScope,
+ @Background bgScope: CoroutineScope,
+ @Background bgDispatcher: CoroutineDispatcher,
) : HomeStatusBarViewModel {
val tableLogger = tableLoggerFactory.getOrCreate(tableLogBufferName(thisDisplayId), 200)
@@ -207,13 +207,14 @@ constructor(
columnName = COL_LOCK_TO_OCCLUDED,
initialValue = false,
)
- .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), initialValue = false)
+ .stateIn(bgScope, SharingStarted.WhileSubscribed(), initialValue = false)
override val transitionFromLockscreenToDreamStartedEvent: Flow<Unit> =
keyguardTransitionInteractor
.transition(Edge.create(from = LOCKSCREEN, to = DREAMING))
.filter { it.transitionState == TransitionState.STARTED }
.map {}
+ .flowOn(bgDispatcher)
override val mediaProjectionStopDialogDueToCallEndedState =
shareToAppChipViewModel.stopDialogToShow
@@ -242,7 +243,7 @@ constructor(
columnName = COL_ALLOWED_BY_SCENE,
initialValue = false,
)
- .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), initialValue = false)
+ .stateIn(bgScope, SharingStarted.WhileSubscribed(), initialValue = false)
override val areNotificationsLightsOut: Flow<Boolean> =
if (NotificationsLiveDataStoreRefactor.isUnexpectedlyInLegacyMode()) {
@@ -261,6 +262,7 @@ constructor(
columnName = COL_NOTIF_LIGHTS_OUT,
initialValue = false,
)
+ .flowOn(bgDispatcher)
override val areaTint: Flow<StatusBarTintColor> =
darkIconInteractor
@@ -276,6 +278,7 @@ constructor(
}
.conflate()
.distinctUntilChanged()
+ .flowOn(bgDispatcher)
/**
* True if the current SysUI state can show the home status bar (aka this status bar), and false
@@ -297,7 +300,7 @@ constructor(
isHomeScreenStatusBarAllowedLegacy
}
- override val shouldHomeStatusBarBeVisible =
+ private val shouldHomeStatusBarBeVisible =
combine(
isHomeStatusBarAllowed,
keyguardInteractor.isSecureCameraActive,
@@ -318,6 +321,7 @@ constructor(
columnName = COL_VISIBLE,
initialValue = false,
)
+ .flowOn(bgDispatcher)
private val isAnyChipVisible =
if (StatusBarNotifChips.isEnabled) {
@@ -361,6 +365,7 @@ constructor(
columnName = COL_SHOW_OPERATOR_NAME,
initialValue = false,
)
+ .flowOn(bgDispatcher)
override val isClockVisible: Flow<VisibilityModel> =
combine(
@@ -382,6 +387,7 @@ constructor(
columnPrefix = COL_PREFIX_CLOCK,
initialValue = VisibilityModel(false.toVisibleOrInvisible(), false),
)
+ .flowOn(bgDispatcher)
override val isNotificationIconContainerVisible: Flow<VisibilityModel> =
combine(
@@ -407,6 +413,7 @@ constructor(
columnPrefix = COL_PREFIX_NOTIF_CONTAINER,
initialValue = VisibilityModel(false.toVisibleOrInvisible(), false),
)
+ .flowOn(bgDispatcher)
private val isSystemInfoVisible =
combine(shouldHomeStatusBarBeVisible, homeStatusBarInteractor.visibilityViaDisableFlags) {
@@ -429,17 +436,17 @@ constructor(
SystemInfoCombinedVisibilityModel(VisibilityModel(View.VISIBLE, false), Idle),
)
.stateIn(
- coroutineScope,
+ bgScope,
SharingStarted.WhileSubscribed(),
SystemInfoCombinedVisibilityModel(VisibilityModel(View.VISIBLE, false), Idle),
)
override val iconBlockList: Flow<List<String>> =
- homeStatusBarIconBlockListInteractor.iconBlockList
+ homeStatusBarIconBlockListInteractor.iconBlockList.flowOn(bgDispatcher)
override val contentArea: Flow<Rect> =
statusBarContentInsetsViewModelStore.forDisplay(thisDisplayId)?.contentArea
- ?: flowOf(Rect(0, 0, 0, 0))
+ ?: flowOf(Rect(0, 0, 0, 0)).flowOn(bgDispatcher)
@View.Visibility
private fun Boolean.toVisibleOrGone(): Int {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt
index 1626904a9c19..bc29dba3442c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt
@@ -20,7 +20,8 @@ import android.content.testableContext
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.backgroundScope
+import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.log.table.tableLogBufferFactory
import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
@@ -59,6 +60,7 @@ var Kosmos.homeStatusBarViewModel: HomeStatusBarViewModel by
statusBarPopupChipsViewModel,
systemStatusEventAnimationInteractor,
multiDisplayStatusBarContentInsetsViewModelStore,
- applicationCoroutineScope,
+ backgroundScope,
+ testDispatcher,
)
}