diff options
author | 2024-10-29 16:29:29 -0400 | |
---|---|---|
committer | 2024-11-11 16:14:21 -0500 | |
commit | 226b32846e117769c8fbef654fc30e28ea5d153b (patch) | |
tree | 1ace74211de94683b8392a1d56c4f50e689aa24e | |
parent | 6900d991ba9b0e00beaf56c5253df565b5a6e80e (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
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, ) } |