diff options
13 files changed, 210 insertions, 147 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt index a50cc8fbacb3..306f4ffa2a54 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt @@ -103,7 +103,6 @@ constructor( private val smartspaceViewModel: KeyguardSmartspaceViewModel, private val lockscreenContentViewModel: LockscreenContentViewModel, private val lockscreenSceneBlueprintsLazy: Lazy<Set<LockscreenSceneBlueprint>>, - private val keyguardBlueprintViewBinder: KeyguardBlueprintViewBinder, private val clockInteractor: KeyguardClockInteractor, private val keyguardViewMediator: KeyguardViewMediator, ) : CoreStartable { @@ -150,7 +149,7 @@ constructor( cs.connect(composeView.id, BOTTOM, PARENT_ID, BOTTOM) keyguardRootView.addView(composeView) } else { - keyguardBlueprintViewBinder.bind( + KeyguardBlueprintViewBinder.bind( keyguardRootView, keyguardBlueprintViewModel, keyguardClockViewModel, @@ -197,12 +196,14 @@ constructor( KeyguardRootViewBinder.bind( keyguardRootView, keyguardRootViewModel, + keyguardBlueprintViewModel, configuration, occludingAppDeviceEntryMessageViewModel, chipbarCoordinator, screenOffAnimationController, shadeInteractor, clockInteractor, + keyguardClockViewModel, interactionJankMonitor, deviceEntryHapticsInteractor, vibratorHelper, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt index 816033561e94..bec8f3da9999 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt @@ -17,17 +17,12 @@ package com.android.systemui.keyguard.ui.binder -import android.os.Handler -import android.transition.Transition -import android.transition.TransitionManager import android.util.Log import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.app.tracing.coroutines.launch -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.KeyguardBottomAreaRefactor import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.BaseBlueprintTransition @@ -40,47 +35,9 @@ import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R import com.android.systemui.shared.R as sharedR import com.android.systemui.util.kotlin.pairwise -import javax.inject.Inject -import kotlin.math.max - -@SysUISingleton -class KeyguardBlueprintViewBinder -@Inject -constructor( - @Main private val handler: Handler, -) { - private var runningPriority = -1 - private val runningTransitions = mutableSetOf<Transition>() - private val isTransitionRunning: Boolean - get() = runningTransitions.size > 0 - private val transitionListener = - object : Transition.TransitionListener { - override fun onTransitionCancel(transition: Transition) { - if (DEBUG) Log.e(TAG, "onTransitionCancel: ${transition::class.simpleName}") - runningTransitions.remove(transition) - } - - override fun onTransitionEnd(transition: Transition) { - if (DEBUG) Log.e(TAG, "onTransitionEnd: ${transition::class.simpleName}") - runningTransitions.remove(transition) - } - - override fun onTransitionPause(transition: Transition) { - if (DEBUG) Log.i(TAG, "onTransitionPause: ${transition::class.simpleName}") - runningTransitions.remove(transition) - } - - override fun onTransitionResume(transition: Transition) { - if (DEBUG) Log.i(TAG, "onTransitionResume: ${transition::class.simpleName}") - runningTransitions.add(transition) - } - - override fun onTransitionStart(transition: Transition) { - if (DEBUG) Log.i(TAG, "onTransitionStart: ${transition::class.simpleName}") - runningTransitions.add(transition) - } - } +object KeyguardBlueprintViewBinder { + @JvmStatic fun bind( constraintLayout: ConstraintLayout, viewModel: KeyguardBlueprintViewModel, @@ -118,7 +75,7 @@ constructor( ) } - runTransition(constraintLayout, transition, config) { + viewModel.runTransition(constraintLayout, transition, config) { // Replace sections from the previous blueprint with the new ones blueprint.replaceViews( constraintLayout, @@ -146,7 +103,7 @@ constructor( viewModel.refreshTransition.collect { config -> val blueprint = viewModel.blueprint.value - runTransition( + viewModel.runTransition( constraintLayout, IntraBlueprintTransition(config, clockViewModel, smartspaceViewModel), config, @@ -167,50 +124,6 @@ constructor( } } - private fun runTransition( - constraintLayout: ConstraintLayout, - transition: Transition, - config: Config, - apply: () -> Unit, - ) { - val currentPriority = if (isTransitionRunning) runningPriority else -1 - if (config.checkPriority && config.type.priority < currentPriority) { - if (DEBUG) { - Log.w( - TAG, - "runTransition: skipping ${transition::class.simpleName}: " + - "currentPriority=$currentPriority; config=$config" - ) - } - apply() - return - } - - if (DEBUG) { - Log.i( - TAG, - "runTransition: running ${transition::class.simpleName}: " + - "currentPriority=$currentPriority; config=$config" - ) - } - - // beginDelayedTransition makes a copy, so we temporarially add the uncopied transition to - // the running set until the copy is started by the handler. - runningTransitions.add(transition) - transition.addListener(transitionListener) - runningPriority = max(currentPriority, config.type.priority) - - handler.post { - if (config.terminatePrevious) { - TransitionManager.endTransitions(constraintLayout) - } - - TransitionManager.beginDelayedTransition(constraintLayout, transition) - runningTransitions.remove(transition) - apply() - } - } - private fun logAlphaVisibilityOfAppliedConstraintSet( cs: ConstraintSet, viewModel: KeyguardClockViewModel @@ -237,8 +150,6 @@ constructor( ) } - companion object { - private const val TAG = "KeyguardBlueprintViewBinder" - private const val DEBUG = false - } + private const val TAG = "KeyguardBlueprintViewBinder" + private const val DEBUG = false } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt index 39db22d5616d..fc92afe17eff 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt @@ -22,6 +22,7 @@ import android.annotation.DrawableRes import android.annotation.SuppressLint import android.graphics.Point import android.graphics.Rect +import android.util.Log import android.view.HapticFeedbackConstants import android.view.View import android.view.View.OnLayoutChangeListener @@ -56,8 +57,11 @@ import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters +import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel +import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel +import com.android.systemui.keyguard.ui.viewmodel.TransitionData import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.FalsingManager @@ -93,12 +97,14 @@ object KeyguardRootViewBinder { fun bind( view: ViewGroup, viewModel: KeyguardRootViewModel, + blueprintViewModel: KeyguardBlueprintViewModel, configuration: ConfigurationState, occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel?, chipbarCoordinator: ChipbarCoordinator?, screenOffAnimationController: ScreenOffAnimationController, shadeInteractor: ShadeInteractor, clockInteractor: KeyguardClockInteractor, + clockViewModel: KeyguardClockViewModel, interactionJankMonitor: InteractionJankMonitor?, deviceEntryHapticsInteractor: DeviceEntryHapticsInteractor?, vibratorHelper: VibratorHelper?, @@ -348,7 +354,16 @@ object KeyguardRootViewBinder { } } - disposables += view.onLayoutChanged(OnLayoutChange(viewModel, childViews, burnInParams)) + disposables += + view.onLayoutChanged( + OnLayoutChange( + viewModel, + blueprintViewModel, + clockViewModel, + childViews, + burnInParams + ) + ) // Views will be added or removed after the call to bind(). This is needed to avoid many // calls to findViewById @@ -404,9 +419,13 @@ object KeyguardRootViewBinder { private class OnLayoutChange( private val viewModel: KeyguardRootViewModel, + private val blueprintViewModel: KeyguardBlueprintViewModel, + private val clockViewModel: KeyguardClockViewModel, private val childViews: Map<Int, View>, private val burnInParams: MutableStateFlow<BurnInParameters>, ) : OnLayoutChangeListener { + var prevTransition: TransitionData? = null + override fun onLayoutChange( view: View, left: Int, @@ -418,11 +437,21 @@ object KeyguardRootViewBinder { oldRight: Int, oldBottom: Int ) { + // After layout, ensure the notifications are positioned correctly childViews[nsslPlaceholderId]?.let { notificationListPlaceholder -> - // After layout, ensure the notifications are positioned correctly + // Do not update a second time while a blueprint transition is running + val transition = blueprintViewModel.currentTransition.value + val shouldAnimate = transition != null && transition.config.type.animateNotifChanges + if (prevTransition == transition && shouldAnimate) { + if (DEBUG) Log.w(TAG, "Skipping; layout during transition") + return + } + + prevTransition = transition viewModel.onNotificationContainerBoundsChanged( notificationListPlaceholder.top.toFloat(), notificationListPlaceholder.bottom.toFloat(), + animate = shouldAnimate ) } @@ -585,4 +614,6 @@ object KeyguardRootViewBinder { private const val ID = "occluding_app_device_entry_unlock_msg" private const val AOD_ICONS_APPEAR_DURATION: Long = 200 + private const val TAG = "KeyguardRootViewBinder" + private const val DEBUG = false } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt index fb1853f13ce9..777c873e47f0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt @@ -68,7 +68,9 @@ import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder import com.android.systemui.keyguard.ui.view.KeyguardRootView import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection +import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel +import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewClockViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewSmartspaceViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel @@ -134,6 +136,7 @@ constructor( private val vibratorHelper: VibratorHelper, private val indicationController: KeyguardIndicationController, private val keyguardRootViewModel: KeyguardRootViewModel, + private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel, @Assisted bundle: Bundle, private val occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel, private val chipbarCoordinator: ChipbarCoordinator, @@ -143,6 +146,7 @@ constructor( private val communalTutorialViewModel: CommunalTutorialIndicatorViewModel, private val defaultShortcutsSection: DefaultShortcutsSection, private val keyguardClockInteractor: KeyguardClockInteractor, + private val keyguardClockViewModel: KeyguardClockViewModel, ) { val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN) private val width: Int = bundle.getInt(KEY_VIEW_WIDTH) @@ -379,12 +383,14 @@ constructor( KeyguardRootViewBinder.bind( keyguardRootView, keyguardRootViewModel, + keyguardBlueprintViewModel, configuration, occludingAppDeviceEntryMessageViewModel, chipbarCoordinator, screenOffAnimationController, shadeInteractor, keyguardClockInteractor, + keyguardClockViewModel, null, // jank monitor not required for preview mode null, // device entry haptics not required preview mode null, // device entry haptics not required for preview mode diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/IntraBlueprintTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/IntraBlueprintTransition.kt index 02e9ca5b6821..39f1ebe25299 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/IntraBlueprintTransition.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/IntraBlueprintTransition.kt @@ -31,16 +31,16 @@ class IntraBlueprintTransition( enum class Type( val priority: Int, + val animateNotifChanges: Boolean, ) { - ClockSize(100), - ClockCenter(99), - DefaultClockStepping(98), - AodNotifIconsTransition(97), - SmartspaceVisibility(2), - DefaultTransition(1), + ClockSize(100, true), + ClockCenter(99, false), + DefaultClockStepping(98, false), + SmartspaceVisibility(2, true), + DefaultTransition(1, false), // When transition between blueprint, we don't need any duration or interpolator but we need // all elements go to correct state - NoTransition(0), + NoTransition(0, false), } data class Config( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt index 2832e9d8a35e..d77b54825664 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt @@ -19,6 +19,8 @@ package com.android.systemui.keyguard.ui.view.layout.sections import android.content.Context import android.view.View +import android.view.View.GONE +import android.view.View.VISIBLE import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.ConstraintSet.BOTTOM @@ -29,6 +31,7 @@ import androidx.constraintlayout.widget.ConstraintSet.TOP import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.keyguard.MigrateClocksToBlueprint import com.android.systemui.keyguard.shared.model.KeyguardSection +import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel import com.android.systemui.res.R import com.android.systemui.statusbar.notification.icon.ui.viewbinder.AlwaysOnDisplayNotificationIconViewStore import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder @@ -38,6 +41,7 @@ import com.android.systemui.statusbar.notification.shared.NotificationIconContai import com.android.systemui.statusbar.phone.NotificationIconAreaController import com.android.systemui.statusbar.phone.NotificationIconContainer import com.android.systemui.statusbar.ui.SystemBarUtilsState +import com.android.systemui.util.ui.value import javax.inject.Inject import kotlinx.coroutines.DisposableHandle @@ -51,6 +55,7 @@ constructor( private val nicAodIconViewStore: AlwaysOnDisplayNotificationIconViewStore, private val notificationIconAreaController: NotificationIconAreaController, private val systemBarUtilsState: SystemBarUtilsState, + private val rootViewModel: KeyguardRootViewModel, ) : KeyguardSection() { private var nicBindingDisposable: DisposableHandle? = null @@ -101,20 +106,14 @@ constructor( if (!MigrateClocksToBlueprint.isEnabled) { return } + val bottomMargin = context.resources.getDimensionPixelSize(R.dimen.keyguard_status_view_bottom_margin) - - val useSplitShade = context.resources.getBoolean(R.bool.config_use_split_notification_shade) - - val topAlignment = - if (useSplitShade) { - TOP - } else { - BOTTOM - } + val isVisible = rootViewModel.isNotifIconContainerVisible.value constraintSet.apply { connect(nicId, TOP, R.id.smart_space_barrier_bottom, BOTTOM, bottomMargin) setGoneMargin(nicId, BOTTOM, bottomMargin) + setVisibility(nicId, if (isVisible.value) VISIBLE else GONE) connect( nicId, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt index 7c745bc227f0..f17dbd24cf25 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt @@ -369,6 +369,21 @@ class ClockSizeTransition( addTarget(R.id.status_view_media_container) } + override fun mutateBounds( + view: View, + fromIsVis: Boolean, + toIsVis: Boolean, + fromBounds: Rect, + toBounds: Rect, + fromSSBounds: Rect?, + toSSBounds: Rect? + ) { + // If view is changing visibility, hold it in place + if (fromIsVis == toIsVis) return + if (DEBUG) Log.i(TAG, "Holding position of ${view.id}") + toBounds.set(fromBounds) + } + companion object { const val STATUS_AREA_MOVE_UP_MILLIS = 967L const val STATUS_AREA_MOVE_DOWN_MILLIS = 467L diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt index b1f189836903..7ac03bffd4f3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt @@ -17,15 +17,119 @@ package com.android.systemui.keyguard.ui.viewmodel +import android.os.Handler +import android.transition.Transition +import android.transition.TransitionManager +import android.util.Log +import androidx.constraintlayout.widget.ConstraintLayout +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor +import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config import javax.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +data class TransitionData( + val config: Config, + val start: Long = System.currentTimeMillis(), +) class KeyguardBlueprintViewModel @Inject constructor( + @Main private val handler: Handler, keyguardBlueprintInteractor: KeyguardBlueprintInteractor, ) { val blueprint = keyguardBlueprintInteractor.blueprint val blueprintId = keyguardBlueprintInteractor.blueprintId val refreshTransition = keyguardBlueprintInteractor.refreshTransition + + private val _currentTransition = MutableStateFlow<TransitionData?>(null) + val currentTransition = _currentTransition.asStateFlow() + + private val runningTransitions = mutableSetOf<Transition>() + private val transitionListener = + object : Transition.TransitionListener { + override fun onTransitionCancel(transition: Transition) { + if (DEBUG) Log.e(TAG, "onTransitionCancel: ${transition::class.simpleName}") + updateTransitions(null) { remove(transition) } + } + + override fun onTransitionEnd(transition: Transition) { + if (DEBUG) Log.e(TAG, "onTransitionEnd: ${transition::class.simpleName}") + updateTransitions(null) { remove(transition) } + } + + override fun onTransitionPause(transition: Transition) { + if (DEBUG) Log.i(TAG, "onTransitionPause: ${transition::class.simpleName}") + updateTransitions(null) { remove(transition) } + } + + override fun onTransitionResume(transition: Transition) { + if (DEBUG) Log.i(TAG, "onTransitionResume: ${transition::class.simpleName}") + updateTransitions(null) { add(transition) } + } + + override fun onTransitionStart(transition: Transition) { + if (DEBUG) Log.i(TAG, "onTransitionStart: ${transition::class.simpleName}") + updateTransitions(null) { add(transition) } + } + } + + fun updateTransitions(data: TransitionData?, mutate: MutableSet<Transition>.() -> Unit) { + runningTransitions.mutate() + + if (runningTransitions.size <= 0) _currentTransition.value = null + else if (data != null) _currentTransition.value = data + } + + fun runTransition( + constraintLayout: ConstraintLayout, + transition: Transition, + config: Config, + apply: () -> Unit, + ) { + val currentPriority = currentTransition.value?.let { it.config.type.priority } ?: -1 + if (config.checkPriority && config.type.priority < currentPriority) { + if (DEBUG) { + Log.w( + TAG, + "runTransition: skipping ${transition::class.simpleName}: " + + "currentPriority=$currentPriority; config=$config" + ) + } + apply() + return + } + + if (DEBUG) { + Log.i( + TAG, + "runTransition: running ${transition::class.simpleName}: " + + "currentPriority=$currentPriority; config=$config" + ) + } + + // beginDelayedTransition makes a copy, so we temporarially add the uncopied transition to + // the running set until the copy is started by the handler. + updateTransitions(TransitionData(config)) { add(transition) } + transition.addListener(transitionListener) + + handler.post { + if (config.terminatePrevious) { + TransitionManager.endTransitions(constraintLayout) + } + + TransitionManager.beginDelayedTransition(constraintLayout, transition) + apply() + + // Delay removal until after copied transition has started + handler.post { updateTransitions(null) { remove(transition) } } + } + } + + companion object { + private const val TAG = "KeyguardBlueprintViewModel" + private const val DEBUG = true + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt index aaec69f4f022..1ec2a4969f0d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt @@ -58,6 +58,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combineTransform @@ -67,13 +69,14 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.stateIn @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class KeyguardRootViewModel @Inject constructor( - @Application private val scope: CoroutineScope, + @Application private val applicationScope: CoroutineScope, private val deviceEntryInteractor: DeviceEntryInteractor, private val dozeParameters: DozeParameters, private val keyguardInteractor: KeyguardInteractor, @@ -280,7 +283,7 @@ constructor( burnInJob?.cancel() burnInJob = - scope.launch("$TAG#aodBurnInViewModel") { + applicationScope.launch("$TAG#aodBurnInViewModel") { aodBurnInViewModel.movement(params).collect { _burnInModel.value = it } } } @@ -294,7 +297,7 @@ constructor( } /** Is the notification icon container visible? */ - val isNotifIconContainerVisible: Flow<AnimatedValue<Boolean>> = + val isNotifIconContainerVisible: StateFlow<AnimatedValue<Boolean>> = combine( goneToAodTransitionRunning, keyguardTransitionInteractor.finishedKeyguardState.map { @@ -336,11 +339,15 @@ constructor( } } } - .distinctUntilChanged() + .stateIn( + scope = applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = AnimatedValue.NotAnimating(false), + ) - fun onNotificationContainerBoundsChanged(top: Float, bottom: Float) { + fun onNotificationContainerBoundsChanged(top: Float, bottom: Float, animate: Boolean = false) { keyguardInteractor.setNotificationContainerBounds( - NotificationContainerBounds(top = top, bottom = bottom) + NotificationContainerBounds(top = top, bottom = bottom, isAnimated = animate) ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt index a18b0330d48f..ec2a1d305ab3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelTest.kt @@ -17,9 +17,11 @@ package com.android.systemui.keyguard.ui.viewmodel +import android.os.fakeExecutorHandler import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor +import com.android.systemui.testKosmos import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -33,12 +35,16 @@ import org.mockito.MockitoAnnotations class KeyguardBlueprintViewModelTest : SysuiTestCase() { @Mock private lateinit var keyguardBlueprintInteractor: KeyguardBlueprintInteractor private lateinit var undertest: KeyguardBlueprintViewModel + private val kosmos = testKosmos() @Before fun setup() { MockitoAnnotations.initMocks(this) undertest = - KeyguardBlueprintViewModel(keyguardBlueprintInteractor = keyguardBlueprintInteractor) + KeyguardBlueprintViewModel( + handler = kosmos.fakeExecutorHandler, + keyguardBlueprintInteractor = keyguardBlueprintInteractor, + ) } @Test diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinderKosmos.kt deleted file mode 100644 index 24d2c2f5dae1..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinderKosmos.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2023 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.keyguard.ui.binder - -import android.os.fakeExecutorHandler -import com.android.systemui.kosmos.Kosmos - -val Kosmos.keyguardBlueprintViewBinder by - Kosmos.Fixture { KeyguardBlueprintViewBinder(fakeExecutorHandler) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt index 63b87c075378..0c538ff1d6fe 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModelKosmos.kt @@ -16,8 +16,14 @@ package com.android.systemui.keyguard.ui.viewmodel +import android.os.fakeExecutorHandler import com.android.systemui.keyguard.domain.interactor.keyguardBlueprintInteractor import com.android.systemui.kosmos.Kosmos val Kosmos.keyguardBlueprintViewModel by - Kosmos.Fixture { KeyguardBlueprintViewModel(keyguardBlueprintInteractor) } + Kosmos.Fixture { + KeyguardBlueprintViewModel( + fakeExecutorHandler, + keyguardBlueprintInteractor, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt index f856d2700270..2567ffee9be8 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt @@ -32,7 +32,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi val Kosmos.keyguardRootViewModel by Fixture { KeyguardRootViewModel( - scope = applicationCoroutineScope, + applicationScope = applicationCoroutineScope, deviceEntryInteractor = deviceEntryInteractor, dozeParameters = dozeParameters, keyguardInteractor = keyguardInteractor, |