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

Commit b12fb720 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I43acab2f,Ib9ba0a6b into main

* changes:
  Fix turbulence noise logic
  Fix unwanted reserved spaces for semantic buttons
parents 8d6962ab d43ebf95
Loading
Loading
Loading
Loading
+0 −16
Original line number Original line Diff line number Diff line
@@ -21,9 +21,7 @@ import android.app.BroadcastOptions
import android.app.PendingIntent
import android.app.PendingIntent
import android.content.Context
import android.content.Context
import android.content.Intent
import android.content.Intent
import android.media.session.MediaController
import android.media.session.MediaSession
import android.media.session.MediaSession
import android.media.session.PlaybackState
import android.provider.Settings
import android.provider.Settings
import android.util.Log
import android.util.Log
import com.android.internal.jank.Cuj
import com.android.internal.jank.Cuj
@@ -42,7 +40,6 @@ import com.android.systemui.media.dialog.MediaOutputDialogManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.kotlin.pairwiseBy
import dagger.assisted.Assisted
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
@@ -70,19 +67,6 @@ constructor(
            .map { entries -> entries[instanceId]?.let { toMediaControlModel(it) } }
            .map { entries -> entries[instanceId]?.let { toMediaControlModel(it) } }
            .distinctUntilChanged()
            .distinctUntilChanged()


    val isStartedPlaying: Flow<Boolean> =
        mediaControl
            .map { mediaControl ->
                mediaControl?.token?.let { token ->
                    MediaController(applicationContext, token).playbackState?.let {
                        it.state == PlaybackState.STATE_PLAYING
                    }
                }
                    ?: false
            }
            .pairwiseBy(initialValue = false) { wasPlaying, isPlaying -> !wasPlaying && isPlaying }
            .distinctUntilChanged()

    val onAnyMediaConfigurationChange: Flow<Unit> = repository.onAnyMediaConfigurationChange
    val onAnyMediaConfigurationChange: Flow<Unit> = repository.onAnyMediaConfigurationChange


    fun removeMediaControl(
    fun removeMediaControl(
+44 −44
Original line number Original line Diff line number Diff line
@@ -260,45 +260,51 @@ object MediaControlViewBinder {
            }
            }


            SEMANTIC_ACTIONS_ALL.forEachIndexed { index, id ->
            SEMANTIC_ACTIONS_ALL.forEachIndexed { index, id ->
                val button = viewHolder.getAction(id)
                val buttonView = viewHolder.getAction(id)
                val actionViewModel = viewModel.actionButtons[index]
                val buttonModel = viewModel.actionButtons[index]
                if (button.id == R.id.actionPrev) {
                if (buttonView.id == R.id.actionPrev) {
                    actionViewModel?.let {
                    viewController.setUpPrevButtonInfo(
                        viewController.setUpPrevButtonInfo(true, it.notVisibleValue)
                        buttonModel.isEnabled,
                    }
                        buttonModel.notVisibleValue
                } else if (button.id == R.id.actionNext) {
                    )
                    actionViewModel?.let {
                } else if (buttonView.id == R.id.actionNext) {
                        viewController.setUpNextButtonInfo(true, it.notVisibleValue)
                    viewController.setUpNextButtonInfo(
                    }
                        buttonModel.isEnabled,
                        buttonModel.notVisibleValue
                    )
                }
                }
                actionViewModel?.let { action ->
                val animHandler = (buttonView.tag ?: AnimationBindHandler()) as AnimationBindHandler
                    val animHandler = (button.tag ?: AnimationBindHandler()) as AnimationBindHandler
                animHandler.tryExecute {
                animHandler.tryExecute {
                        if (animHandler.updateRebindId(action.rebindId)) {
                    if (buttonModel.isEnabled) {
                        if (animHandler.updateRebindId(buttonModel.rebindId)) {
                            animHandler.unregisterAll()
                            animHandler.unregisterAll()
                            animHandler.tryRegister(action.icon)
                            animHandler.tryRegister(buttonModel.icon)
                            animHandler.tryRegister(action.background)
                            animHandler.tryRegister(buttonModel.background)
                            bindButtonCommon(
                            bindButtonCommon(
                                button,
                                buttonView,
                                viewHolder.multiRippleView,
                                viewHolder.multiRippleView,
                                action,
                                buttonModel,
                                viewController,
                                viewController,
                                falsingManager,
                                falsingManager,
                            )
                            )
                        }
                        }
                        val visible = action.isVisibleWhenScrubbing || !viewController.isScrubbing
                    } else {
                        animHandler.unregisterAll()
                        clearButton(buttonView)
                    }
                    val visible =
                        buttonModel.isEnabled &&
                            (buttonModel.isVisibleWhenScrubbing || !viewController.isScrubbing)
                    setSemanticButtonVisibleAndAlpha(
                    setSemanticButtonVisibleAndAlpha(
                        viewHolder.getAction(id),
                        viewHolder.getAction(id),
                        viewController.expandedLayout,
                        viewController.expandedLayout,
                        viewController.collapsedLayout,
                        viewController.collapsedLayout,
                        visible,
                        visible,
                            action.notVisibleValue,
                        buttonModel.notVisibleValue,
                            action.showInCollapsed
                        buttonModel.showInCollapsed
                    )
                    )
                }
                }
            }
            }
                    ?: clearButton(button)
            }
        } else {
        } else {
            // Hide buttons that only appear for semantic actions
            // Hide buttons that only appear for semantic actions
            SEMANTIC_ACTIONS_COMPACT.forEach { buttonId ->
            SEMANTIC_ACTIONS_COMPACT.forEach { buttonId ->
@@ -309,7 +315,7 @@ object MediaControlViewBinder {
            // Set all generic buttons
            // Set all generic buttons
            genericButtons.forEachIndexed { index, button ->
            genericButtons.forEachIndexed { index, button ->
                if (index < viewModel.actionButtons.size) {
                if (index < viewModel.actionButtons.size) {
                    viewModel.actionButtons[index]?.let { action ->
                    val action = viewModel.actionButtons[index]
                    bindButtonCommon(
                    bindButtonCommon(
                        button,
                        button,
                        viewHolder.multiRippleView,
                        viewHolder.multiRippleView,
@@ -318,13 +324,7 @@ object MediaControlViewBinder {
                        falsingManager,
                        falsingManager,
                    )
                    )
                    setVisibleAndAlpha(expandedSet, button.id, visible = true)
                    setVisibleAndAlpha(expandedSet, button.id, visible = true)
                        setVisibleAndAlpha(
                    setVisibleAndAlpha(collapsedSet, button.id, visible = action.showInCollapsed)
                            collapsedSet,
                            button.id,
                            visible = action.showInCollapsed
                        )
                    }
                        ?: clearButton(button)
                } else {
                } else {
                    // Hide any unused buttons
                    // Hide any unused buttons
                    clearButton(button)
                    clearButton(button)
+8 −6
Original line number Original line Diff line number Diff line
@@ -709,12 +709,6 @@ constructor(


        // For Turbulence noise.
        // For Turbulence noise.
        val loadingEffectView = mediaViewHolder.loadingEffectView
        val loadingEffectView = mediaViewHolder.loadingEffectView
        turbulenceNoiseAnimationConfig =
            createTurbulenceNoiseConfig(
                loadingEffectView,
                turbulenceNoiseView,
                colorSchemeTransition
            )
        noiseDrawCallback =
        noiseDrawCallback =
            object : PaintDrawCallback {
            object : PaintDrawCallback {
                override fun onDraw(paint: Paint) {
                override fun onDraw(paint: Paint) {
@@ -809,6 +803,14 @@ constructor(


    fun setUpTurbulenceNoise() {
    fun setUpTurbulenceNoise() {
        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
        if (!mediaFlags.isMediaControlsRefactorEnabled()) return
        if (!this::turbulenceNoiseAnimationConfig.isInitialized) {
            turbulenceNoiseAnimationConfig =
                createTurbulenceNoiseConfig(
                    mediaViewHolder.loadingEffectView,
                    mediaViewHolder.turbulenceNoiseView,
                    colorSchemeTransition
                )
        }
        if (Flags.shaderlibLoadingEffectRefactor()) {
        if (Flags.shaderlibLoadingEffectRefactor()) {
            if (!this::loadingEffect.isInitialized) {
            if (!this::loadingEffect.isInitialized) {
                loadingEffect =
                loadingEffect =
+35 −44
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context
import android.content.pm.PackageManager
import android.content.pm.PackageManager
import android.media.session.MediaController
import android.media.session.MediaController
import android.media.session.MediaSession.Token
import android.media.session.MediaSession.Token
import android.media.session.PlaybackState
import android.text.TextUtils
import android.text.TextUtils
import android.util.Log
import android.util.Log
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet
@@ -40,16 +41,14 @@ import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.monet.ColorScheme
import com.android.systemui.monet.ColorScheme
import com.android.systemui.monet.Style
import com.android.systemui.monet.Style
import com.android.systemui.res.R
import com.android.systemui.res.R
import com.android.systemui.util.kotlin.sample
import java.util.concurrent.Executor
import java.util.concurrent.Executor
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map


/** Models UI state and handles user input for a media control. */
/** Models UI state and handles user input for a media control. */
class MediaControlViewModel(
class MediaControlViewModel(
@@ -60,31 +59,20 @@ class MediaControlViewModel(
    private val logger: MediaUiEventLogger,
    private val logger: MediaUiEventLogger,
) {
) {


    private val isAnyButtonClicked: MutableStateFlow<Boolean> = MutableStateFlow(false)

    private val playTurbulenceNoise: Flow<Boolean> =
        interactor.mediaControl.sample(
            combine(isAnyButtonClicked, interactor.isStartedPlaying) {
                    isButtonClicked,
                    isStartedPlaying ->
                    isButtonClicked && isStartedPlaying
                }
                .distinctUntilChanged()
        )

    @OptIn(ExperimentalCoroutinesApi::class)
    @OptIn(ExperimentalCoroutinesApi::class)
    val player: Flow<MediaPlayerViewModel?> =
    val player: Flow<MediaPlayerViewModel?> =
        interactor.onAnyMediaConfigurationChange
        interactor.onAnyMediaConfigurationChange
            .flatMapLatest {
            .flatMapLatest {
                combine(playTurbulenceNoise, interactor.mediaControl) {
                interactor.mediaControl.map { mediaControl ->
                    playTurbulenceNoise,
                    mediaControl?.let { toViewModel(it) }
                    mediaControl ->
                    mediaControl?.let { toViewModel(it, playTurbulenceNoise) }
                }
                }
            }
            }
            .distinctUntilChanged()
            .distinctUntilChanged()
            .flowOn(backgroundDispatcher)
            .flowOn(backgroundDispatcher)


    private var isPlaying = false
    private var isAnyButtonClicked = false

    private fun onDismissMediaData(
    private fun onDismissMediaData(
        token: Token?,
        token: Token?,
        uid: Int,
        uid: Int,
@@ -95,10 +83,8 @@ class MediaControlViewModel(
        interactor.removeMediaControl(token, instanceId, MEDIA_PLAYER_ANIMATION_DELAY)
        interactor.removeMediaControl(token, instanceId, MEDIA_PLAYER_ANIMATION_DELAY)
    }
    }


    private suspend fun toViewModel(
    private suspend fun toViewModel(model: MediaControlModel): MediaPlayerViewModel? {
        model: MediaControlModel,
        val mediaController = model.token?.let { MediaController(applicationContext, it) }
        playTurbulenceNoise: Boolean
    ): MediaPlayerViewModel? {
        val wallpaperColors =
        val wallpaperColors =
            MediaArtworkHelper.getWallpaperColor(
            MediaArtworkHelper.getWallpaperColor(
                applicationContext,
                applicationContext,
@@ -118,8 +104,14 @@ class MediaControlViewModel(


        val gutsViewModel = toGutsViewModel(model, scheme)
        val gutsViewModel = toGutsViewModel(model, scheme)


        // Set playing state
        val wasPlaying = isPlaying
        isPlaying =
            mediaController?.playbackState?.let { it.state == PlaybackState.STATE_PLAYING } ?: false

        // Resetting button clicks state.
        // Resetting button clicks state.
        isAnyButtonClicked.value = false
        val wasButtonClicked = isAnyButtonClicked
        isAnyButtonClicked = false


        return MediaPlayerViewModel(
        return MediaPlayerViewModel(
            contentDescription = { gutsVisible ->
            contentDescription = { gutsVisible ->
@@ -144,7 +136,7 @@ class MediaControlViewModel(
            shouldAddGradient = wallpaperColors != null,
            shouldAddGradient = wallpaperColors != null,
            colorScheme = scheme,
            colorScheme = scheme,
            canShowTime = canShowScrubbingTimeViews(model.semanticActionButtons),
            canShowTime = canShowScrubbingTimeViews(model.semanticActionButtons),
            playTurbulenceNoise = playTurbulenceNoise,
            playTurbulenceNoise = isPlaying && !wasPlaying && wasButtonClicked,
            useSemanticActions = model.semanticActionButtons != null,
            useSemanticActions = model.semanticActionButtons != null,
            actionButtons = toActionViewModels(model),
            actionButtons = toActionViewModels(model),
            outputSwitcher = toOutputSwitcherViewModel(model),
            outputSwitcher = toOutputSwitcherViewModel(model),
@@ -168,9 +160,7 @@ class MediaControlViewModel(
                    seekBarViewModel.updateStaticProgress(model.resumeProgress)
                    seekBarViewModel.updateStaticProgress(model.resumeProgress)
                } else {
                } else {
                    backgroundExecutor.execute {
                    backgroundExecutor.execute {
                        seekBarViewModel.updateController(
                        seekBarViewModel.updateController(mediaController)
                            model.token?.let { MediaController(applicationContext, it) }
                        )
                    }
                    }
                }
                }
            }
            }
@@ -283,16 +273,17 @@ class MediaControlViewModel(
        )
        )
    }
    }


    private fun toActionViewModels(model: MediaControlModel): List<MediaActionViewModel?> {
    private fun toActionViewModels(model: MediaControlModel): List<MediaActionViewModel> {
        val semanticActionButtons =
        val semanticActionButtons =
            model.semanticActionButtons?.let { mediaButton ->
            model.semanticActionButtons?.let { mediaButton ->
                with(mediaButton) {
                val isScrubbingTimeEnabled = canShowScrubbingTimeViews(mediaButton)
                val isScrubbingTimeEnabled = canShowScrubbingTimeViews(mediaButton)
                SEMANTIC_ACTIONS_ALL.map { buttonId ->
                SEMANTIC_ACTIONS_ALL.map { buttonId ->
                        getActionById(buttonId)?.let {
                    toSemanticActionViewModel(
                            toSemanticActionViewModel(model, it, buttonId, isScrubbingTimeEnabled)
                        model,
                        }
                        mediaButton.getActionById(buttonId),
                    }
                        buttonId,
                        isScrubbingTimeEnabled
                    )
                }
                }
            }
            }
        val notifActionButtons =
        val notifActionButtons =
@@ -304,7 +295,7 @@ class MediaControlViewModel(


    private fun toSemanticActionViewModel(
    private fun toSemanticActionViewModel(
        model: MediaControlModel,
        model: MediaControlModel,
        mediaAction: MediaAction,
        mediaAction: MediaAction?,
        buttonId: Int,
        buttonId: Int,
        canShowScrubbingTimeViews: Boolean
        canShowScrubbingTimeViews: Boolean
    ): MediaActionViewModel {
    ): MediaActionViewModel {
@@ -312,9 +303,9 @@ class MediaControlViewModel(
        val hideWhenScrubbing = SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.contains(buttonId)
        val hideWhenScrubbing = SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.contains(buttonId)
        val shouldHideWhenScrubbing = canShowScrubbingTimeViews && hideWhenScrubbing
        val shouldHideWhenScrubbing = canShowScrubbingTimeViews && hideWhenScrubbing
        return MediaActionViewModel(
        return MediaActionViewModel(
            icon = mediaAction.icon,
            icon = mediaAction?.icon,
            contentDescription = mediaAction.contentDescription,
            contentDescription = mediaAction?.contentDescription,
            background = mediaAction.background,
            background = mediaAction?.background,
            isVisibleWhenScrubbing = !shouldHideWhenScrubbing,
            isVisibleWhenScrubbing = !shouldHideWhenScrubbing,
            notVisibleValue =
            notVisibleValue =
                if (
                if (
@@ -326,11 +317,11 @@ class MediaControlViewModel(
                    ConstraintSet.GONE
                    ConstraintSet.GONE
                },
                },
            showInCollapsed = showInCollapsed,
            showInCollapsed = showInCollapsed,
            rebindId = mediaAction.rebindId,
            rebindId = mediaAction?.rebindId,
            buttonId = buttonId,
            buttonId = buttonId,
            isEnabled = mediaAction.action != null,
            isEnabled = mediaAction?.action != null,
            onClicked = { id ->
            onClicked = { id ->
                mediaAction.action?.let {
                mediaAction?.action?.let {
                    onButtonClicked(id, model.uid, model.packageName, model.instanceId, it)
                    onButtonClicked(id, model.uid, model.packageName, model.instanceId, it)
                }
                }
            },
            },
@@ -366,7 +357,7 @@ class MediaControlViewModel(
    ) {
    ) {
        logger.logTapAction(id, uid, packageName, instanceId)
        logger.logTapAction(id, uid, packageName, instanceId)
        // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_CLICK_EVENT)
        // TODO (b/330897926) log smartspace card reported (SMARTSPACE_CARD_CLICK_EVENT)
        isAnyButtonClicked.value = true
        isAnyButtonClicked = true
        action.run()
        action.run()
    }
    }


+1 −1
Original line number Original line Diff line number Diff line
@@ -35,7 +35,7 @@ data class MediaPlayerViewModel(
    val canShowTime: Boolean,
    val canShowTime: Boolean,
    val playTurbulenceNoise: Boolean,
    val playTurbulenceNoise: Boolean,
    val useSemanticActions: Boolean,
    val useSemanticActions: Boolean,
    val actionButtons: List<MediaActionViewModel?>,
    val actionButtons: List<MediaActionViewModel>,
    val outputSwitcher: MediaOutputSwitcherViewModel,
    val outputSwitcher: MediaOutputSwitcherViewModel,
    val gutsMenu: GutsViewModel,
    val gutsMenu: GutsViewModel,
    val onClicked: (Expandable) -> Unit,
    val onClicked: (Expandable) -> Unit,