Loading packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt +0 −16 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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( Loading packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt +44 −44 Original line number Original line Diff line number Diff line Loading @@ -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 -> Loading @@ -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, Loading @@ -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) Loading packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt +8 −6 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 = Loading packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt +35 −44 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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( Loading @@ -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, Loading @@ -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, Loading @@ -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 -> Loading @@ -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), Loading @@ -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) } ) } } } } } } Loading Loading @@ -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 = Loading @@ -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 { Loading @@ -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 ( Loading @@ -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) } } }, }, Loading Loading @@ -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() } } Loading packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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, Loading Loading
packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt +0 −16 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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( Loading
packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt +44 −44 Original line number Original line Diff line number Diff line Loading @@ -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 -> Loading @@ -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, Loading @@ -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) Loading
packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt +8 −6 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 = Loading
packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt +35 −44 Original line number Original line Diff line number Diff line Loading @@ -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 Loading @@ -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( Loading @@ -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, Loading @@ -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, Loading @@ -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 -> Loading @@ -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), Loading @@ -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) } ) } } } } } } Loading Loading @@ -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 = Loading @@ -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 { Loading @@ -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 ( Loading @@ -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) } } }, }, Loading Loading @@ -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() } } Loading
packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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, Loading