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

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

[SB] Update view model to hide status bar when in keyguard or shade.

Instead of trying to mimic all the incredibly complicated visibility
logic from CollapsedStatusBarFragment into CollapsedStatusBarViewModel,
this CL just starts with the basic facts: Hide the status bar when
lockscreen, shade, or bouncer is visible; show the status bar if the
lockscreen is occluded or none of those surfaces are visible.

We'll add back in the edge cases from CSBF as-needed, but this starts
with just the basics.

Bug: 364360986
Flag: com.android.systemui.status_bar_simple_fragment
Test: Verify status bar appears on home screen and in apps but not when
on lockscreen, bouncer, or shade
Test: Launch occluding activity that requires status bar over lockscreen
(e.g. with lockscreen shortcut) -> verify home status bar appears
Test: With status_bar_simple_fragment flag off, verify everything still
works as before and there's no crashes
Test: atest CollapsedStatusBarViewModelTest
CollapsedStatusBarFragmentTest

Change-Id: I053e6bc2e560e060dd2d5cf1e276ba97d0443693
parent 190697ff
Loading
Loading
Loading
Loading
+61 −8
Original line number Diff line number Diff line
@@ -56,7 +56,8 @@ import com.android.systemui.statusbar.OperatorNameView;
import com.android.systemui.statusbar.OperatorNameViewController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.chips.ron.shared.StatusBarRonChips;
import com.android.systemui.statusbar.disableflags.DisableFlagsLogger.DisableState;
import com.android.systemui.statusbar.core.StatusBarSimpleFragment;
import com.android.systemui.statusbar.disableflags.DisableFlagsLogger;
import com.android.systemui.statusbar.events.SystemStatusAnimationCallback;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder;
@@ -366,8 +367,10 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
        mPrimaryOngoingActivityChip = mStatusBar.findViewById(R.id.ongoing_activity_chip_primary);
        mSecondaryOngoingActivityChip =
                mStatusBar.findViewById(R.id.ongoing_activity_chip_secondary);
        if (!StatusBarSimpleFragment.isEnabled()) {
            showEndSideContent(false);
            showClock(false);
        }
        initOperatorName();
        initNotificationIconArea();
        mSystemEventAnimator = getSystemEventAnimator();
@@ -455,7 +458,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
        super.onPause();
        mCommandQueue.removeCallback(this);
        mStatusBarStateController.removeCallback(this);
        if (!StatusBarSimpleFragment.isEnabled()) {
            mOngoingCallController.removeCallback(mOngoingCallListener);
        }
        mAnimationScheduler.removeCallback(this);
        mSecureSettings.unregisterContentObserverSync(mVolumeSettingObserver);
    }
@@ -490,7 +495,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
        mNotificationIconAreaInner = notificationIcons;
        mNicBindingDisposable = mNicViewBinder.bindWhileAttached(notificationIcons);

        if (!StatusBarSimpleFragment.isEnabled()) {
            updateNotificationIconAreaAndOngoingActivityChip(/* animate= */ false);
        }
        Trace.endSection();
    }

@@ -509,11 +516,17 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
            new StatusBarVisibilityChangeListener() {
                @Override
                public void onStatusBarVisibilityMaybeChanged() {
                    if (StatusBarSimpleFragment.isEnabled()) {
                        return;
                    }
                    updateStatusBarVisibilities(/* animate= */ true);
                }

                @Override
                public void onTransitionFromLockscreenToDreamStarted() {
                    if (StatusBarSimpleFragment.isEnabled()) {
                        return;
                    }
                    mTransitionFromLockscreenToDreamStarted = true;
                }

@@ -522,6 +535,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
                        boolean hasPrimaryOngoingActivity,
                        boolean hasSecondaryOngoingActivity,
                        boolean shouldAnimate) {
                    if (StatusBarSimpleFragment.isEnabled()) {
                        return;
                    }
                    mHasPrimaryOngoingActivity = hasPrimaryOngoingActivity;
                    mHasSecondaryOngoingActivity = hasSecondaryOngoingActivity;
                    updateStatusBarVisibilities(shouldAnimate);
@@ -530,6 +546,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
                @Override
                public void onIsHomeStatusBarAllowedBySceneChanged(
                        boolean isHomeStatusBarAllowedByScene) {
                    if (StatusBarSimpleFragment.isEnabled()) {
                        return;
                    }
                    mHomeStatusBarAllowedByScene = isHomeStatusBarAllowedByScene;
                    updateStatusBarVisibilities(/* animate= */ true);
                }
@@ -537,17 +556,22 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue

    @Override
    public void disable(int displayId, int state1, int state2, boolean animate) {
        if (StatusBarSimpleFragment.isEnabled()) {
            return;
        }
        if (displayId != getContext().getDisplayId()) {
            return;
        }
        mCollapsedStatusBarFragmentLogger
                .logDisableFlagChange(new DisableState(state1, state2));
                .logDisableFlagChange(new DisableFlagsLogger.DisableState(state1, state2));
        mLastSystemVisibility =
                StatusBarVisibilityModel.createModelFromFlags(state1, state2);
        updateStatusBarVisibilities(animate);
    }

    private void updateStatusBarVisibilities(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();

        StatusBarVisibilityModel previousModel = mLastModifiedVisibility;
        StatusBarVisibilityModel newModel = calculateInternalModel(mLastSystemVisibility);
        mCollapsedStatusBarFragmentLogger.logVisibilityModel(newModel);
@@ -587,6 +611,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue

    private StatusBarVisibilityModel calculateInternalModel(
            StatusBarVisibilityModel externalModel) {
        StatusBarSimpleFragment.assertInLegacyMode();

        // TODO(b/328393714) use HeadsUpNotificationInteractor.showHeadsUpStatusBar instead.
        boolean headsUpVisible =
                mStatusBarFragmentComponent.getHeadsUpAppearanceController().shouldBeVisible();
@@ -639,6 +665,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
     * mLastModifiedVisibility.
     */
    private void updateNotificationIconAreaAndOngoingActivityChip(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();

        StatusBarVisibilityModel visibilityModel = mLastModifiedVisibility;
        boolean disableNotifications = !visibilityModel.getShowNotificationIcons();
        boolean hasOngoingActivity = visibilityModel.getShowPrimaryOngoingActivityChip();
@@ -674,6 +702,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
    }

    private boolean shouldHideStatusBar() {
        StatusBarSimpleFragment.assertInLegacyMode();

        if (!mShadeExpansionStateManager.isClosed()
                && mPanelExpansionInteractor.shouldHideStatusBarIconsWhenExpanded()) {
            return true;
@@ -728,6 +758,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
    }

    private void hideEndSideContent(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        if (!animate || !mAnimationsEnabled) {
            mEndSideAlphaController.setAlpha(/*alpha*/ 0f, SOURCE_OTHER);
        } else {
@@ -737,6 +768,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
    }

    private void showEndSideContent(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        if (!animate || !mAnimationsEnabled) {
            mEndSideAlphaController.setAlpha(1f, SOURCE_OTHER);
            return;
@@ -753,15 +785,18 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
    }

    private void hideClock(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        animateHiddenState(mClockView, clockHiddenMode(), animate);
    }

    private void showClock(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        animateShow(mClockView, animate);
    }

    /** Hides the primary ongoing activity chip. */
    private void hidePrimaryOngoingActivityChip(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        animateHiddenState(mPrimaryOngoingActivityChip, View.GONE, animate);
    }

@@ -773,15 +808,18 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
     * activities. See b/332662551.
     */
    private void showPrimaryOngoingActivityChip(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        animateShow(mPrimaryOngoingActivityChip, animate);
    }

    private void hideSecondaryOngoingActivityChip(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        animateHiddenState(mSecondaryOngoingActivityChip, View.GONE, animate);
    }

    private void showSecondaryOngoingActivityChip(boolean animate) {
        StatusBarRonChips.assertInNewMode();
        StatusBarSimpleFragment.assertInLegacyMode();
        animateShow(mSecondaryOngoingActivityChip, animate);
    }

@@ -790,6 +828,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
     * don't set the clock GONE otherwise it'll mess up the animation.
     */
    private int clockHiddenMode() {
        StatusBarSimpleFragment.assertInLegacyMode();
        if (!mShadeExpansionStateManager.isClosed() && !mKeyguardStateController.isShowing()
                && !mStatusBarStateController.isDozing()) {
            return View.INVISIBLE;
@@ -798,20 +837,24 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
    }

    public void hideNotificationIconArea(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        animateHide(mNotificationIconAreaInner, animate);
    }

    public void showNotificationIconArea(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        animateShow(mNotificationIconAreaInner, animate);
    }

    public void hideOperatorName(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        if (mOperatorNameViewController != null) {
            animateHide(mOperatorNameViewController.getView(), animate);
        }
    }

    public void showOperatorName(boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        if (mOperatorNameViewController != null) {
            animateShow(mOperatorNameViewController.getView(), animate);
        }
@@ -821,6 +864,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
     * Animate a view to INVISIBLE or GONE
     */
    private void animateHiddenState(final View v, int state, boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        v.animate().cancel();
        if (!animate || !mAnimationsEnabled) {
            v.setAlpha(0f);
@@ -840,6 +884,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
     * Hides a view.
     */
    private void animateHide(final View v, boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        animateHiddenState(v, View.INVISIBLE, animate);
    }

@@ -847,6 +892,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
     * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
     */
    private void animateShow(View v, boolean animate) {
        StatusBarSimpleFragment.assertInLegacyMode();
        v.animate().cancel();
        v.setVisibility(View.VISIBLE);
        if (!animate || !mAnimationsEnabled) {
@@ -883,13 +929,17 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
            mOperatorNameViewController.init();
            // This view should not be visible on lock-screen
            if (mKeyguardStateController.isShowing()) {
                if (!StatusBarSimpleFragment.isEnabled()) {
                    hideOperatorName(false);
                }
            }
        }
    }

    private void initOngoingCallChip() {
        if (!StatusBarSimpleFragment.isEnabled()) {
            mOngoingCallController.addCallback(mOngoingCallListener);
        }
        // TODO(b/364653005): Do we also need to set the secondary activity chip?
        mOngoingCallController.setChipView(mPrimaryOngoingActivityChip);
    }
@@ -899,6 +949,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue

    @Override
    public void onDozingChanged(boolean isDozing) {
        if (StatusBarSimpleFragment.isEnabled()) {
            return;
        }
        updateStatusBarVisibilities(/* animate= */ false);
    }

+6 −3
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.view.View
import androidx.core.animation.Interpolator
import androidx.core.animation.ValueAnimator
import com.android.app.animation.InterpolatorsAndroidX
import com.android.systemui.statusbar.core.StatusBarSimpleFragment

/**
 * A controller that keeps track of multiple sources applying alpha value changes to a view. It will
@@ -48,7 +49,7 @@ constructor(private val view: View, private val initialAlpha: Float = 1f) {
        sourceId: Int,
        duration: Long,
        interpolator: Interpolator = InterpolatorsAndroidX.ALPHA_IN,
        startDelay: Long = 0
        startDelay: Long = 0,
    ) {
        animators[sourceId]?.cancel()
        val animator = ValueAnimator.ofFloat(getMinAlpha(), alpha)
@@ -74,9 +75,11 @@ constructor(private val view: View, private val initialAlpha: Float = 1f) {

    private fun applyAlphaToView() {
        val minAlpha = getMinAlpha()
        if (!StatusBarSimpleFragment.isEnabled) {
            view.visibility = if (minAlpha != 0f) View.VISIBLE else View.INVISIBLE
            view.alpha = minAlpha
        }
    }

    private fun getMinAlpha() = alphas.minOfOrNull { it.value } ?: initialAlpha
}
+45 −8
Original line number Diff line number Diff line
@@ -22,12 +22,15 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
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.scene.domain.interactor.SceneContainerOcclusionInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModel
@@ -124,6 +127,7 @@ constructor(
    keyguardTransitionInteractor: KeyguardTransitionInteractor,
    sceneInteractor: SceneInteractor,
    sceneContainerOcclusionInteractor: SceneContainerOcclusionInteractor,
    shadeInteractor: ShadeInteractor,
    ongoingActivityChipsViewModel: OngoingActivityChipsViewModel,
    @Application coroutineScope: CoroutineScope,
) : CollapsedStatusBarViewModel {
@@ -169,21 +173,54 @@ constructor(
                .distinctUntilChanged()
        }

    // TODO(b/364360986): For all the is<SomeChildView>Visible flows, take other conditions into
    // account like whether we're on keyguard or shade.
    /**
     * True if the current SysUI state can show the home status bar (aka this status bar), and false
     * if we shouldn't be showing any part of the home status bar.
     */
    private val isHomeScreenStatusBarAllowedLegacy: Flow<Boolean> =
        combine(
            keyguardTransitionInteractor.currentKeyguardState,
            shadeInteractor.isAnyFullyExpanded,
        ) { currentKeyguardState, isShadeExpanded ->
            (currentKeyguardState == GONE || currentKeyguardState == OCCLUDED) && !isShadeExpanded
            // TODO(b/364360986): Add edge cases, like secure camera launch.
        }

    private val isHomeScreenStatusBarAllowed: Flow<Boolean> =
        if (SceneContainerFlag.isEnabled) {
            isHomeStatusBarAllowedByScene
        } else {
            isHomeScreenStatusBarAllowedLegacy
        }

    override val isClockVisible: Flow<VisibilityModel> =
        collapsedStatusBarInteractor.visibilityViaDisableFlags.map {
        combine(
            isHomeScreenStatusBarAllowed,
            collapsedStatusBarInteractor.visibilityViaDisableFlags,
        ) { isStatusBarAllowed, visibilityViaDisableFlags ->
            val showClock = isStatusBarAllowed && visibilityViaDisableFlags.isClockAllowed
            // TODO(b/364360986): Take CollapsedStatusBarFragment.clockHiddenMode into account.
            VisibilityModel(it.isClockAllowed.toVisibilityInt(), it.animate)
            VisibilityModel(showClock.toVisibilityInt(), visibilityViaDisableFlags.animate)
        }
    override val isNotificationIconContainerVisible: Flow<VisibilityModel> =
        collapsedStatusBarInteractor.visibilityViaDisableFlags.map {
            VisibilityModel(it.areNotificationIconsAllowed.toVisibilityInt(), it.animate)
        combine(
            isHomeScreenStatusBarAllowed,
            collapsedStatusBarInteractor.visibilityViaDisableFlags,
        ) { isStatusBarAllowed, visibilityViaDisableFlags ->
            val showNotificationIconContainer =
                isStatusBarAllowed && visibilityViaDisableFlags.areNotificationIconsAllowed
            VisibilityModel(
                showNotificationIconContainer.toVisibilityInt(),
                visibilityViaDisableFlags.animate
            )
        }
    override val isSystemInfoVisible: Flow<VisibilityModel> =
        collapsedStatusBarInteractor.visibilityViaDisableFlags.map {
            VisibilityModel(it.isSystemInfoAllowed.toVisibilityInt(), it.animate)
        combine(
            isHomeScreenStatusBarAllowed,
            collapsedStatusBarInteractor.visibilityViaDisableFlags,
        ) { isStatusBarAllowed, visibilityViaDisableFlags ->
            val showSystemInfo = isStatusBarAllowed && visibilityViaDisableFlags.isSystemInfoAllowed
            VisibilityModel(showSystemInfo.toVisibilityInt(), visibilityViaDisableFlags.animate)
        }

    @View.Visibility
+113 −14

File changed.

Preview size limit exceeded, changes collapsed.

+6 −3
Original line number Diff line number Diff line
@@ -16,10 +16,12 @@

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

import android.platform.test.annotations.DisableFlags
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_STATUS_BAR_SIMPLE_FRAGMENT
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.AnimatorTestRule
import junit.framework.Assert.assertEquals
@@ -36,6 +38,7 @@ private const val INITIAL_ALPHA = 1f
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
@DisableFlags(FLAG_STATUS_BAR_SIMPLE_FRAGMENT)
class MultiSourceMinAlphaControllerTest : SysuiTestCase() {

    private val view = View(context)
@@ -60,7 +63,7 @@ class MultiSourceMinAlphaControllerTest : SysuiTestCase() {
        multiSourceMinAlphaController.animateToAlpha(
            alpha = 0.5f,
            sourceId = TEST_SOURCE_1,
            duration = TEST_ANIMATION_DURATION
            duration = TEST_ANIMATION_DURATION,
        )
        animatorTestRule.advanceTimeBy(TEST_ANIMATION_DURATION)
        assertEquals(0.5f, view.alpha)
@@ -71,7 +74,7 @@ class MultiSourceMinAlphaControllerTest : SysuiTestCase() {
        multiSourceMinAlphaController.animateToAlpha(
            alpha = 0.5f,
            sourceId = TEST_SOURCE_1,
            duration = TEST_ANIMATION_DURATION
            duration = TEST_ANIMATION_DURATION,
        )
        multiSourceMinAlphaController.setAlpha(alpha = 0.7f, sourceId = TEST_SOURCE_2)
        multiSourceMinAlphaController.reset()
@@ -94,7 +97,7 @@ class MultiSourceMinAlphaControllerTest : SysuiTestCase() {
        multiSourceMinAlphaController.animateToAlpha(
            alpha = 0f,
            sourceId = TEST_SOURCE_1,
            duration = TEST_ANIMATION_DURATION
            duration = TEST_ANIMATION_DURATION,
        )
        animatorTestRule.advanceTimeBy(TEST_ANIMATION_DURATION / 2)
        multiSourceMinAlphaController.setAlpha(alpha = 1f, sourceId = TEST_SOURCE_1)
Loading