diff options
8 files changed, 282 insertions, 17 deletions
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index f37d22146b25..584823746662 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1275,6 +1275,9 @@ <!-- DREAMING -> LOCKSCREEN transition: Amount to shift lockscreen content on entering --> <dimen name="dreaming_to_lockscreen_transition_lockscreen_translation_y">40dp</dimen> + <!-- OCCLUDED -> LOCKSCREEN transition: Amount to shift lockscreen content on entering --> + <dimen name="occluded_to_lockscreen_transition_lockscreen_translation_y">40dp</dimen> + <!-- The amount of vertical offset for the keyguard during the full shade transition. --> <dimen name="lockscreen_shade_keyguard_transition_vertical_offset">0dp</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt index 937e8ffd9f61..88789019b10f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt @@ -80,7 +80,7 @@ constructor( name, KeyguardState.OCCLUDED, KeyguardState.LOCKSCREEN, - getAnimator(), + getAnimator(TO_LOCKSCREEN_DURATION), ) ) } @@ -97,6 +97,6 @@ constructor( companion object { private val DEFAULT_DURATION = 500.milliseconds - val TO_LOCKSCREEN_DURATION = 1183.milliseconds + val TO_LOCKSCREEN_DURATION = 933.milliseconds } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt index 3b9d6f59a8e7..04024be571c8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt @@ -24,7 +24,9 @@ import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN +import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionState.STARTED import com.android.systemui.keyguard.shared.model.TransitionStep import javax.inject.Inject import kotlin.time.Duration @@ -50,6 +52,10 @@ constructor( val dreamingToLockscreenTransition: Flow<TransitionStep> = repository.transition(DREAMING, LOCKSCREEN) + /** OCCLUDED->LOCKSCREEN transition information. */ + val occludedToLockscreenTransition: Flow<TransitionStep> = + repository.transition(OCCLUDED, LOCKSCREEN) + /** (any)->AOD transition information */ val anyStateToAodTransition: Flow<TransitionStep> = repository.transitions.filter { step -> step.to == KeyguardState.AOD } @@ -93,7 +99,14 @@ constructor( val start = (params.startTime / totalDuration).toFloat() val chunks = (totalDuration / params.duration).toFloat() return flow - .map { step -> (step.value - start) * chunks } + // When starting, emit a value of 0f to give animations a chance to set initial state + .map { step -> + if (step.transitionState == STARTED) { + 0f + } else { + (step.value - start) * chunks + } + } .filter { value -> value >= 0f && value <= 1f } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt new file mode 100644 index 000000000000..e804562bc85f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 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.viewmodel + +import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.AnimationParams +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +/** + * Breaks down OCCLUDED->LOCKSCREEN transition into discrete steps for corresponding views to + * consume. + */ +@SysUISingleton +class OccludedToLockscreenTransitionViewModel +@Inject +constructor( + private val interactor: KeyguardTransitionInteractor, +) { + /** Lockscreen views y-translation */ + fun lockscreenTranslationY(translatePx: Int): Flow<Float> { + return flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value -> + -translatePx + (EMPHASIZED_DECELERATE.getInterpolation(value) * translatePx) + } + } + + /** Lockscreen views alpha */ + val lockscreenAlpha: Flow<Float> = flowForAnimation(LOCKSCREEN_ALPHA) + + private fun flowForAnimation(params: AnimationParams): Flow<Float> { + return interactor.transitionStepAnimation( + interactor.occludedToLockscreenTransition, + params, + totalDuration = TO_LOCKSCREEN_DURATION + ) + } + + companion object { + @JvmField val LOCKSCREEN_ANIMATION_DURATION_MS = TO_LOCKSCREEN_DURATION.inWholeMilliseconds + val LOCKSCREEN_TRANSLATION_Y = AnimationParams(duration = TO_LOCKSCREEN_DURATION) + val LOCKSCREEN_ALPHA = + AnimationParams(startTime = 233.milliseconds, duration = 250.milliseconds) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 8054f27029ae..fe9b73315e72 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -144,6 +144,7 @@ import com.android.systemui.keyguard.shared.model.TransitionState; import com.android.systemui.keyguard.shared.model.TransitionStep; import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel; import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel; +import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel; import com.android.systemui.media.controls.pipeline.MediaDataManager; import com.android.systemui.media.controls.ui.KeyguardMediaController; import com.android.systemui.media.controls.ui.MediaHierarchyManager; @@ -238,6 +239,8 @@ import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Provider; +import kotlinx.coroutines.CoroutineDispatcher; + @CentralSurfacesComponent.CentralSurfacesScope public final class NotificationPanelViewController implements Dumpable { @@ -683,10 +686,13 @@ public final class NotificationPanelViewController implements Dumpable { private boolean mIgnoreXTouchSlop; private boolean mExpandLatencyTracking; private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel; + private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel; private KeyguardTransitionInteractor mKeyguardTransitionInteractor; - private boolean mIsDreamToLockscreenTransitionRunning = false; + private CoroutineDispatcher mMainDispatcher; + private boolean mIsToLockscreenTransitionRunning = false; private int mDreamingToLockscreenTransitionTranslationY; + private int mOccludedToLockscreenTransitionTranslationY; private boolean mUnocclusionTransitionFlagEnabled = false; private final Runnable mFlingCollapseRunnable = () -> fling(0, false /* expand */, @@ -705,7 +711,13 @@ public final class NotificationPanelViewController implements Dumpable { private final Consumer<TransitionStep> mDreamingToLockscreenTransition = (TransitionStep step) -> { - mIsDreamToLockscreenTransitionRunning = + mIsToLockscreenTransitionRunning = + step.getTransitionState() == TransitionState.RUNNING; + }; + + private final Consumer<TransitionStep> mOccludedToLockscreenTransition = + (TransitionStep step) -> { + mIsToLockscreenTransitionRunning = step.getTransitionState() == TransitionState.RUNNING; }; @@ -778,6 +790,8 @@ public final class NotificationPanelViewController implements Dumpable { KeyguardBottomAreaViewModel keyguardBottomAreaViewModel, KeyguardBottomAreaInteractor keyguardBottomAreaInteractor, DreamingToLockscreenTransitionViewModel dreamingToLockscreenTransitionViewModel, + OccludedToLockscreenTransitionViewModel occludedToLockscreenTransitionViewModel, + @Main CoroutineDispatcher mainDispatcher, KeyguardTransitionInteractor keyguardTransitionInteractor, DumpManager dumpManager) { keyguardStateController.addCallback(new KeyguardStateController.Callback() { @@ -795,6 +809,7 @@ public final class NotificationPanelViewController implements Dumpable { mShadeHeightLogger = shadeHeightLogger; mGutsManager = gutsManager; mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel; + mOccludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel; mKeyguardTransitionInteractor = keyguardTransitionInteractor; mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override @@ -873,6 +888,7 @@ public final class NotificationPanelViewController implements Dumpable { mFalsingCollector = falsingCollector; mPowerManager = powerManager; mWakeUpCoordinator = coordinator; + mMainDispatcher = mainDispatcher; mAccessibilityManager = accessibilityManager; mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle()); setPanelAlpha(255, false /* animate */); @@ -1097,15 +1113,27 @@ public final class NotificationPanelViewController implements Dumpable { controller.setup(mNotificationContainerParent)); if (mUnocclusionTransitionFlagEnabled) { + // Dreaming->Lockscreen + collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(), + mDreamingToLockscreenTransition, mMainDispatcher); collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(), - dreamingToLockscreenTransitionAlpha(mNotificationStackScrollLayoutController)); - + toLockscreenTransitionAlpha(mNotificationStackScrollLayoutController), + mMainDispatcher); collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY( mDreamingToLockscreenTransitionTranslationY), - dreamingToLockscreenTransitionY(mNotificationStackScrollLayoutController)); + toLockscreenTransitionY(mNotificationStackScrollLayoutController), + mMainDispatcher); - collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(), - mDreamingToLockscreenTransition); + // Occluded->Lockscreen + collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(), + mOccludedToLockscreenTransition, mMainDispatcher); + collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(), + toLockscreenTransitionAlpha(mNotificationStackScrollLayoutController), + mMainDispatcher); + collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY( + mOccludedToLockscreenTransitionTranslationY), + toLockscreenTransitionY(mNotificationStackScrollLayoutController), + mMainDispatcher); } } @@ -1143,6 +1171,8 @@ public final class NotificationPanelViewController implements Dumpable { R.dimen.split_shade_scrim_transition_distance); mDreamingToLockscreenTransitionTranslationY = mResources.getDimensionPixelSize( R.dimen.dreaming_to_lockscreen_transition_lockscreen_translation_y); + mOccludedToLockscreenTransitionTranslationY = mResources.getDimensionPixelSize( + R.dimen.occluded_to_lockscreen_transition_lockscreen_translation_y); } private void updateViewControllers(KeyguardStatusView keyguardStatusView, @@ -1806,7 +1836,7 @@ public final class NotificationPanelViewController implements Dumpable { } private void updateClock() { - if (mIsDreamToLockscreenTransitionRunning) { + if (mIsToLockscreenTransitionRunning) { return; } float alpha = mClockPositionResult.clockAlpha * mKeyguardOnlyContentAlpha; @@ -2697,7 +2727,7 @@ public final class NotificationPanelViewController implements Dumpable { } else if (statusBarState == KEYGUARD || statusBarState == StatusBarState.SHADE_LOCKED) { mKeyguardBottomArea.setVisibility(View.VISIBLE); - if (!mIsDreamToLockscreenTransitionRunning) { + if (!mIsToLockscreenTransitionRunning) { mKeyguardBottomArea.setAlpha(1f); } } else { @@ -3566,7 +3596,7 @@ public final class NotificationPanelViewController implements Dumpable { } private void updateNotificationTranslucency() { - if (mIsDreamToLockscreenTransitionRunning) { + if (mIsToLockscreenTransitionRunning) { return; } float alpha = 1f; @@ -3624,7 +3654,7 @@ public final class NotificationPanelViewController implements Dumpable { } private void updateKeyguardBottomAreaAlpha() { - if (mIsDreamToLockscreenTransitionRunning) { + if (mIsToLockscreenTransitionRunning) { return; } // There are two possible panel expansion behaviors: @@ -5856,7 +5886,7 @@ public final class NotificationPanelViewController implements Dumpable { mCurrentPanelState = state; } - private Consumer<Float> dreamingToLockscreenTransitionAlpha( + private Consumer<Float> toLockscreenTransitionAlpha( NotificationStackScrollLayoutController stackScroller) { return (Float alpha) -> { mKeyguardStatusViewController.setAlpha(alpha); @@ -5874,7 +5904,7 @@ public final class NotificationPanelViewController implements Dumpable { }; } - private Consumer<Float> dreamingToLockscreenTransitionY( + private Consumer<Float> toLockscreenTransitionY( NotificationStackScrollLayoutController stackScroller) { return (Float translationY) -> { mKeyguardStatusViewController.setTranslationY(translationY, /* excludeMedia= */false); diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt index 9653985cb6e6..d6b3b22bfd02 100644 --- a/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt @@ -21,6 +21,8 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.lifecycle.repeatWhenAttached import java.util.function.Consumer +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect @@ -34,7 +36,10 @@ fun <T> collectFlow( view: View, flow: Flow<T>, consumer: Consumer<T>, + coroutineContext: CoroutineContext = EmptyCoroutineContext, state: Lifecycle.State = Lifecycle.State.CREATED, ) { - view.repeatWhenAttached { repeatOnLifecycle(state) { flow.collect { consumer.accept(it) } } } + view.repeatWhenAttached(coroutineContext) { + repeatOnLifecycle(state) { flow.collect { consumer.accept(it) } } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt new file mode 100644 index 000000000000..98d292d689e4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2022 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.viewmodel + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.AnimationParams +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel.Companion.LOCKSCREEN_ALPHA +import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel.Companion.LOCKSCREEN_TRANSLATION_Y +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@SmallTest +@RunWith(JUnit4::class) +class OccludedToLockscreenTransitionViewModelTest : SysuiTestCase() { + private lateinit var underTest: OccludedToLockscreenTransitionViewModel + private lateinit var repository: FakeKeyguardTransitionRepository + + @Before + fun setUp() { + repository = FakeKeyguardTransitionRepository() + val interactor = KeyguardTransitionInteractor(repository) + underTest = OccludedToLockscreenTransitionViewModel(interactor) + } + + @Test + fun lockscreenFadeIn() = + runTest(UnconfinedTestDispatcher()) { + val values = mutableListOf<Float>() + + val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this) + + repository.sendTransitionStep(step(0f)) + // Should start running here... + repository.sendTransitionStep(step(0.3f)) + repository.sendTransitionStep(step(0.4f)) + repository.sendTransitionStep(step(0.5f)) + // ...up to here + repository.sendTransitionStep(step(0.6f)) + repository.sendTransitionStep(step(1f)) + + // Only two values should be present, since the dream overlay runs for a small fraction + // of the overall animation time + assertThat(values.size).isEqualTo(3) + assertThat(values[0]).isEqualTo(animValue(0.3f, LOCKSCREEN_ALPHA)) + assertThat(values[1]).isEqualTo(animValue(0.4f, LOCKSCREEN_ALPHA)) + assertThat(values[2]).isEqualTo(animValue(0.5f, LOCKSCREEN_ALPHA)) + + job.cancel() + } + + @Test + fun lockscreenTranslationY() = + runTest(UnconfinedTestDispatcher()) { + val values = mutableListOf<Float>() + + val pixels = 100 + val job = + underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this) + + repository.sendTransitionStep(step(0f)) + repository.sendTransitionStep(step(0.3f)) + repository.sendTransitionStep(step(0.5f)) + repository.sendTransitionStep(step(1f)) + + assertThat(values.size).isEqualTo(4) + assertThat(values[0]) + .isEqualTo( + -pixels + + EMPHASIZED_DECELERATE.getInterpolation( + animValue(0f, LOCKSCREEN_TRANSLATION_Y) + ) * pixels + ) + assertThat(values[1]) + .isEqualTo( + -pixels + + EMPHASIZED_DECELERATE.getInterpolation( + animValue(0.3f, LOCKSCREEN_TRANSLATION_Y) + ) * pixels + ) + assertThat(values[2]) + .isEqualTo( + -pixels + + EMPHASIZED_DECELERATE.getInterpolation( + animValue(0.5f, LOCKSCREEN_TRANSLATION_Y) + ) * pixels + ) + assertThat(values[3]) + .isEqualTo( + -pixels + + EMPHASIZED_DECELERATE.getInterpolation( + animValue(1f, LOCKSCREEN_TRANSLATION_Y) + ) * pixels + ) + + job.cancel() + } + + private fun animValue(stepValue: Float, params: AnimationParams): Float { + val totalDuration = TO_LOCKSCREEN_DURATION + val startValue = (params.startTime / totalDuration).toFloat() + + val multiplier = (totalDuration / params.duration).toFloat() + return (stepValue - startValue) * multiplier + } + + private fun step(value: Float): TransitionStep { + return TransitionStep( + from = KeyguardState.OCCLUDED, + to = KeyguardState.LOCKSCREEN, + value = value, + transitionState = TransitionState.RUNNING, + ownerName = "OccludedToLockscreenTransitionViewModelTest" + ) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java index ad993c391bcd..65b2ac0eb2d3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java @@ -107,6 +107,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInterac import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel; import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel; +import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel; import com.android.systemui.media.controls.pipeline.MediaDataManager; import com.android.systemui.media.controls.ui.KeyguardMediaController; import com.android.systemui.media.controls.ui.MediaHierarchyManager; @@ -188,6 +189,8 @@ import org.mockito.stubbing.Answer; import java.util.List; import java.util.Optional; +import kotlinx.coroutines.CoroutineDispatcher; + @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @@ -289,7 +292,9 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { @Mock private KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel; @Mock private KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor; @Mock private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel; + @Mock private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel; @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor; + @Mock private CoroutineDispatcher mMainDispatcher; @Mock private MotionEvent mDownMotionEvent; @Captor private ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener> @@ -507,6 +512,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mKeyguardBottomAreaViewModel, mKeyguardBottomAreaInteractor, mDreamingToLockscreenTransitionViewModel, + mOccludedToLockscreenTransitionViewModel, + mMainDispatcher, mKeyguardTransitionInteractor, mDumpManager); mNotificationPanelViewController.initDependencies( |