Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b11171ee authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[Status bar] Delay showing the status bar during dream transition.

Bug: 273314977
Test: manual: trigger lockscreen to dream transition -> verify that the
status bar icons in the top left don't flicker visible for a few frames
(see video attached to bug)
Test: atest CollapsedStatusBarFragmentTest
CollapsedStatusBarViewModelTest

Change-Id: I3474a5c7f6f485e8d26ffc92eac31a9b08901d51
parent 541ef6fb
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -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.CollapsedStatusBarFragmentLogger;
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
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.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
@@ -158,6 +159,7 @@ public abstract class StatusBarViewModule {
            StatusBarIconController statusBarIconController,
            StatusBarIconController statusBarIconController,
            StatusBarIconController.DarkIconManager.Factory darkIconManagerFactory,
            StatusBarIconController.DarkIconManager.Factory darkIconManagerFactory,
            CollapsedStatusBarViewModel collapsedStatusBarViewModel,
            CollapsedStatusBarViewModel collapsedStatusBarViewModel,
            CollapsedStatusBarViewBinder collapsedStatusBarViewBinder,
            StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
            StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
            KeyguardStateController keyguardStateController,
            KeyguardStateController keyguardStateController,
            ShadeViewController shadeViewController,
            ShadeViewController shadeViewController,
@@ -182,6 +184,7 @@ public abstract class StatusBarViewModule {
                statusBarIconController,
                statusBarIconController,
                darkIconManagerFactory,
                darkIconManagerFactory,
                collapsedStatusBarViewModel,
                collapsedStatusBarViewModel,
                collapsedStatusBarViewBinder,
                statusBarHideIconsForBouncerManager,
                statusBarHideIconsForBouncerManager,
                keyguardStateController,
                keyguardStateController,
                shadeViewController,
                shadeViewController,
+43 −10
Original line number Original line Diff line number Diff line
@@ -14,8 +14,6 @@


package com.android.systemui.statusbar.phone.fragment;
package com.android.systemui.statusbar.phone.fragment;




import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.IDLE;
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.IDLE;
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.SHOWING_PERSISTENT_DOT;
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.OngoingCallController;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener;
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.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.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
@@ -131,6 +130,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
    private final StatusBarIconController mStatusBarIconController;
    private final StatusBarIconController mStatusBarIconController;
    private final CarrierConfigTracker mCarrierConfigTracker;
    private final CarrierConfigTracker mCarrierConfigTracker;
    private final CollapsedStatusBarViewModel mCollapsedStatusBarViewModel;
    private final CollapsedStatusBarViewModel mCollapsedStatusBarViewModel;
    private final CollapsedStatusBarViewBinder mCollapsedStatusBarViewBinder;
    private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
    private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
    private final StatusBarIconController.DarkIconManager.Factory mDarkIconManagerFactory;
    private final StatusBarIconController.DarkIconManager.Factory mDarkIconManagerFactory;
    private final SecureSettings mSecureSettings;
    private final SecureSettings mSecureSettings;
@@ -182,12 +182,22 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
     */
     */
    private boolean mWaitingForWindowStateChangeAfterCameraLaunch = false;
    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
     * Listener that updates {@link #mWaitingForWindowStateChangeAfterCameraLaunch} when it receives
     * a new status bar window state.
     * a new status bar window state.
     */
     */
    private final StatusBarWindowStateListener mStatusBarWindowStateListener = state ->
    private final StatusBarWindowStateListener mStatusBarWindowStateListener = state -> {
        mWaitingForWindowStateChangeAfterCameraLaunch = false;
        mWaitingForWindowStateChangeAfterCameraLaunch = false;
        mTransitionFromLockscreenToDreamStarted = false;
    };


    @SuppressLint("ValidFragment")
    @SuppressLint("ValidFragment")
    public CollapsedStatusBarFragment(
    public CollapsedStatusBarFragment(
@@ -201,6 +211,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
            StatusBarIconController statusBarIconController,
            StatusBarIconController statusBarIconController,
            StatusBarIconController.DarkIconManager.Factory darkIconManagerFactory,
            StatusBarIconController.DarkIconManager.Factory darkIconManagerFactory,
            CollapsedStatusBarViewModel collapsedStatusBarViewModel,
            CollapsedStatusBarViewModel collapsedStatusBarViewModel,
            CollapsedStatusBarViewBinder collapsedStatusBarViewBinder,
            StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
            StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
            KeyguardStateController keyguardStateController,
            KeyguardStateController keyguardStateController,
            ShadeViewController shadeViewController,
            ShadeViewController shadeViewController,
@@ -224,6 +235,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
        mFeatureFlags = featureFlags;
        mFeatureFlags = featureFlags;
        mStatusBarIconController = statusBarIconController;
        mStatusBarIconController = statusBarIconController;
        mCollapsedStatusBarViewModel = collapsedStatusBarViewModel;
        mCollapsedStatusBarViewModel = collapsedStatusBarViewModel;
        mCollapsedStatusBarViewBinder = collapsedStatusBarViewBinder;
        mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
        mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
        mDarkIconManagerFactory = darkIconManagerFactory;
        mDarkIconManagerFactory = darkIconManagerFactory;
        mKeyguardStateController = keyguardStateController;
        mKeyguardStateController = keyguardStateController;
@@ -296,8 +308,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
        mCarrierConfigTracker.addCallback(mCarrierConfigCallback);
        mCarrierConfigTracker.addCallback(mCarrierConfigCallback);
        mCarrierConfigTracker.addDefaultDataSubscriptionChangedListener(mDefaultDataListener);
        mCarrierConfigTracker.addDefaultDataSubscriptionChangedListener(mDefaultDataListener);


        CollapsedStatusBarViewBinder.bind(
        mCollapsedStatusBarViewBinder.bind(
                mStatusBar, mCollapsedStatusBarViewModel, this::updateStatusBarVisibilities);
                mStatusBar, mCollapsedStatusBarViewModel, mStatusBarVisibilityChangeListener);
    }
    }


    @Override
    @Override
@@ -411,6 +423,19 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
        return mStatusBarFragmentComponent;
        return mStatusBarFragmentComponent;
    }
    }


    private StatusBarVisibilityChangeListener mStatusBarVisibilityChangeListener =
            new StatusBarVisibilityChangeListener() {
        @Override
        public void onStatusBarVisibilityMaybeChanged() {
            updateStatusBarVisibilities(/* animate= */ true);
        }

        @Override
        public void onTransitionFromLockscreenToDreamStarted() {
            mTransitionFromLockscreenToDreamStarted = true;
        }
    };

    @Override
    @Override
    public void disable(int displayId, int state1, int state2, boolean animate) {
    public void disable(int displayId, int state1, int state2, boolean animate) {
        if (displayId != getContext().getDisplayId()) {
        if (displayId != getContext().getDisplayId()) {
@@ -423,10 +448,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
        updateStatusBarVisibilities(animate);
        updateStatusBarVisibilities(animate);
    }
    }


    private void updateStatusBarVisibilities() {
        updateStatusBarVisibilities(/* animate= */ true);
    }

    private void updateStatusBarVisibilities(boolean animate) {
    private void updateStatusBarVisibilities(boolean animate) {
        StatusBarVisibilityModel previousModel = mLastModifiedVisibility;
        StatusBarVisibilityModel previousModel = mLastModifiedVisibility;
        StatusBarVisibilityModel newModel = calculateInternalModel(mLastSystemVisibility);
        StatusBarVisibilityModel newModel = calculateInternalModel(mLastSystemVisibility);
@@ -546,6 +567,18 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
            return true;
            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
        // 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
        // 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
        // briefly show the status bar just to immediately hide it again. So, we wait for the
+7 −0
Original line number Original line Diff line number Diff line
@@ -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.mobile.util.SubscriptionManagerProxyImpl
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
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.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.RealWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositorySwitcher
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositorySwitcher
@@ -107,6 +109,11 @@ abstract class StatusBarPipelineModule {
        impl: CollapsedStatusBarViewModelImpl
        impl: CollapsedStatusBarViewModelImpl
    ): CollapsedStatusBarViewModel
    ): CollapsedStatusBarViewModel


    @Binds
    abstract fun collapsedStatusBarViewBinder(
        impl: CollapsedStatusBarViewBinderImpl
    ): CollapsedStatusBarViewBinder

    companion object {
    companion object {
        @Provides
        @Provides
        @SysUISingleton
        @SysUISingleton
+36 −9
Original line number Original line Diff line number Diff line
@@ -19,34 +19,61 @@ package com.android.systemui.statusbar.pipeline.shared.ui.binder
import android.view.View
import android.view.View
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel
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
     * Binds the view to the view-model. [listener] will be notified whenever an event that may
     * change the status bar visibility occurs.
     * change the status bar visibility occurs.
     */
     */
    @JvmStatic
    fun bind(
    fun bind(
        view: View,
        view: View,
        viewModel: CollapsedStatusBarViewModel,
        viewModel: CollapsedStatusBarViewModel,
        listener: StatusBarVisibilityChangeListener,
        listener: StatusBarVisibilityChangeListener,
    )
}

@SysUISingleton
class CollapsedStatusBarViewBinderImpl @Inject constructor() : CollapsedStatusBarViewBinder {
    override fun bind(
        view: View,
        viewModel: CollapsedStatusBarViewModel,
        listener: StatusBarVisibilityChangeListener,
    ) {
    ) {
        view.repeatWhenAttached {
        view.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                launch {
                    viewModel.isTransitioningFromLockscreenToOccluded.collect {
                    viewModel.isTransitioningFromLockscreenToOccluded.collect {
                        listener.onStatusBarVisibilityMaybeChanged()
                        listener.onStatusBarVisibilityMaybeChanged()
                    }
                    }
                }
                }

                launch {
                    viewModel.transitionFromLockscreenToDreamStartedEvent.collect {
                        listener.onTransitionFromLockscreenToDreamStarted()
                    }
                }
            }
        }
        }
    }
    }
}
}


/** Listener for various events that may affect the status bar's visibility. */
interface StatusBarVisibilityChangeListener {
    /**
    /**
 * Listener to be notified when the status bar visibility might have changed due to the device
     * Called when the status bar visibility might have changed due to the device moving to a
 * moving to a different state.
     * different state.
     */
     */
fun interface StatusBarVisibilityChangeListener {
    fun onStatusBarVisibilityMaybeChanged()
    fun onStatusBarVisibilityMaybeChanged()

    /** Called when a transition from lockscreen to dream has started. */
    fun onTransitionFromLockscreenToDreamStarted()
}
}
+10 −0
Original line number Original line Diff line number Diff line
@@ -22,8 +22,10 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionState
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.stateIn


@@ -43,6 +45,9 @@ interface CollapsedStatusBarViewModel {
     * otherwise.
     * otherwise.
     */
     */
    val isTransitioningFromLockscreenToOccluded: StateFlow<Boolean>
    val isTransitioningFromLockscreenToOccluded: StateFlow<Boolean>

    /** Emits whenever a transition from lockscreen to dream has started. */
    val transitionFromLockscreenToDreamStartedEvent: Flow<Unit>
}
}


@SysUISingleton
@SysUISingleton
@@ -59,4 +64,9 @@ constructor(
                    it.transitionState == TransitionState.RUNNING
                    it.transitionState == TransitionState.RUNNING
            }
            }
            .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), initialValue = false)
            .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), initialValue = false)

    override val transitionFromLockscreenToDreamStartedEvent: Flow<Unit> =
        keyguardTransitionInteractor.lockscreenToDreamingTransition
            .filter { it.transitionState == TransitionState.STARTED }
            .map {}
}
}
Loading