summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Evan Laird <evanlaird@google.com> 2024-10-29 16:29:29 -0400
committer Evan Laird <evanlaird@google.com> 2024-11-11 16:14:21 -0500
commit226b32846e117769c8fbef654fc30e28ea5d153b (patch)
tree1ace74211de94683b8392a1d56c4f50e689aa24e
parent6900d991ba9b0e00beaf56c5253df565b5a6e80e (diff)
[sb] Move status bar animation to binder
Since the visibility of the status bar is controlled by the view binder now, we have to move the animation logic to the binder as well. The old system asked views to provide an AnimatorSet that would get `playTogether()`'d with the chip animator to ensure that all animations had the same keyframes. This change removes that guarantee, and instead exposes explicit states from the animation repository and expects that views can coordinate on their own terms. For now, this means that we have the possibility that animations could be out of sync by a frame or so. In practice, that's not an issue. And the further things move into Compose, the more we can get that kind of state synchronization back, since the whole view tree can be modeled on the state of the system event animation repository. Test: SystemStatusAnimationSchedulerImplTest Test: atest SystemUITests Test: manually triggering battery / camera events and checking the animation Bug: 364360986 Flag: com.android.systemui.status_bar_root_modernization Change-Id: I576aa9f3e2b2a45e73f6899aa9b5a6991a322d35
-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.kt12
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt91
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/data/repository/SystemStatusEventAnimationRepository.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/domain/interactor/SystemStatusEventAnimationInteractor.kt89
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt114
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowView.java2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/events/data/repository/SystemStatusEventAnimationRepositoryKosmos.kt28
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/events/domain/interactor/SystemStatusEventAnimationInteractorKosmos.kt31
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt2
16 files changed, 434 insertions, 81 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 cdc7aa2dea2a..9888574071e6 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
@@ -32,6 +32,8 @@ class FakeHomeStatusBarViewBinder : HomeStatusBarViewBinder {
override fun bind(
view: View,
viewModel: HomeStatusBarViewModel,
+ systemEventChipAnimateIn: ((View) -> Unit)?,
+ systemEventChipAnimateOut: ((View) -> Unit)?,
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 02c1540d3d8b..eef5753cef8a 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
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
import android.view.View
import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.Idle
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -53,11 +54,14 @@ class FakeHomeStatusBarViewModel : HomeStatusBarViewModel {
)
)
- override val isSystemInfoVisible =
+ override val systemInfoCombinedVis =
MutableStateFlow(
- HomeStatusBarViewModel.VisibilityModel(
- visibility = View.GONE,
- shouldAnimateChange = false,
+ HomeStatusBarViewModel.SystemInfoCombinedVisibilityModel(
+ HomeStatusBarViewModel.VisibilityModel(
+ visibility = View.GONE,
+ shouldAnimateChange = false,
+ ),
+ Idle,
)
)
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 b3a73d82122f..c4d2569bba89 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
@@ -60,11 +60,16 @@ import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepositor
import com.android.systemui.statusbar.data.repository.fakeStatusBarModeRepository
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
+import com.android.systemui.statusbar.events.data.repository.systemStatusEventAnimationRepository
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimatingIn
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimatingOut
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.Idle
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel.VisibilityModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow
@@ -90,6 +95,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
private val activeNotificationListRepository = kosmos.activeNotificationListRepository
private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
private val disableFlagsRepository = kosmos.fakeDisableFlagsRepository
+ private val systemStatusEventAnimationRepository = kosmos.systemStatusEventAnimationRepository
private lateinit var underTest: HomeStatusBarViewModel
@@ -546,25 +552,50 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
@Test
fun isSystemInfoVisible_allowedByDisableFlags_visible() =
testScope.runTest {
- val latest by collectLastValue(underTest.isSystemInfoVisible)
+ val latest by collectLastValue(underTest.systemInfoCombinedVis)
transitionKeyguardToGone()
disableFlagsRepository.disableFlags.value =
DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
- assertThat(latest!!.visibility).isEqualTo(View.VISIBLE)
+ assertThat(latest!!.baseVisibility.visibility).isEqualTo(View.VISIBLE)
}
@Test
fun isSystemInfoVisible_notAllowedByDisableFlags_gone() =
testScope.runTest {
- val latest by collectLastValue(underTest.isSystemInfoVisible)
+ val latest by collectLastValue(underTest.systemInfoCombinedVis)
transitionKeyguardToGone()
disableFlagsRepository.disableFlags.value =
DisableFlagsModel(DISABLE_SYSTEM_INFO, DISABLE2_NONE)
- assertThat(latest!!.visibility).isEqualTo(View.GONE)
+ assertThat(latest!!.baseVisibility.visibility).isEqualTo(View.GONE)
+ }
+
+ @Test
+ fun systemInfoCombineVis_animationsPassThrough() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.systemInfoCombinedVis)
+ transitionKeyguardToGone()
+
+ assertThat(latest!!.baseVisibility)
+ .isEqualTo(VisibilityModel(visibility = View.VISIBLE, shouldAnimateChange = false))
+ assertThat(latest!!.animationState).isEqualTo(Idle)
+
+ // WHEN the animation state changes, but the visibility state doesn't change
+ systemStatusEventAnimationRepository.animationState.value = AnimatingIn
+
+ // THEN the visibility is the same
+ assertThat(latest!!.baseVisibility)
+ .isEqualTo(VisibilityModel(visibility = View.VISIBLE, shouldAnimateChange = false))
+ // THEN the animation state updates
+ assertThat(latest!!.animationState).isEqualTo(AnimatingIn)
+
+ systemStatusEventAnimationRepository.animationState.value = AnimatingOut
+ assertThat(latest!!.baseVisibility)
+ .isEqualTo(VisibilityModel(visibility = View.VISIBLE, shouldAnimateChange = false))
+ assertThat(latest!!.animationState).isEqualTo(AnimatingOut)
}
@Test
@@ -573,7 +604,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.GONE,
@@ -583,7 +614,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
}
@Test
@@ -592,13 +623,13 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
kosmos.sceneContainerRepository.snapToScene(Scenes.Lockscreen)
assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
}
@Test
@@ -607,7 +638,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.LOCKSCREEN,
@@ -617,7 +648,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
}
@Test
@@ -626,13 +657,13 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
kosmos.sceneContainerRepository.snapToScene(Scenes.Bouncer)
assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
}
@Test
@@ -641,7 +672,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.LOCKSCREEN,
@@ -651,7 +682,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
assertThat(clockVisible!!.visibility).isEqualTo(View.VISIBLE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.VISIBLE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.VISIBLE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.VISIBLE)
}
@Test
@@ -660,14 +691,14 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
kosmos.sceneContainerRepository.snapToScene(Scenes.Lockscreen)
kosmos.keyguardOcclusionRepository.setShowWhenLockedActivityInfo(true, taskInfo = null)
assertThat(clockVisible!!.visibility).isEqualTo(View.VISIBLE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.VISIBLE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.VISIBLE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.VISIBLE)
}
@Test
@@ -676,13 +707,13 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
transitionKeyguardToGone()
assertThat(clockVisible!!.visibility).isEqualTo(View.VISIBLE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.VISIBLE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.VISIBLE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.VISIBLE)
}
@Test
@@ -691,14 +722,14 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
transitionKeyguardToGone()
kosmos.shadeTestUtil.setShadeExpansion(0f)
assertThat(clockVisible!!.visibility).isEqualTo(View.VISIBLE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.VISIBLE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.VISIBLE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.VISIBLE)
}
@Test
@@ -707,13 +738,13 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
kosmos.sceneContainerRepository.snapToScene(Scenes.Gone)
assertThat(clockVisible!!.visibility).isEqualTo(View.VISIBLE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.VISIBLE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.VISIBLE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.VISIBLE)
}
@Test
@@ -722,14 +753,14 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
transitionKeyguardToGone()
kosmos.shadeTestUtil.setShadeExpansion(1f)
assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
}
@Test
@@ -738,14 +769,14 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
transitionKeyguardToGone()
kosmos.sceneContainerRepository.snapToScene(Scenes.Shade)
assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
}
@Test
@@ -754,7 +785,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
// Secure camera is an occluding activity
keyguardTransitionRepository.sendTransitionSteps(
@@ -766,7 +797,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
}
@Test
@@ -775,7 +806,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
testScope.runTest {
val clockVisible by collectLastValue(underTest.isClockVisible)
val notifIconsVisible by collectLastValue(underTest.isNotificationIconContainerVisible)
- val systemInfoVisible by collectLastValue(underTest.isSystemInfoVisible)
+ val systemInfoVisible by collectLastValue(underTest.systemInfoCombinedVis)
kosmos.sceneContainerRepository.snapToScene(Scenes.Lockscreen)
// Secure camera is an occluding activity
@@ -784,7 +815,7 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
assertThat(clockVisible!!.visibility).isEqualTo(View.GONE)
assertThat(notifIconsVisible!!.visibility).isEqualTo(View.GONE)
- assertThat(systemInfoVisible!!.visibility).isEqualTo(View.GONE)
+ assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
}
private fun activeNotificationsStore(notifications: List<ActiveNotificationModel>) =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
index 564d52a62cde..1cb4c44d10e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
@@ -27,7 +27,10 @@ import kotlinx.coroutines.flow.StateFlow
interface SystemStatusAnimationScheduler :
CallbackController<SystemStatusAnimationCallback>, Dumpable {
- /** StateFlow holding the current [SystemEventAnimationState] at any time. */
+ /**
+ * The current state of the animation. This can be used from compose functions to coordinate
+ * their animations with the chip
+ */
val animationState: StateFlow<SystemEventAnimationState>
fun onStatusEvent(event: StatusEvent)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/data/repository/SystemStatusEventAnimationRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/data/repository/SystemStatusEventAnimationRepository.kt
new file mode 100644
index 000000000000..971f5d1b04f2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/data/repository/SystemStatusEventAnimationRepository.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 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.statusbar.events.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState
+import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
+
+/** Repository to expose the [SystemStatusAnimationScheduler] state via flows */
+interface SystemStatusEventAnimationRepository {
+ val animationState: StateFlow<SystemEventAnimationState>
+}
+
+@SysUISingleton
+class SystemStatusEventAnimationRepositoryImpl
+@Inject
+constructor(scheduler: SystemStatusAnimationScheduler) : SystemStatusEventAnimationRepository {
+ override val animationState = scheduler.animationState
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/domain/interactor/SystemStatusEventAnimationInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/domain/interactor/SystemStatusEventAnimationInteractor.kt
new file mode 100644
index 000000000000..3e3064223595
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/domain/interactor/SystemStatusEventAnimationInteractor.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2024 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.statusbar.events.domain.interactor
+
+import android.view.View
+import androidx.core.animation.Animator
+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.res.R
+import com.android.systemui.statusbar.events.data.repository.SystemStatusEventAnimationRepository
+import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventDefaultAnimator
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * Interactor for dealing with system status event animations. This class can be used to monitor the
+ * current [animationState], and defines some common animation functions that an handle hiding
+ * system chrome in order to make space for the event chips
+ */
+@SysUISingleton
+class SystemStatusEventAnimationInteractor
+@Inject
+constructor(
+ repo: SystemStatusEventAnimationRepository,
+ configurationInteractor: ConfigurationInteractor,
+ @Application scope: CoroutineScope,
+) {
+ private val chipAnimateInTranslationX =
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.ongoing_appops_chip_animation_in_status_bar_translation_x)
+ .stateIn(scope, SharingStarted.Eagerly, 0)
+
+ private val chipAnimateOutTranslationX =
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.ongoing_appops_chip_animation_out_status_bar_translation_x)
+ .stateIn(scope, SharingStarted.Eagerly, 0)
+
+ val animationState = repo.animationState
+
+ private fun getDefaultStatusBarAnimationForChipEnter(
+ setX: (Float) -> Unit,
+ setAlpha: (Float) -> Unit,
+ ): Animator {
+ return StatusBarSystemEventDefaultAnimator.getDefaultStatusBarAnimationForChipEnter(
+ chipAnimateInTranslationX.value,
+ setX,
+ setAlpha,
+ )
+ }
+
+ private fun getDefaultStatusBarAnimationForChipExit(
+ setX: (Float) -> Unit,
+ setAlpha: (Float) -> Unit,
+ ): Animator {
+ return StatusBarSystemEventDefaultAnimator.getDefaultStatusBarAnimationForChipExit(
+ chipAnimateOutTranslationX.value,
+ setX,
+ setAlpha,
+ )
+ }
+
+ fun animateStatusBarContentForChipEnter(v: View) {
+ getDefaultStatusBarAnimationForChipEnter(setX = v::setTranslationX, setAlpha = v::setAlpha)
+ .start()
+ }
+
+ fun animateStatusBarContentForChipExit(v: View) {
+ v.translationX = chipAnimateOutTranslationX.value.toFloat()
+ getDefaultStatusBarAnimationForChipExit(setX = v::setTranslationX, setAlpha = v::setAlpha)
+ .start()
+ }
+}
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 c55a63c9edf5..23b4b65bb2ac 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
@@ -376,7 +376,11 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
mCarrierConfigTracker.addDefaultDataSubscriptionChangedListener(mDefaultDataListener);
mHomeStatusBarViewBinder.bind(
- mStatusBar, mHomeStatusBarViewModel, mStatusBarVisibilityChangeListener);
+ mStatusBar,
+ mHomeStatusBarViewModel,
+ /* systemEventChipAnimateIn */ null,
+ /* systemEventChipAnimateOut */ null,
+ mStatusBarVisibilityChangeListener);
}
private String getDumpableName() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
index 1f9ea08e602f..fd7bce099d81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
@@ -71,49 +71,87 @@ constructor(
override fun onSystemEventAnimationBegin(): Animator {
isAnimationRunning = true
- val moveOut =
- ValueAnimator.ofFloat(0f, 1f).apply {
- duration = 23.frames
- interpolator = STATUS_BAR_X_MOVE_OUT
- addUpdateListener {
- onTranslationXChanged(-(translationXIn * animatedValue as Float))
- }
- }
- val alphaOut =
- ValueAnimator.ofFloat(1f, 0f).apply {
- duration = 8.frames
- interpolator = null
- addUpdateListener { onAlphaChanged(animatedValue as Float) }
- }
-
- val animSet = AnimatorSet()
- animSet.playTogether(moveOut, alphaOut)
- return animSet
+ return getDefaultStatusBarAnimationForChipEnter(
+ translationXIn,
+ onTranslationXChanged,
+ onAlphaChanged,
+ )
}
override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator {
onTranslationXChanged(translationXOut.toFloat())
- val moveIn =
- ValueAnimator.ofFloat(1f, 0f).apply {
- duration = 23.frames
- startDelay = 7.frames
- interpolator = STATUS_BAR_X_MOVE_IN
- addUpdateListener {
- onTranslationXChanged(translationXOut * animatedValue as Float)
+ val anim =
+ getDefaultStatusBarAnimationForChipExit(
+ translationXOut,
+ onTranslationXChanged,
+ onAlphaChanged,
+ )
+ anim.doOnEnd { isAnimationRunning = false }
+ anim.doOnCancel { isAnimationRunning = false }
+
+ return anim
+ }
+
+ /** Static definition of these animations so we can use them more easily from view binders */
+ companion object {
+ /**
+ * Chip: coming in. Animated view: going out.
+ *
+ * Implements the exact spec for animating any status bar elements OUT to make space for the
+ * chip IN animation.
+ */
+ fun getDefaultStatusBarAnimationForChipEnter(
+ targetTranslation: Int,
+ setX: (Float) -> Unit,
+ setAlpha: (Float) -> Unit,
+ ): Animator {
+ val moveOut =
+ ValueAnimator.ofFloat(0f, 1f).apply {
+ duration = 23.frames
+ interpolator = STATUS_BAR_X_MOVE_OUT
+ addUpdateListener { setX(-(targetTranslation * animatedValue as Float)) }
+ }
+ val alphaOut =
+ ValueAnimator.ofFloat(1f, 0f).apply {
+ duration = 8.frames
+ interpolator = null
+ addUpdateListener { setAlpha(animatedValue as Float) }
+ }
+
+ val animSet = AnimatorSet()
+ animSet.playTogether(moveOut, alphaOut)
+ return animSet
+ }
+
+ /**
+ * Chip: going out. Animated view: coming in.
+ *
+ * Implements the exact spec for animating any status bar elements IN as the chip is
+ * animating OUT
+ */
+ fun getDefaultStatusBarAnimationForChipExit(
+ targetTranslation: Int,
+ setX: (Float) -> Unit,
+ setAlpha: (Float) -> Unit,
+ ): Animator {
+ val moveIn =
+ ValueAnimator.ofFloat(1f, 0f).apply {
+ duration = 23.frames
+ startDelay = 7.frames
+ interpolator = STATUS_BAR_X_MOVE_IN
+ addUpdateListener { setX(targetTranslation * animatedValue as Float) }
+ }
+ val alphaIn =
+ ValueAnimator.ofFloat(0f, 1f).apply {
+ duration = 5.frames
+ startDelay = 11.frames
+ interpolator = null
+ addUpdateListener { setAlpha(animatedValue as Float) }
}
- }
- val alphaIn =
- ValueAnimator.ofFloat(0f, 1f).apply {
- duration = 5.frames
- startDelay = 11.frames
- interpolator = null
- addUpdateListener { onAlphaChanged(animatedValue as Float) }
- }
- val animatorSet = AnimatorSet()
- animatorSet.playTogether(moveIn, alphaIn)
- animatorSet.doOnEnd { isAnimationRunning = false }
- animatorSet.doOnCancel { isAnimationRunning = false }
- return animatorSet
+ val animatorSet = AnimatorSet()
+ animatorSet.playTogether(moveIn, alphaIn)
+ return animatorSet
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index 935b1012be31..bfdc8bd5e4c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -23,6 +23,8 @@ import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.statusbar.events.data.repository.SystemStatusEventAnimationRepository
+import com.android.systemui.statusbar.events.data.repository.SystemStatusEventAnimationRepositoryImpl
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepositoryImpl
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
@@ -85,6 +87,11 @@ abstract class StatusBarPipelineModule {
abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository
@Binds
+ abstract fun systemStatusEventAnimationRepository(
+ impl: SystemStatusEventAnimationRepositoryImpl
+ ): SystemStatusEventAnimationRepository
+
+ @Binds
abstract fun realDeviceBasedSatelliteRepository(
impl: DeviceBasedSatelliteRepositoryImpl
): RealDeviceBasedSatelliteRepository
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 2177e025b976..72df02714d43 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
@@ -32,6 +32,10 @@ import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifCh
import com.android.systemui.statusbar.chips.ui.binder.OngoingActivityChipBinder
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.core.StatusBarRootModernization
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimatingIn
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.AnimatingOut
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.RunningChipAnim
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel
@@ -46,10 +50,16 @@ interface HomeStatusBarViewBinder {
/**
* Binds the view to the view-model. [listener] will be notified whenever an event that may
* change the status bar visibility occurs.
+ *
+ * Null chip animations are used when [StatusBarRootModernization] is off (i.e., when we are
+ * binding from the fragment). If non-null, they control the animation of the system icon area
+ * to support the chip animations.
*/
fun bind(
view: View,
viewModel: HomeStatusBarViewModel,
+ systemEventChipAnimateIn: ((View) -> Unit)?,
+ systemEventChipAnimateOut: ((View) -> Unit)?,
listener: StatusBarVisibilityChangeListener,
)
}
@@ -59,6 +69,8 @@ class HomeStatusBarViewBinderImpl @Inject constructor() : HomeStatusBarViewBinde
override fun bind(
view: View,
viewModel: HomeStatusBarViewModel,
+ systemEventChipAnimateIn: ((View) -> Unit)?,
+ systemEventChipAnimateOut: ((View) -> Unit)?,
listener: StatusBarVisibilityChangeListener,
) {
view.repeatWhenAttached {
@@ -95,6 +107,7 @@ class HomeStatusBarViewBinderImpl @Inject constructor() : HomeStatusBarViewBinde
when (primaryChipModel) {
is OngoingActivityChipModel.Shown ->
primaryChipView.show(shouldAnimateChange = true)
+
is OngoingActivityChipModel.Hidden ->
primaryChipView.hide(
state = View.GONE,
@@ -109,6 +122,7 @@ class HomeStatusBarViewBinderImpl @Inject constructor() : HomeStatusBarViewBinde
hasSecondaryOngoingActivity = false,
shouldAnimate = true,
)
+
is OngoingActivityChipModel.Hidden ->
listener.onOngoingActivityStatusChanged(
hasPrimaryOngoingActivity = false,
@@ -175,10 +189,30 @@ class HomeStatusBarViewBinderImpl @Inject constructor() : HomeStatusBarViewBinde
view.requireViewById<View>(R.id.status_bar_end_side_content)
// TODO(b/364360986): Also handle operator name view.
launch {
- viewModel.isSystemInfoVisible.collect {
- systemInfoView.adjustVisibility(it)
- // TODO(b/364360986): The system info view has a custom alpha controller
- // in CollapsedStatusBarFragment.
+ viewModel.systemInfoCombinedVis.collect { (baseVis, animState) ->
+ // Broadly speaking, the baseVis controls the view.visibility, and
+ // the animation state uses only alpha to achieve its effect. This
+ // means that we can always modify the visibility, and if we're
+ // animating we can use the animState to handle it. If we are not
+ // animating, then we can use the baseVis default animation
+ if (animState.isAnimatingChip()) {
+ // Just apply the visibility of the view, but don't animate
+ systemInfoView.visibility = baseVis.visibility
+ // Now apply the animation state, with its animator
+ when (animState) {
+ AnimatingIn -> {
+ systemEventChipAnimateIn?.invoke(systemInfoView)
+ }
+ AnimatingOut -> {
+ systemEventChipAnimateOut?.invoke(systemInfoView)
+ }
+ else -> {
+ // Nothing to do here
+ }
+ }
+ } else {
+ systemInfoView.adjustVisibility(baseVis)
+ }
}
}
}
@@ -186,6 +220,14 @@ class HomeStatusBarViewBinderImpl @Inject constructor() : HomeStatusBarViewBinde
}
}
+ private fun SystemEventAnimationState.isAnimatingChip() =
+ when (this) {
+ AnimatingIn,
+ AnimatingOut,
+ RunningChipAnim -> true
+ else -> false
+ }
+
private fun OngoingActivityChipModel.toVisibilityModel(): VisibilityModel {
return VisibilityModel(
visibility = if (this is OngoingActivityChipModel.Shown) View.VISIBLE else View.GONE,
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 a9c2f72f7b18..1faa9f32af1f 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
@@ -35,6 +35,7 @@ import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.res.R
import com.android.systemui.statusbar.data.repository.DarkIconDispatcherStore
+import com.android.systemui.statusbar.events.domain.interactor.SystemStatusEventAnimationInteractor
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder
import com.android.systemui.statusbar.phone.NotificationIconContainer
import com.android.systemui.statusbar.phone.PhoneStatusBarView
@@ -59,6 +60,7 @@ constructor(
private val iconController: StatusBarIconController,
private val ongoingCallController: OngoingCallController,
private val darkIconDispatcherStore: DarkIconDispatcherStore,
+ private val eventAnimationInteractor: SystemStatusEventAnimationInteractor,
) {
fun create(root: ViewGroup, andThen: (ViewGroup) -> Unit): ComposeView {
val composeView = ComposeView(root.context)
@@ -73,6 +75,7 @@ constructor(
iconController = iconController,
ongoingCallController = ongoingCallController,
darkIconDispatcher = darkIconDispatcherStore.forDisplay(root.context.displayId),
+ eventAnimationInteractor = eventAnimationInteractor,
onViewCreated = andThen,
)
}
@@ -102,6 +105,7 @@ fun StatusBarRoot(
iconController: StatusBarIconController,
ongoingCallController: OngoingCallController,
darkIconDispatcher: DarkIconDispatcher,
+ eventAnimationInteractor: SystemStatusEventAnimationInteractor,
onViewCreated: (ViewGroup) -> Unit,
) {
// None of these methods are used when [StatusBarRootModernization] is on.
@@ -181,6 +185,8 @@ fun StatusBarRoot(
statusBarViewBinder.bind(
phoneStatusBarView,
statusBarViewModel,
+ eventAnimationInteractor::animateStatusBarContentForChipEnter,
+ eventAnimationInteractor::animateStatusBarContentForChipExit,
nopVisibilityChangeListener,
)
}
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 4277a8be64d3..6a9b43c995e4 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
@@ -35,6 +35,9 @@ import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModel
+import com.android.systemui.statusbar.events.domain.interactor.SystemStatusEventAnimationInteractor
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.Idle
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.phone.domain.interactor.LightsOutInteractor
@@ -95,7 +98,12 @@ interface HomeStatusBarViewModel {
val isClockVisible: Flow<VisibilityModel>
val isNotificationIconContainerVisible: Flow<VisibilityModel>
- val isSystemInfoVisible: Flow<VisibilityModel>
+ /**
+ * Pair of (system info visibility, event animation state). The animation state can be used to
+ * respond to the system event chip animations. In all cases, system info visibility correctly
+ * models the View.visibility for the system info area
+ */
+ val systemInfoCombinedVis: StateFlow<SystemInfoCombinedVisibilityModel>
/**
* Apps can request a low profile mode [android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE] where
@@ -114,6 +122,12 @@ interface HomeStatusBarViewModel {
/** True if a visibility change should be animated. */
val shouldAnimateChange: Boolean,
)
+
+ /** The combined visibility + animation state for the system info status bar area */
+ data class SystemInfoCombinedVisibilityModel(
+ val baseVisibility: VisibilityModel,
+ val animationState: SystemEventAnimationState,
+ )
}
@SysUISingleton
@@ -129,6 +143,7 @@ constructor(
sceneContainerOcclusionInteractor: SceneContainerOcclusionInteractor,
shadeInteractor: ShadeInteractor,
ongoingActivityChipsViewModel: OngoingActivityChipsViewModel,
+ animations: SystemStatusEventAnimationInteractor,
@Application coroutineScope: CoroutineScope,
) : HomeStatusBarViewModel {
override val isTransitioningFromLockscreenToOccluded: StateFlow<Boolean> =
@@ -228,7 +243,7 @@ constructor(
visibilityViaDisableFlags.animate,
)
}
- override val isSystemInfoVisible: Flow<VisibilityModel> =
+ private val isSystemInfoVisible =
combine(
shouldHomeStatusBarBeVisible,
collapsedStatusBarInteractor.visibilityViaDisableFlags,
@@ -238,6 +253,22 @@ constructor(
VisibilityModel(showSystemInfo.toVisibilityInt(), visibilityViaDisableFlags.animate)
}
+ override val systemInfoCombinedVis =
+ combine(isSystemInfoVisible, animations.animationState) { sysInfoVisible, animationState ->
+ HomeStatusBarViewModel.SystemInfoCombinedVisibilityModel(
+ sysInfoVisible,
+ animationState,
+ )
+ }
+ .stateIn(
+ coroutineScope,
+ SharingStarted.WhileSubscribed(),
+ HomeStatusBarViewModel.SystemInfoCombinedVisibilityModel(
+ VisibilityModel(View.VISIBLE, false),
+ Idle,
+ ),
+ )
+
@View.Visibility
private fun Boolean.toVisibilityInt(): Int {
return if (this) View.VISIBLE else View.GONE
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowView.java
index b79d39e65682..36d64a9b405e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowView.java
@@ -39,7 +39,7 @@ import com.android.systemui.statusbar.core.StatusBarRootModernization;
import com.android.systemui.statusbar.data.repository.StatusBarConfigurationController;
/**
- * Status bar view.
+ * Status bar view
* We now extend WindowRootView so that we can host Compose views
*/
public class StatusBarWindowView extends FrameLayout {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/events/data/repository/SystemStatusEventAnimationRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/events/data/repository/SystemStatusEventAnimationRepositoryKosmos.kt
new file mode 100644
index 000000000000..92eeef97f7c4
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/events/data/repository/SystemStatusEventAnimationRepositoryKosmos.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 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.statusbar.events.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState
+import kotlinx.coroutines.flow.MutableStateFlow
+
+val Kosmos.systemStatusEventAnimationRepository: FakeSystemStatusEventAnimationRepository by
+ Kosmos.Fixture { FakeSystemStatusEventAnimationRepository() }
+
+class FakeSystemStatusEventAnimationRepository : SystemStatusEventAnimationRepository {
+ override val animationState = MutableStateFlow(SystemEventAnimationState.Idle)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/events/domain/interactor/SystemStatusEventAnimationInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/events/domain/interactor/SystemStatusEventAnimationInteractorKosmos.kt
new file mode 100644
index 000000000000..7513fead0187
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/events/domain/interactor/SystemStatusEventAnimationInteractorKosmos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 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.statusbar.events.domain.interactor
+
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.statusbar.events.data.repository.systemStatusEventAnimationRepository
+
+val Kosmos.systemStatusEventAnimationInteractor by
+ Kosmos.Fixture {
+ SystemStatusEventAnimationInteractor(
+ repo = systemStatusEventAnimationRepository,
+ configurationInteractor = configurationInteractor,
+ scope = applicationCoroutineScope,
+ )
+ }
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 3a7ada2e61b8..03e4c894c2f2 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
@@ -24,6 +24,7 @@ import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInter
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.statusbar.chips.ui.viewmodel.ongoingActivityChipsViewModel
+import com.android.systemui.statusbar.events.domain.interactor.systemStatusEventAnimationInteractor
import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
import com.android.systemui.statusbar.phone.domain.interactor.lightsOutInteractor
import com.android.systemui.statusbar.pipeline.shared.domain.interactor.collapsedStatusBarInteractor
@@ -40,6 +41,7 @@ val Kosmos.homeStatusBarViewModel: HomeStatusBarViewModel by
sceneContainerOcclusionInteractor,
shadeInteractor,
ongoingActivityChipsViewModel,
+ systemStatusEventAnimationInteractor,
applicationCoroutineScope,
)
}