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

Commit fc8397a6 authored by Steve Elliott's avatar Steve Elliott
Browse files

Move aod icon vis handling to parent view-binder

Flag: ACONFIG com.android.systemui.notifications_icon_container_refactor
DEVELOPMENT
Bug: 278765923
Test: atest SystemUITests

Change-Id: I8ab7c62725b799606a008c500d77260415877f03
parent 7c947d64
Loading
Loading
Loading
Loading
+29 −13
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ import com.android.systemui.flags.FeatureFlagsClassic;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.core.LogLevel;
import com.android.systemui.log.dagger.KeyguardClockLog;
@@ -95,6 +97,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
    private final ClockEventController mClockEventController;
    private final LogBuffer mLogBuffer;
    private final NotificationIconContainerAlwaysOnDisplayViewModel mAodIconsViewModel;
    private final KeyguardRootViewModel mKeyguardRootViewModel;
    private final ConfigurationState mConfigurationState;
    private final ConfigurationController mConfigurationController;
    private final DozeParameters mDozeParameters;
@@ -127,7 +130,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
    private KeyguardInteractor mKeyguardInteractor;
    private final DelayableExecutor mUiExecutor;
    private boolean mCanShowDoubleLineClock = true;
    private DisposableHandle mAodIconsBindJob;
    private DisposableHandle mAodIconsBindHandle;
    @Nullable private NotificationIconContainer mAodIconContainer;

    @VisibleForTesting
@@ -179,6 +182,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
            ClockEventController clockEventController,
            @KeyguardClockLog LogBuffer logBuffer,
            NotificationIconContainerAlwaysOnDisplayViewModel aodIconsViewModel,
            KeyguardRootViewModel keyguardRootViewModel,
            ConfigurationState configurationState,
            DozeParameters dozeParameters,
            AlwaysOnDisplayNotificationIconViewStore aodIconViewStore,
@@ -199,6 +203,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
        mClockEventController = clockEventController;
        mLogBuffer = logBuffer;
        mAodIconsViewModel = aodIconsViewModel;
        mKeyguardRootViewModel = keyguardRootViewModel;
        mConfigurationState = configurationState;
        mDozeParameters = dozeParameters;
        mAodIconViewStore = aodIconViewStore;
@@ -567,21 +572,32 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
                    mView.findViewById(
                            com.android.systemui.res.R.id.left_aligned_notification_icon_container);
            if (NotificationIconContainerRefactor.isEnabled()) {
                if (mAodIconsBindJob != null) {
                    mAodIconsBindJob.dispose();
                if (mAodIconsBindHandle != null) {
                    mAodIconsBindHandle.dispose();
                }
                if (nic != null) {
                    nic.setOnLockScreen(true);
                    mAodIconsBindJob = NotificationIconContainerViewBinder.bind(
                    final DisposableHandle viewHandle = NotificationIconContainerViewBinder.bind(
                            nic,
                            mAodIconsViewModel,
                            mConfigurationState,
                            mConfigurationController,
                            mDozeParameters,
                            mAodIconViewStore);
                    final DisposableHandle visHandle = KeyguardRootViewBinder.bindAodIconVisibility(
                            nic,
                            mKeyguardRootViewModel.isNotifIconContainerVisible(),
                            mConfigurationState,
                            mFeatureFlags,
                        mScreenOffAnimationController,
                        mAodIconViewStore
                    );
                            mScreenOffAnimationController);
                    if (visHandle == null) {
                        mAodIconsBindHandle = viewHandle;
                    } else {
                        mAodIconsBindHandle = () -> {
                            viewHandle.dispose();
                            visHandle.dispose();
                        };
                    }
                    mAodIconContainer = nic;
                }
            } else {
+8 −5
Original line number Diff line number Diff line
@@ -27,9 +27,10 @@ import com.android.keyguard.LockIconView
import com.android.keyguard.LockIconViewController
import com.android.keyguard.dagger.KeyguardStatusViewComponent
import com.android.systemui.CoreStartable
import com.android.systemui.common.ui.ConfigurationState
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
@@ -46,7 +47,7 @@ import com.android.systemui.shade.NotificationShadeWindowView
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.KeyguardIndicationController
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
import dagger.Lazy
import javax.inject.Inject
@@ -63,14 +64,15 @@ constructor(
    private val keyguardRootViewModel: KeyguardRootViewModel,
    private val keyguardIndicationAreaViewModel: KeyguardIndicationAreaViewModel,
    private val notificationShadeWindowView: NotificationShadeWindowView,
    private val featureFlags: FeatureFlags,
    private val featureFlags: FeatureFlagsClassic,
    private val indicationController: KeyguardIndicationController,
    private val keyguardStateController: KeyguardStateController,
    private val screenOffAnimationController: ScreenOffAnimationController,
    private val occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
    private val chipbarCoordinator: ChipbarCoordinator,
    private val keyguardBlueprintCommandListener: KeyguardBlueprintCommandListener,
    private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel,
    private val keyguardStatusViewComponentFactory: KeyguardStatusViewComponent.Factory,
    private val configuration: ConfigurationState,
    private val context: Context,
    private val keyguardIndicationController: KeyguardIndicationController,
    private val lockIconViewController: Lazy<LockIconViewController>,
@@ -143,10 +145,11 @@ constructor(
            KeyguardRootViewBinder.bind(
                keyguardRootView,
                keyguardRootViewModel,
                configuration,
                featureFlags,
                occludingAppDeviceEntryMessageViewModel,
                chipbarCoordinator,
                keyguardStateController,
                screenOffAnimationController,
                shadeInteractor,
                { keyguardStatusViewController!!.getClockController() },
                interactionJankMonitor,
+158 −6
Original line number Diff line number Diff line
@@ -16,25 +16,31 @@

package com.android.systemui.keyguard.ui.binder

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.annotation.DrawableRes
import android.view.HapticFeedbackConstants
import android.view.View
import android.view.View.OnLayoutChangeListener
import android.view.ViewGroup
import android.view.ViewGroup.OnHierarchyChangeListener
import android.view.ViewPropertyAnimator
import android.view.WindowInsets
import android.view.WindowInsets.Type
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.animation.Interpolators
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
import com.android.keyguard.KeyguardClockSwitch.MISSING_CLOCK_ID
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.shared.model.Text
import com.android.systemui.common.shared.model.TintedIcon
import com.android.systemui.common.ui.ConfigurationState
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.flags.RefactorFlag
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
@@ -42,29 +48,38 @@ import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.ClockController
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.CrossFadeHelper
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
import com.android.systemui.temporarydisplay.ViewPriority
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
import com.android.systemui.temporarydisplay.chipbar.ChipbarInfo
import com.android.systemui.util.ui.AnimatedValue
import com.android.systemui.util.ui.isAnimating
import com.android.systemui.util.ui.stopAnimating
import com.android.systemui.util.ui.value
import javax.inject.Provider
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

/** Bind occludingAppDeviceEntryMessageViewModel to run whenever the keyguard view is attached. */
@ExperimentalCoroutinesApi
@OptIn(ExperimentalCoroutinesApi::class)
object KeyguardRootViewBinder {

    @JvmStatic
    fun bind(
        view: ViewGroup,
        viewModel: KeyguardRootViewModel,
        featureFlags: FeatureFlags,
        configuration: ConfigurationState,
        featureFlags: FeatureFlagsClassic,
        occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
        chipbarCoordinator: ChipbarCoordinator,
        keyguardStateController: KeyguardStateController,
        screenOffAnimationController: ScreenOffAnimationController,
        shadeInteractor: ShadeInteractor,
        clockControllerProvider: Provider<ClockController>?,
        interactionJankMonitor: InteractionJankMonitor?,
@@ -149,6 +164,24 @@ object KeyguardRootViewBinder {
                            }
                        }

                        if (NotificationIconContainerRefactor.isEnabled) {
                            launch {
                                val iconsAppearTranslationPx =
                                    configuration
                                        .getDimensionPixelSize(R.dimen.shelf_appear_translation)
                                        .stateIn(this)
                                viewModel.isNotifIconContainerVisible.collect { isVisible ->
                                    childViews[aodNotificationIconContainerId]
                                        ?.setAodNotifIconContainerIsVisible(
                                            isVisible,
                                            featureFlags,
                                            iconsAppearTranslationPx.value,
                                            screenOffAnimationController,
                                        )
                                }
                            }
                        }

                        interactionJankMonitor?.let { jankMonitor ->
                            launch {
                                viewModel.goneToAodTransition.collect {
@@ -312,5 +345,124 @@ object KeyguardRootViewBinder {
        }
    }

    @JvmStatic
    fun bindAodIconVisibility(
        view: View,
        isVisible: Flow<AnimatedValue<Boolean>>,
        configuration: ConfigurationState,
        featureFlags: FeatureFlagsClassic,
        screenOffAnimationController: ScreenOffAnimationController,
    ): DisposableHandle? {
        RefactorFlag(featureFlags, Flags.MIGRATE_KEYGUARD_STATUS_VIEW).assertInLegacyMode()
        if (NotificationIconContainerRefactor.isUnexpectedlyInLegacyMode()) return null
        return view.repeatWhenAttached {
            lifecycleScope.launch {
                val iconAppearTranslationPx =
                    configuration
                        .getDimensionPixelSize(R.dimen.shelf_appear_translation)
                        .stateIn(this)
                isVisible.collect { isVisible ->
                    view.setAodNotifIconContainerIsVisible(
                        isVisible,
                        featureFlags,
                        iconAppearTranslationPx.value,
                        screenOffAnimationController,
                    )
                }
            }
        }
    }

    private fun View.setAodNotifIconContainerIsVisible(
        isVisible: AnimatedValue<Boolean>,
        featureFlags: FeatureFlagsClassic,
        iconsAppearTranslationPx: Int,
        screenOffAnimationController: ScreenOffAnimationController,
    ) {
        val statusViewMigrated = featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)
        animate().cancel()
        val animatorListener =
            object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    isVisible.stopAnimating()
                }
            }
        when {
            !isVisible.isAnimating -> {
                alpha = 1f
                if (!statusViewMigrated) {
                    translationY = 0f
                }
                visibility = if (isVisible.value) View.VISIBLE else View.INVISIBLE
            }
            featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION) -> {
                animateInIconTranslation(statusViewMigrated)
                if (isVisible.value) {
                    CrossFadeHelper.fadeIn(this, animatorListener)
                } else {
                    CrossFadeHelper.fadeOut(this, animatorListener)
                }
            }
            !isVisible.value -> {
                // Let's make sure the icon are translated to 0, since we cancelled it above
                animateInIconTranslation(statusViewMigrated)
                CrossFadeHelper.fadeOut(this, animatorListener)
            }
            visibility != View.VISIBLE -> {
                // No fading here, let's just appear the icons instead!
                visibility = View.VISIBLE
                alpha = 1f
                appearIcons(
                    animate = screenOffAnimationController.shouldAnimateAodIcons(),
                    iconsAppearTranslationPx,
                    statusViewMigrated,
                    animatorListener,
                )
            }
            else -> {
                // Let's make sure the icons are translated to 0, since we cancelled it above
                animateInIconTranslation(statusViewMigrated)
                // We were fading out, let's fade in instead
                CrossFadeHelper.fadeIn(this, animatorListener)
            }
        }
    }

    private fun View.appearIcons(
        animate: Boolean,
        iconAppearTranslation: Int,
        statusViewMigrated: Boolean,
        animatorListener: Animator.AnimatorListener,
    ) {
        if (animate) {
            if (!statusViewMigrated) {
                translationY = -iconAppearTranslation.toFloat()
            }
            alpha = 0f
            animate()
                .alpha(1f)
                .setInterpolator(Interpolators.LINEAR)
                .setDuration(AOD_ICONS_APPEAR_DURATION)
                .apply { if (statusViewMigrated) animateInIconTranslation() }
                .setListener(animatorListener)
                .start()
        } else {
            alpha = 1.0f
            if (!statusViewMigrated) {
                translationY = 0f
            }
        }
    }

    private fun View.animateInIconTranslation(statusViewMigrated: Boolean) {
        if (!statusViewMigrated) {
            animate().animateInIconTranslation().setDuration(AOD_ICONS_APPEAR_DURATION).start()
        }
    }

    private fun ViewPropertyAnimator.animateInIconTranslation(): ViewPropertyAnimator =
        setInterpolator(Interpolators.DECELERATE_QUINT).translationY(0f)

    private const val ID = "occluding_app_device_entry_unlock_msg"
    private const val AOD_ICONS_APPEAR_DURATION: Long = 200
}
+8 −7
Original line number Diff line number Diff line
@@ -44,10 +44,10 @@ import com.android.keyguard.KeyguardClockSwitch
import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.ui.ConfigurationState
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.binder.KeyguardPreviewClockViewBinder
import com.android.systemui.keyguard.ui.binder.KeyguardPreviewSmartspaceViewBinder
@@ -76,7 +76,7 @@ import com.android.systemui.statusbar.KeyguardIndicationController
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
@@ -99,12 +99,13 @@ constructor(
    private val quickAffordancesCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel,
    displayManager: DisplayManager,
    private val windowManager: WindowManager,
    private val configuration: ConfigurationState,
    private val clockController: ClockEventController,
    private val clockRegistry: ClockRegistry,
    private val broadcastDispatcher: BroadcastDispatcher,
    private val lockscreenSmartspaceController: LockscreenSmartspaceController,
    private val udfpsOverlayInteractor: UdfpsOverlayInteractor,
    private val featureFlags: FeatureFlags,
    private val featureFlags: FeatureFlagsClassic,
    private val falsingManager: FalsingManager,
    private val vibratorHelper: VibratorHelper,
    private val indicationController: KeyguardIndicationController,
@@ -113,9 +114,8 @@ constructor(
    private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel,
    private val occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
    private val chipbarCoordinator: ChipbarCoordinator,
    private val keyguardStateController: KeyguardStateController,
    private val screenOffAnimationController: ScreenOffAnimationController,
    private val shadeInteractor: ShadeInteractor,
    private val deviceEntryHapticsInteractor: DeviceEntryHapticsInteractor,
) {

    val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN)
@@ -341,10 +341,11 @@ constructor(
            KeyguardRootViewBinder.bind(
                keyguardRootView,
                keyguardRootViewModel,
                configuration,
                featureFlags,
                occludingAppDeviceEntryMessageViewModel,
                chipbarCoordinator,
                keyguardStateController,
                screenOffAnimationController,
                shadeInteractor,
                null, // clock provider only needed for burn in
                null, // jank monitor not required for preview mode
+0 −6
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.res.R
import com.android.systemui.shade.NotificationPanelView
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.AlwaysOnDisplayNotificationIconViewStore
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder
import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerAlwaysOnDisplayViewModel
@@ -39,7 +38,6 @@ import com.android.systemui.statusbar.notification.shared.NotificationIconContai
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.NotificationIconAreaController
import com.android.systemui.statusbar.phone.NotificationIconContainer
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
import com.android.systemui.statusbar.policy.ConfigurationController
import javax.inject.Inject
import kotlinx.coroutines.DisposableHandle
@@ -54,9 +52,7 @@ constructor(
    private val featureFlags: FeatureFlagsClassic,
    private val nicAodViewModel: NotificationIconContainerAlwaysOnDisplayViewModel,
    private val nicAodIconViewStore: AlwaysOnDisplayNotificationIconViewStore,
    private val notificationPanelView: NotificationPanelView,
    private val notificationIconAreaController: NotificationIconAreaController,
    private val screenOffAnimationController: ScreenOffAnimationController,
) : KeyguardSection() {

    private var nicBindingDisposable: DisposableHandle? = null
@@ -97,8 +93,6 @@ constructor(
                    configurationState,
                    configurationController,
                    dozeParameters,
                    featureFlags,
                    screenOffAnimationController,
                    nicAodIconViewStore,
                )
        } else {
Loading