Merge "[Status bar] Delay showing the status bar during dream transition." into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
e0ff509876
@@ -53,6 +53,7 @@ import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
|
||||
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
|
||||
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder;
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
|
||||
@@ -158,6 +159,7 @@ public abstract class StatusBarViewModule {
|
||||
StatusBarIconController statusBarIconController,
|
||||
StatusBarIconController.DarkIconManager.Factory darkIconManagerFactory,
|
||||
CollapsedStatusBarViewModel collapsedStatusBarViewModel,
|
||||
CollapsedStatusBarViewBinder collapsedStatusBarViewBinder,
|
||||
StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
|
||||
KeyguardStateController keyguardStateController,
|
||||
ShadeViewController shadeViewController,
|
||||
@@ -182,6 +184,7 @@ public abstract class StatusBarViewModule {
|
||||
statusBarIconController,
|
||||
darkIconManagerFactory,
|
||||
collapsedStatusBarViewModel,
|
||||
collapsedStatusBarViewBinder,
|
||||
statusBarHideIconsForBouncerManager,
|
||||
keyguardStateController,
|
||||
shadeViewController,
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone.fragment;
|
||||
|
||||
|
||||
|
||||
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.IDLE;
|
||||
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.SHOWING_PERSISTENT_DOT;
|
||||
|
||||
@@ -69,6 +67,7 @@ import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentCom
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener;
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder;
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener;
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
|
||||
@@ -131,6 +130,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
private final StatusBarIconController mStatusBarIconController;
|
||||
private final CarrierConfigTracker mCarrierConfigTracker;
|
||||
private final CollapsedStatusBarViewModel mCollapsedStatusBarViewModel;
|
||||
private final CollapsedStatusBarViewBinder mCollapsedStatusBarViewBinder;
|
||||
private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
|
||||
private final StatusBarIconController.DarkIconManager.Factory mDarkIconManagerFactory;
|
||||
private final SecureSettings mSecureSettings;
|
||||
@@ -182,12 +182,22 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
*/
|
||||
private boolean mWaitingForWindowStateChangeAfterCameraLaunch = false;
|
||||
|
||||
/**
|
||||
* True when a transition from lockscreen to dream has started, but haven't yet received a
|
||||
* status bar window state change afterward.
|
||||
*
|
||||
* Similar to [mWaitingForWindowStateChangeAfterCameraLaunch].
|
||||
*/
|
||||
private boolean mTransitionFromLockscreenToDreamStarted = false;
|
||||
|
||||
/**
|
||||
* Listener that updates {@link #mWaitingForWindowStateChangeAfterCameraLaunch} when it receives
|
||||
* a new status bar window state.
|
||||
*/
|
||||
private final StatusBarWindowStateListener mStatusBarWindowStateListener = state ->
|
||||
mWaitingForWindowStateChangeAfterCameraLaunch = false;
|
||||
private final StatusBarWindowStateListener mStatusBarWindowStateListener = state -> {
|
||||
mWaitingForWindowStateChangeAfterCameraLaunch = false;
|
||||
mTransitionFromLockscreenToDreamStarted = false;
|
||||
};
|
||||
|
||||
@SuppressLint("ValidFragment")
|
||||
public CollapsedStatusBarFragment(
|
||||
@@ -201,6 +211,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
StatusBarIconController statusBarIconController,
|
||||
StatusBarIconController.DarkIconManager.Factory darkIconManagerFactory,
|
||||
CollapsedStatusBarViewModel collapsedStatusBarViewModel,
|
||||
CollapsedStatusBarViewBinder collapsedStatusBarViewBinder,
|
||||
StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
|
||||
KeyguardStateController keyguardStateController,
|
||||
ShadeViewController shadeViewController,
|
||||
@@ -224,6 +235,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
mFeatureFlags = featureFlags;
|
||||
mStatusBarIconController = statusBarIconController;
|
||||
mCollapsedStatusBarViewModel = collapsedStatusBarViewModel;
|
||||
mCollapsedStatusBarViewBinder = collapsedStatusBarViewBinder;
|
||||
mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
|
||||
mDarkIconManagerFactory = darkIconManagerFactory;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
@@ -296,8 +308,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
mCarrierConfigTracker.addCallback(mCarrierConfigCallback);
|
||||
mCarrierConfigTracker.addDefaultDataSubscriptionChangedListener(mDefaultDataListener);
|
||||
|
||||
CollapsedStatusBarViewBinder.bind(
|
||||
mStatusBar, mCollapsedStatusBarViewModel, this::updateStatusBarVisibilities);
|
||||
mCollapsedStatusBarViewBinder.bind(
|
||||
mStatusBar, mCollapsedStatusBarViewModel, mStatusBarVisibilityChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -411,6 +423,19 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
return mStatusBarFragmentComponent;
|
||||
}
|
||||
|
||||
private StatusBarVisibilityChangeListener mStatusBarVisibilityChangeListener =
|
||||
new StatusBarVisibilityChangeListener() {
|
||||
@Override
|
||||
public void onStatusBarVisibilityMaybeChanged() {
|
||||
updateStatusBarVisibilities(/* animate= */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionFromLockscreenToDreamStarted() {
|
||||
mTransitionFromLockscreenToDreamStarted = true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void disable(int displayId, int state1, int state2, boolean animate) {
|
||||
if (displayId != getContext().getDisplayId()) {
|
||||
@@ -423,10 +448,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
updateStatusBarVisibilities(animate);
|
||||
}
|
||||
|
||||
private void updateStatusBarVisibilities() {
|
||||
updateStatusBarVisibilities(/* animate= */ true);
|
||||
}
|
||||
|
||||
private void updateStatusBarVisibilities(boolean animate) {
|
||||
StatusBarVisibilityModel previousModel = mLastModifiedVisibility;
|
||||
StatusBarVisibilityModel newModel = calculateInternalModel(mLastSystemVisibility);
|
||||
@@ -546,6 +567,18 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
return true;
|
||||
}
|
||||
|
||||
// Similar to [hideIconsForSecureCamera]: When dream is launched over lockscreen, the icons
|
||||
// are momentarily visible because the dream animation has finished, but SysUI has not been
|
||||
// informed that the dream is full-screen. For extra safety, we double-check that we're
|
||||
// still dreaming.
|
||||
final boolean hideIconsForDream =
|
||||
mTransitionFromLockscreenToDreamStarted
|
||||
&& mKeyguardUpdateMonitor.isDreaming()
|
||||
&& mKeyguardStateController.isOccluded();
|
||||
if (hideIconsForDream) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// While the status bar is transitioning from lockscreen to an occluded, we don't yet know
|
||||
// if the occluding activity is fullscreen or not. If it *is* fullscreen, we don't want to
|
||||
// briefly show the status bar just to immediately hide it again. So, we wait for the
|
||||
|
||||
@@ -44,6 +44,8 @@ import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerPr
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerProxyImpl
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinderImpl
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositorySwitcher
|
||||
@@ -107,6 +109,11 @@ abstract class StatusBarPipelineModule {
|
||||
impl: CollapsedStatusBarViewModelImpl
|
||||
): CollapsedStatusBarViewModel
|
||||
|
||||
@Binds
|
||||
abstract fun collapsedStatusBarViewBinder(
|
||||
impl: CollapsedStatusBarViewBinderImpl
|
||||
): CollapsedStatusBarViewBinder
|
||||
|
||||
companion object {
|
||||
@Provides
|
||||
@SysUISingleton
|
||||
|
||||
@@ -19,34 +19,61 @@ package com.android.systemui.statusbar.pipeline.shared.ui.binder
|
||||
import android.view.View
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.lifecycle.repeatWhenAttached
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
object CollapsedStatusBarViewBinder {
|
||||
/**
|
||||
* Interface to assist with binding the [CollapsedStatusBarFragment] to
|
||||
* [CollapsedStatusBarViewModel]. Used only to enable easy testing of [CollapsedStatusBarFragment].
|
||||
*/
|
||||
interface CollapsedStatusBarViewBinder {
|
||||
/**
|
||||
* Binds the view to the view-model. [listener] will be notified whenever an event that may
|
||||
* change the status bar visibility occurs.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun bind(
|
||||
view: View,
|
||||
viewModel: CollapsedStatusBarViewModel,
|
||||
listener: StatusBarVisibilityChangeListener,
|
||||
)
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
class CollapsedStatusBarViewBinderImpl @Inject constructor() : CollapsedStatusBarViewBinder {
|
||||
override fun bind(
|
||||
view: View,
|
||||
viewModel: CollapsedStatusBarViewModel,
|
||||
listener: StatusBarVisibilityChangeListener,
|
||||
) {
|
||||
view.repeatWhenAttached {
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
viewModel.isTransitioningFromLockscreenToOccluded.collect {
|
||||
listener.onStatusBarVisibilityMaybeChanged()
|
||||
launch {
|
||||
viewModel.isTransitioningFromLockscreenToOccluded.collect {
|
||||
listener.onStatusBarVisibilityMaybeChanged()
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
viewModel.transitionFromLockscreenToDreamStartedEvent.collect {
|
||||
listener.onTransitionFromLockscreenToDreamStarted()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener to be notified when the status bar visibility might have changed due to the device
|
||||
* moving to a different state.
|
||||
*/
|
||||
fun interface StatusBarVisibilityChangeListener {
|
||||
/** Listener for various events that may affect the status bar's visibility. */
|
||||
interface StatusBarVisibilityChangeListener {
|
||||
/**
|
||||
* Called when the status bar visibility might have changed due to the device moving to a
|
||||
* different state.
|
||||
*/
|
||||
fun onStatusBarVisibilityMaybeChanged()
|
||||
|
||||
/** Called when a transition from lockscreen to dream has started. */
|
||||
fun onTransitionFromLockscreenToDreamStarted()
|
||||
}
|
||||
|
||||
@@ -22,8 +22,10 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
|
||||
import com.android.systemui.keyguard.shared.model.TransitionState
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
@@ -43,6 +45,9 @@ interface CollapsedStatusBarViewModel {
|
||||
* otherwise.
|
||||
*/
|
||||
val isTransitioningFromLockscreenToOccluded: StateFlow<Boolean>
|
||||
|
||||
/** Emits whenever a transition from lockscreen to dream has started. */
|
||||
val transitionFromLockscreenToDreamStartedEvent: Flow<Unit>
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
@@ -59,4 +64,9 @@ constructor(
|
||||
it.transitionState == TransitionState.RUNNING
|
||||
}
|
||||
.stateIn(coroutineScope, SharingStarted.WhileSubscribed(), initialValue = false)
|
||||
|
||||
override val transitionFromLockscreenToDreamStartedEvent: Flow<Unit> =
|
||||
keyguardTransitionInteractor.lockscreenToDreamingTransition
|
||||
.filter { it.transitionState == TransitionState.STARTED }
|
||||
.map {}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconController;
|
||||
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
|
||||
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeCollapsedStatusBarViewBinder;
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeCollapsedStatusBarViewModel;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
|
||||
@@ -129,6 +130,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
@Mock
|
||||
private StatusBarIconController.DarkIconManager mIconManager;
|
||||
private FakeCollapsedStatusBarViewModel mCollapsedStatusBarViewModel;
|
||||
private FakeCollapsedStatusBarViewBinder mCollapsedStatusBarViewBinder;
|
||||
@Mock
|
||||
private StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
|
||||
@Mock
|
||||
@@ -612,6 +614,55 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
assertEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusBarIcons_hiddenThroughoutLockscreenToDreamTransition() {
|
||||
final CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
|
||||
// WHEN a transition to dream has started
|
||||
mCollapsedStatusBarViewBinder.getListener().onTransitionFromLockscreenToDreamStarted();
|
||||
when(mKeyguardUpdateMonitor.isDreaming()).thenReturn(true);
|
||||
when(mKeyguardStateController.isOccluded()).thenReturn(true);
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
// THEN status icons should be invisible or gone, but certainly not VISIBLE.
|
||||
assertNotEquals(View.VISIBLE, getEndSideContentView().getVisibility());
|
||||
assertNotEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
|
||||
// WHEN the transition has finished and dream is displaying
|
||||
mockLockscreenToDreamTransitionFinished();
|
||||
// (This approximates "dream is displaying")
|
||||
when(mStatusBarHideIconsForBouncerManager.getShouldHideStatusBarIconsForBouncer())
|
||||
.thenReturn(true);
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
// THEN the views still aren't visible because dream is hiding them
|
||||
assertNotEquals(View.VISIBLE, getEndSideContentView().getVisibility());
|
||||
assertNotEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
|
||||
// WHEN dream has ended
|
||||
when(mStatusBarHideIconsForBouncerManager.getShouldHideStatusBarIconsForBouncer())
|
||||
.thenReturn(false);
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
// THEN the views can be visible again
|
||||
assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusBarIcons_lockscreenToDreamTransitionButNotDreaming_iconsVisible() {
|
||||
final CollapsedStatusBarFragment fragment = resumeAndGetFragment();
|
||||
|
||||
// WHEN a transition to dream has started but we're *not* dreaming
|
||||
mCollapsedStatusBarViewBinder.getListener().onTransitionFromLockscreenToDreamStarted();
|
||||
when(mKeyguardUpdateMonitor.isDreaming()).thenReturn(false);
|
||||
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
|
||||
|
||||
// THEN the views are still visible
|
||||
assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
|
||||
assertEquals(View.VISIBLE, getClockView().getVisibility());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Fragment instantiate(Context context, String className, Bundle arguments) {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -631,6 +682,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
|
||||
mShadeExpansionStateManager = new ShadeExpansionStateManager();
|
||||
mCollapsedStatusBarViewModel = new FakeCollapsedStatusBarViewModel();
|
||||
mCollapsedStatusBarViewBinder = new FakeCollapsedStatusBarViewBinder();
|
||||
|
||||
setUpNotificationIconAreaController();
|
||||
return new CollapsedStatusBarFragment(
|
||||
@@ -644,6 +696,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
mStatusBarIconController,
|
||||
mIconManagerFactory,
|
||||
mCollapsedStatusBarViewModel,
|
||||
mCollapsedStatusBarViewBinder,
|
||||
mStatusBarHideIconsForBouncerManager,
|
||||
mKeyguardStateController,
|
||||
mShadeViewController,
|
||||
@@ -718,6 +771,12 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void mockLockscreenToDreamTransitionFinished() {
|
||||
for (StatusBarWindowStateListener listener : mStatusBarWindowStateListeners) {
|
||||
listener.onStatusBarWindowStateChanged(StatusBarManager.WINDOW_STATE_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
private CollapsedStatusBarFragment resumeAndGetFragment() {
|
||||
mFragments.dispatchResume();
|
||||
processAllMessages();
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
|
||||
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.coroutines.collectValues
|
||||
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||
import com.android.systemui.keyguard.shared.model.KeyguardState
|
||||
@@ -176,4 +177,139 @@ class CollapsedStatusBarViewModelImplTest : SysuiTestCase() {
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transitionFromLockscreenToDreamStartedEvent_started_emitted() =
|
||||
testScope.runTest {
|
||||
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
|
||||
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
value = 0f,
|
||||
TransitionState.STARTED,
|
||||
)
|
||||
)
|
||||
|
||||
assertThat(emissions.size).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transitionFromLockscreenToDreamStartedEvent_startedMultiple_emittedMultiple() =
|
||||
testScope.runTest {
|
||||
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
|
||||
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
value = 0f,
|
||||
TransitionState.STARTED,
|
||||
)
|
||||
)
|
||||
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
value = 0f,
|
||||
TransitionState.STARTED,
|
||||
)
|
||||
)
|
||||
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
value = 0f,
|
||||
TransitionState.STARTED,
|
||||
)
|
||||
)
|
||||
|
||||
assertThat(emissions.size).isEqualTo(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transitionFromLockscreenToDreamStartedEvent_startedThenRunning_emittedOnlyOne() =
|
||||
testScope.runTest {
|
||||
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
|
||||
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
value = 0f,
|
||||
TransitionState.STARTED,
|
||||
)
|
||||
)
|
||||
assertThat(emissions.size).isEqualTo(1)
|
||||
|
||||
// WHEN the transition progresses through its animation by going through the RUNNING
|
||||
// step with increasing fractions
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
value = .1f,
|
||||
TransitionState.RUNNING,
|
||||
)
|
||||
)
|
||||
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
value = .2f,
|
||||
TransitionState.RUNNING,
|
||||
)
|
||||
)
|
||||
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
value = .3f,
|
||||
TransitionState.RUNNING,
|
||||
)
|
||||
)
|
||||
|
||||
// THEN the flow does not emit since the flow should only emit when the transition
|
||||
// starts
|
||||
assertThat(emissions.size).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transitionFromLockscreenToDreamStartedEvent_irrelevantTransition_notEmitted() =
|
||||
testScope.runTest {
|
||||
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
|
||||
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.OCCLUDED,
|
||||
value = 0f,
|
||||
TransitionState.STARTED,
|
||||
)
|
||||
)
|
||||
|
||||
assertThat(emissions).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transitionFromLockscreenToDreamStartedEvent_irrelevantTransitionState_notEmitted() =
|
||||
testScope.runTest {
|
||||
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
|
||||
|
||||
keyguardTransitionRepository.sendTransitionStep(
|
||||
TransitionStep(
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
value = 1.0f,
|
||||
TransitionState.FINISHED,
|
||||
)
|
||||
)
|
||||
|
||||
assertThat(emissions).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.statusbar.pipeline.shared.ui.viewmodel
|
||||
|
||||
import android.view.View
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder
|
||||
import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener
|
||||
|
||||
/**
|
||||
* A fake view binder that can be used from Java tests.
|
||||
*
|
||||
* Since Java tests can't run tests within test scopes, we need to bypass the flows from
|
||||
* [CollapsedStatusBarViewModel] and just trigger the listener directly.
|
||||
*/
|
||||
class FakeCollapsedStatusBarViewBinder : CollapsedStatusBarViewBinder {
|
||||
var listener: StatusBarVisibilityChangeListener? = null
|
||||
|
||||
override fun bind(
|
||||
view: View,
|
||||
viewModel: CollapsedStatusBarViewModel,
|
||||
listener: StatusBarVisibilityChangeListener,
|
||||
) {
|
||||
this.listener = listener
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
|
||||
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class FakeCollapsedStatusBarViewModel : CollapsedStatusBarViewModel {
|
||||
override val isTransitioningFromLockscreenToOccluded = MutableStateFlow(false)
|
||||
|
||||
override val transitionFromLockscreenToDreamStartedEvent = MutableSharedFlow<Unit>()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user