diff options
10 files changed, 258 insertions, 231 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt index 4055818dcb0b..7a6de5c07b43 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt @@ -55,6 +55,7 @@ import com.android.systemui.media.controls.ui.viewmodel.MediaOutputSwitcherViewM import com.android.systemui.media.controls.ui.viewmodel.MediaPlayerViewModel import com.android.systemui.media.controls.util.MediaDataUtils import com.android.systemui.monet.ColorScheme +import com.android.systemui.monet.Style import com.android.systemui.plugins.FalsingManager import com.android.systemui.res.R import com.android.systemui.surfaceeffects.ripple.MultiRippleView @@ -66,6 +67,8 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +private const val TAG = "MediaControlViewBinder" + object MediaControlViewBinder { fun bind( @@ -234,9 +237,6 @@ object MediaControlViewBinder { } } setDismissible(model.isDismissEnabled) - setTextPrimaryColor(model.textPrimaryColor) - setAccentPrimaryColor(model.accentPrimaryColor) - setSurfaceColor(model.surfaceColor) } } @@ -423,22 +423,37 @@ object MediaControlViewBinder { val width = viewController.widthInSceneContainerPx val height = viewController.heightInSceneContainerPx withContext(backgroundDispatcher) { + val wallpaperColors = + MediaArtworkHelper.getWallpaperColor( + viewHolder.albumView.context, + backgroundDispatcher, + viewModel.backgroundCover, + TAG, + ) + val isArtworkBound = wallpaperColors != null + val scheme = + wallpaperColors?.let { ColorScheme(it, true, Style.CONTENT) } + ?: let { + if (viewModel.launcherIcon is Icon.Loaded) { + MediaArtworkHelper.getColorScheme(viewModel.launcherIcon.drawable, TAG) + } else { + null + } + } val artwork = - if (viewModel.shouldAddGradient) { + wallpaperColors?.let { addGradientToPlayerAlbum( viewHolder.albumView.context, viewModel.backgroundCover!!, - viewModel.colorScheme, + scheme!!, width, height, ) - } else { - ColorDrawable(Color.TRANSPARENT) - } + } ?: ColorDrawable(Color.TRANSPARENT) withContext(mainDispatcher) { // Transition Colors to current color scheme val colorSchemeChanged = - viewController.colorSchemeTransition.updateColorScheme(viewModel.colorScheme) + viewController.colorSchemeTransition.updateColorScheme(scheme) val albumView = viewHolder.albumView // Set up width of album view constraint. @@ -449,7 +464,7 @@ object MediaControlViewBinder { if ( updateBackground || colorSchemeChanged || - (!viewController.isArtworkBound && viewModel.shouldAddGradient) + (!viewController.isArtworkBound && isArtworkBound) ) { viewController.prevArtwork?.let { // Since we throw away the last transition, this will pop if your @@ -464,12 +479,10 @@ object MediaControlViewBinder { transitionDrawable.isCrossFadeEnabled = true albumView.setImageDrawable(transitionDrawable) - transitionDrawable.startTransition( - if (viewModel.shouldAddGradient) 333 else 80 - ) + transitionDrawable.startTransition(if (isArtworkBound) 333 else 80) } ?: albumView.setImageDrawable(artwork) } - viewController.isArtworkBound = viewModel.shouldAddGradient + viewController.isArtworkBound = isArtworkBound viewController.prevArtwork = artwork if (viewModel.useGrayColorFilter) { diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt index 5e8a879adbb4..8a04799d3f94 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt @@ -16,13 +16,24 @@ package com.android.systemui.media.controls.ui.binder +import android.app.WallpaperColors import android.content.Context import android.content.res.ColorStateList import android.content.res.Configuration +import android.graphics.Bitmap +import android.graphics.Color import android.graphics.Matrix +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import android.graphics.drawable.GradientDrawable +import android.graphics.drawable.Icon +import android.graphics.drawable.LayerDrawable +import android.os.Trace import android.util.TypedValue import android.view.View import android.view.ViewGroup +import androidx.appcompat.content.res.AppCompatResources import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope @@ -30,17 +41,29 @@ import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.animation.Expandable import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.media.controls.shared.model.NUM_REQUIRED_RECOMMENDATIONS +import com.android.systemui.media.controls.ui.animation.surfaceFromScheme +import com.android.systemui.media.controls.ui.animation.textPrimaryFromScheme +import com.android.systemui.media.controls.ui.animation.textSecondaryFromScheme import com.android.systemui.media.controls.ui.controller.MediaViewController +import com.android.systemui.media.controls.ui.util.MediaArtworkHelper import com.android.systemui.media.controls.ui.view.RecommendationViewHolder import com.android.systemui.media.controls.ui.viewmodel.MediaRecViewModel import com.android.systemui.media.controls.ui.viewmodel.MediaRecommendationsViewModel import com.android.systemui.media.controls.ui.viewmodel.MediaRecsCardViewModel +import com.android.systemui.monet.ColorScheme +import com.android.systemui.monet.Style import com.android.systemui.plugins.FalsingManager import com.android.systemui.res.R import com.android.systemui.util.animation.TransitionLayout import kotlin.math.min +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +private const val TAG = "MediaRecommendationsViewBinder" +private const val MEDIA_REC_SCRIM_START_ALPHA = 0.15f +private const val MEDIA_REC_SCRIM_END_ALPHA = 1.0f object MediaRecommendationsViewBinder { @@ -50,6 +73,8 @@ object MediaRecommendationsViewBinder { viewModel: MediaRecommendationsViewModel, mediaViewController: MediaViewController, falsingManager: FalsingManager, + backgroundDispatcher: CoroutineDispatcher, + mainDispatcher: CoroutineDispatcher, ) { mediaViewController.recsConfigurationChangeListener = this::updateRecommendationsVisibility val cardView = viewHolder.recommendations @@ -59,7 +84,14 @@ object MediaRecommendationsViewBinder { launch { viewModel.mediaRecsCard.collectLatest { viewModel -> viewModel?.let { - bindRecsCard(viewHolder, it, mediaViewController, falsingManager) + bindRecsCard( + viewHolder, + it, + mediaViewController, + falsingManager, + backgroundDispatcher, + mainDispatcher, + ) } } } @@ -68,19 +100,19 @@ object MediaRecommendationsViewBinder { } } - fun bindRecsCard( + suspend fun bindRecsCard( viewHolder: RecommendationViewHolder, viewModel: MediaRecsCardViewModel, viewController: MediaViewController, falsingManager: FalsingManager, + backgroundDispatcher: CoroutineDispatcher, + mainDispatcher: CoroutineDispatcher, ) { // Set up media control location and its listener. viewModel.onLocationChanged(viewController.currentEndLocation) viewController.locationChangeListener = viewModel.onLocationChanged // Bind main card. - viewHolder.cardTitle.setTextColor(viewModel.cardTitleColor) - viewHolder.recommendations.backgroundTintList = ColorStateList.valueOf(viewModel.cardColor) viewHolder.recommendations.contentDescription = viewModel.contentDescription.invoke(viewController.isGutsVisible) @@ -100,8 +132,17 @@ object MediaRecommendationsViewBinder { return@setOnLongClickListener true } + // Bind colors + val appIcon = viewModel.mediaRecs.first().appIcon + fetchAndUpdateColors(viewHolder, appIcon, backgroundDispatcher, mainDispatcher) // Bind all recommendations. - bindRecommendationsList(viewHolder, viewModel.mediaRecs, falsingManager) + bindRecommendationsList( + viewHolder, + viewModel.mediaRecs, + falsingManager, + backgroundDispatcher, + mainDispatcher, + ) updateRecommendationsVisibility(viewController, viewHolder.recommendations) // Set visibility of recommendations. @@ -153,26 +194,21 @@ object MediaRecommendationsViewBinder { } gutsViewHolder.setDismissible(gutsViewModel.isDismissEnabled) - gutsViewHolder.setTextPrimaryColor(gutsViewModel.textPrimaryColor) - gutsViewHolder.setAccentPrimaryColor(gutsViewModel.accentPrimaryColor) - gutsViewHolder.setSurfaceColor(gutsViewModel.surfaceColor) } - private fun bindRecommendationsList( + private suspend fun bindRecommendationsList( viewHolder: RecommendationViewHolder, mediaRecs: List<MediaRecViewModel>, - falsingManager: FalsingManager + falsingManager: FalsingManager, + backgroundDispatcher: CoroutineDispatcher, + mainDispatcher: CoroutineDispatcher, ) { mediaRecs.forEachIndexed { index, mediaRecViewModel -> if (index >= NUM_REQUIRED_RECOMMENDATIONS) return@forEachIndexed val appIconView = viewHolder.mediaAppIcons[index] appIconView.clearColorFilter() - if (mediaRecViewModel.appIcon != null) { - appIconView.setImageDrawable(mediaRecViewModel.appIcon) - } else { - appIconView.setImageResource(R.drawable.ic_music_note) - } + appIconView.setImageDrawable(mediaRecViewModel.appIcon) val mediaCoverContainer = viewHolder.mediaCoverContainers[index] mediaCoverContainer.setOnClickListener { @@ -187,29 +223,24 @@ object MediaRecommendationsViewBinder { } val mediaCover = viewHolder.mediaCoverItems[index] - val width: Int = - mediaCover.context.resources.getDimensionPixelSize(R.dimen.qs_media_rec_album_width) - val height: Int = - mediaCover.context.resources.getDimensionPixelSize( - R.dimen.qs_media_rec_album_height_expanded - ) - val coverMatrix = Matrix(mediaCover.imageMatrix) - coverMatrix.postScale(1.25f, 1.25f, 0.5f * width, 0.5f * height) - mediaCover.imageMatrix = coverMatrix - mediaCover.setImageDrawable(mediaRecViewModel.albumIcon) + bindRecommendationArtwork( + mediaCover.context, + viewHolder, + mediaRecViewModel, + index, + backgroundDispatcher, + mainDispatcher, + ) mediaCover.contentDescription = mediaRecViewModel.contentDescription val title = viewHolder.mediaTitles[index] title.text = mediaRecViewModel.title - title.setTextColor(ColorStateList.valueOf(mediaRecViewModel.titleColor)) val subtitle = viewHolder.mediaSubtitles[index] subtitle.text = mediaRecViewModel.subtitle - subtitle.setTextColor(ColorStateList.valueOf(mediaRecViewModel.subtitleColor)) val progressBar = viewHolder.mediaProgressBars[index] progressBar.progress = mediaRecViewModel.progress - progressBar.progressTintList = ColorStateList.valueOf(mediaRecViewModel.progressColor) if (mediaRecViewModel.progress == 0) { progressBar.visibility = View.GONE } @@ -291,11 +322,148 @@ object MediaRecommendationsViewBinder { TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, displayAvailableDpWidth.toFloat(), - res.displayMetrics + res.displayMetrics, ) .toInt() displayAvailableWidth / recCoverWidth } return min(fittedNum.toDouble(), NUM_REQUIRED_RECOMMENDATIONS.toDouble()).toInt() } + + private suspend fun bindRecommendationArtwork( + context: Context, + viewHolder: RecommendationViewHolder, + viewModel: MediaRecViewModel, + index: Int, + backgroundDispatcher: CoroutineDispatcher, + mainDispatcher: CoroutineDispatcher, + ) { + val traceCookie = viewHolder.hashCode() + val traceName = "MediaRecommendationsViewBinder#bindRecommendationArtwork" + Trace.beginAsyncSection(traceName, traceCookie) + + // Capture width & height from views in foreground for artwork scaling in background + val width = context.resources.getDimensionPixelSize(R.dimen.qs_media_rec_album_width) + val height = + context.resources.getDimensionPixelSize(R.dimen.qs_media_rec_album_height_expanded) + + withContext(backgroundDispatcher) { + val artwork = + getRecCoverBackground( + context, + viewModel.albumIcon, + width, + height, + backgroundDispatcher, + ) + withContext(mainDispatcher) { + val mediaCover = viewHolder.mediaCoverItems[index] + val coverMatrix = Matrix(mediaCover.imageMatrix) + coverMatrix.postScale(1.25f, 1.25f, 0.5f * width, 0.5f * height) + mediaCover.imageMatrix = coverMatrix + mediaCover.setImageDrawable(artwork) + } + } + } + + /** Returns the recommendation album cover of [width]x[height] size. */ + private suspend fun getRecCoverBackground( + context: Context, + icon: Icon?, + width: Int, + height: Int, + backgroundDispatcher: CoroutineDispatcher, + ): Drawable = + withContext(backgroundDispatcher) { + return@withContext MediaArtworkHelper.getWallpaperColor( + context, + backgroundDispatcher, + icon, + TAG, + ) + ?.let { wallpaperColors -> + addGradientToRecommendationAlbum( + context, + icon!!, + ColorScheme(wallpaperColors, true, Style.CONTENT), + width, + height, + ) + } ?: ColorDrawable(Color.TRANSPARENT) + } + + private fun addGradientToRecommendationAlbum( + context: Context, + artworkIcon: Icon, + mutableColorScheme: ColorScheme, + width: Int, + height: Int, + ): LayerDrawable { + // First try scaling rec card using bitmap drawable. + // If returns null, set drawable bounds. + val albumArt = + getScaledRecommendationCover(context, artworkIcon, width, height) + ?: MediaArtworkHelper.getScaledBackground(context, artworkIcon, width, height) + val gradient = + AppCompatResources.getDrawable(context, R.drawable.qs_media_rec_scrim)?.mutate() + as GradientDrawable + return MediaArtworkHelper.setUpGradientColorOnDrawable( + albumArt, + gradient, + mutableColorScheme, + MEDIA_REC_SCRIM_START_ALPHA, + MEDIA_REC_SCRIM_END_ALPHA, + ) + } + + /** Returns a [Drawable] of a given [artworkIcon] scaled to [width]x[height] size, . */ + private fun getScaledRecommendationCover( + context: Context, + artworkIcon: Icon, + width: Int, + height: Int, + ): Drawable? { + check(width > 0) { "Width must be a positive number but was $width" } + check(height > 0) { "Height must be a positive number but was $height" } + + return if ( + artworkIcon.type == Icon.TYPE_BITMAP || artworkIcon.type == Icon.TYPE_ADAPTIVE_BITMAP + ) { + artworkIcon.bitmap?.let { + val bitmap = Bitmap.createScaledBitmap(it, width, height, false) + BitmapDrawable(context.resources, bitmap) + } + } else { + null + } + } + + private suspend fun fetchAndUpdateColors( + viewHolder: RecommendationViewHolder, + appIcon: Drawable, + backgroundDispatcher: CoroutineDispatcher, + mainDispatcher: CoroutineDispatcher, + ) = + withContext(backgroundDispatcher) { + val colorScheme = + ColorScheme(WallpaperColors.fromDrawable(appIcon), /* darkTheme= */ true) + withContext(mainDispatcher) { + val backgroundColor = surfaceFromScheme(colorScheme) + val textPrimaryColor = textPrimaryFromScheme(colorScheme) + val textSecondaryColor = textSecondaryFromScheme(colorScheme) + + viewHolder.cardTitle.setTextColor(textPrimaryColor) + viewHolder.recommendations.setBackgroundTintList( + ColorStateList.valueOf(backgroundColor) + ) + + viewHolder.mediaTitles.forEach { it.setTextColor(textPrimaryColor) } + viewHolder.mediaSubtitles.forEach { it.setTextColor(textSecondaryColor) } + viewHolder.mediaProgressBars.forEach { + it.progressTintList = ColorStateList.valueOf(textPrimaryColor) + } + + viewHolder.gutsViewHolder.setColors(colorScheme) + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt index 49a8758ed51e..bb9517a14142 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt @@ -768,6 +768,8 @@ constructor( commonViewModel.recsViewModel, viewController, falsingManager, + backgroundDispatcher, + mainDispatcher, ) mediaContent.addView(viewHolder.recommendations, position) controllerById[commonViewModel.key] = viewController diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt index c97221e7bd50..c21513b1263a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaArtworkHelper.kt @@ -87,26 +87,19 @@ object MediaArtworkHelper { gradient: GradientDrawable, colorScheme: ColorScheme, startAlpha: Float, - endAlpha: Float + endAlpha: Float, ): LayerDrawable { gradient.colors = intArrayOf( getColorWithAlpha(backgroundStartFromScheme(colorScheme), startAlpha), - getColorWithAlpha(backgroundEndFromScheme(colorScheme), endAlpha) + getColorWithAlpha(backgroundEndFromScheme(colorScheme), endAlpha), ) return LayerDrawable(arrayOf(albumArt, gradient)) } - /** Returns [ColorScheme] of media app given its [packageName]. */ - fun getColorScheme( - applicationContext: Context, - packageName: String, - tag: String, - style: Style = Style.TONAL_SPOT - ): ColorScheme? { + /** Returns [ColorScheme] of media app given its [icon]. */ + fun getColorScheme(icon: Drawable, tag: String, style: Style = Style.TONAL_SPOT): ColorScheme? { return try { - // Set up media source app's logo. - val icon = applicationContext.packageManager.getApplicationIcon(packageName) ColorScheme(WallpaperColors.fromDrawable(icon), true, style) } catch (e: PackageManager.NameNotFoundException) { Log.w(tag, "Fail to get media app info", e) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt index 6c7c31c41eeb..314d9afe5aa6 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/GutsViewModel.kt @@ -16,15 +16,11 @@ package com.android.systemui.media.controls.ui.viewmodel -import android.annotation.ColorInt import android.graphics.drawable.Drawable /** Models UI state for media guts menu */ data class GutsViewModel( val gutsText: CharSequence, - @ColorInt val textPrimaryColor: Int, - @ColorInt val accentPrimaryColor: Int, - @ColorInt val surfaceColor: Int, val isDismissEnabled: Boolean = true, val onDismissClicked: () -> Unit, val cancelTextBackground: Drawable?, diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt index 104d155ab74e..f07f2de08537 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt @@ -33,15 +33,9 @@ import com.android.systemui.media.controls.domain.pipeline.interactor.MediaContr import com.android.systemui.media.controls.shared.model.MediaAction import com.android.systemui.media.controls.shared.model.MediaButton import com.android.systemui.media.controls.shared.model.MediaControlModel -import com.android.systemui.media.controls.ui.animation.accentPrimaryFromScheme -import com.android.systemui.media.controls.ui.animation.surfaceFromScheme -import com.android.systemui.media.controls.ui.animation.textPrimaryFromScheme -import com.android.systemui.media.controls.ui.util.MediaArtworkHelper import com.android.systemui.media.controls.util.MediaSmartspaceLogger.Companion.SMARTSPACE_CARD_CLICK_EVENT import com.android.systemui.media.controls.util.MediaSmartspaceLogger.Companion.SMARTSPACE_CARD_DISMISS_EVENT import com.android.systemui.media.controls.util.MediaUiEventLogger -import com.android.systemui.monet.ColorScheme -import com.android.systemui.monet.Style import com.android.systemui.res.R import java.util.concurrent.Executor import kotlinx.coroutines.CoroutineDispatcher @@ -104,26 +98,9 @@ class MediaControlViewModel( ) } - private suspend fun toViewModel(model: MediaControlModel): MediaPlayerViewModel? { + private fun toViewModel(model: MediaControlModel): MediaPlayerViewModel { val mediaController = model.token?.let { MediaController(applicationContext, it) } - val wallpaperColors = - MediaArtworkHelper.getWallpaperColor( - applicationContext, - backgroundDispatcher, - model.artwork, - TAG, - ) - val scheme = - wallpaperColors?.let { ColorScheme(it, true, Style.CONTENT) } - ?: MediaArtworkHelper.getColorScheme( - applicationContext, - model.packageName, - TAG, - Style.CONTENT, - ) - ?: return null - - val gutsViewModel = toGutsViewModel(model, scheme) + val gutsViewModel = toGutsViewModel(model) // Set playing state val wasPlaying = isPlaying @@ -154,8 +131,6 @@ class MediaControlViewModel( artistName = model.artistName ?: "", titleName = model.songName ?: "", isExplicitVisible = model.showExplicit, - shouldAddGradient = wallpaperColors != null, - colorScheme = scheme, canShowTime = canShowScrubbingTimeViews(model.semanticActionButtons), playTurbulenceNoise = isPlaying && !wasPlaying && wasButtonClicked, useSemanticActions = model.semanticActionButtons != null, @@ -276,7 +251,7 @@ class MediaControlViewModel( ) } - private fun toGutsViewModel(model: MediaControlModel, scheme: ColorScheme): GutsViewModel { + private fun toGutsViewModel(model: MediaControlModel): GutsViewModel { return GutsViewModel( gutsText = if (model.isDismissible) { @@ -287,9 +262,6 @@ class MediaControlViewModel( } else { applicationContext.getString(R.string.controls_media_active_session) }, - textPrimaryColor = textPrimaryFromScheme(scheme), - accentPrimaryColor = accentPrimaryFromScheme(scheme), - surfaceColor = surfaceFromScheme(scheme), isDismissEnabled = model.isDismissible, onDismissClicked = { onDismissMediaData(model.token, model.uid, model.packageName, model.instanceId) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt index f4b0d6e2c990..4aae72fb375b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaPlayerViewModel.kt @@ -18,7 +18,6 @@ package com.android.systemui.media.controls.ui.viewmodel import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon -import com.android.systemui.monet.ColorScheme /** Models UI state for media player. */ data class MediaPlayerViewModel( @@ -30,8 +29,6 @@ data class MediaPlayerViewModel( val artistName: CharSequence, val titleName: CharSequence, val isExplicitVisible: Boolean, - val shouldAddGradient: Boolean, - val colorScheme: ColorScheme, val canShowTime: Boolean, val playTurbulenceNoise: Boolean, val useSemanticActions: Boolean, @@ -52,7 +49,6 @@ data class MediaPlayerViewModel( artistName == other.artistName && titleName == other.titleName && isExplicitVisible == other.isExplicitVisible && - shouldAddGradient == other.shouldAddGradient && canShowTime == other.canShowTime && playTurbulenceNoise == other.playTurbulenceNoise && useSemanticActions == other.useSemanticActions && diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecViewModel.kt index 2f9fc9bc699a..77add4035067 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecViewModel.kt @@ -16,21 +16,18 @@ package com.android.systemui.media.controls.ui.viewmodel -import android.annotation.ColorInt import android.graphics.drawable.Drawable +import android.graphics.drawable.Icon import com.android.systemui.animation.Expandable /** Models UI state for media recommendation item */ data class MediaRecViewModel( val contentDescription: CharSequence, val title: CharSequence = "", - @ColorInt val titleColor: Int, val subtitle: CharSequence = "", - @ColorInt val subtitleColor: Int, /** track progress [0 - 100] for the recommendation album. */ val progress: Int = 0, - @ColorInt val progressColor: Int, - val albumIcon: Drawable? = null, - val appIcon: Drawable? = null, + val albumIcon: Icon? = null, + val appIcon: Drawable, val onClicked: ((Expandable, Int) -> Unit), ) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt index 1fd9c4f014ee..a7bce7772270 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt @@ -18,17 +18,10 @@ package com.android.systemui.media.controls.ui.viewmodel import android.content.Context import android.content.Intent -import android.graphics.Bitmap -import android.graphics.Color -import android.graphics.drawable.BitmapDrawable -import android.graphics.drawable.ColorDrawable +import android.content.pm.PackageManager import android.graphics.drawable.Drawable -import android.graphics.drawable.GradientDrawable -import android.graphics.drawable.Icon -import android.graphics.drawable.LayerDrawable import android.os.Process import android.util.Log -import androidx.appcompat.content.res.AppCompatResources import com.android.internal.logging.InstanceId import com.android.systemui.animation.Expandable import com.android.systemui.dagger.SysUISingleton @@ -38,18 +31,11 @@ import com.android.systemui.media.controls.domain.pipeline.interactor.MediaRecom import com.android.systemui.media.controls.shared.model.MediaRecModel import com.android.systemui.media.controls.shared.model.MediaRecommendationsModel import com.android.systemui.media.controls.shared.model.NUM_REQUIRED_RECOMMENDATIONS -import com.android.systemui.media.controls.ui.animation.accentPrimaryFromScheme -import com.android.systemui.media.controls.ui.animation.surfaceFromScheme -import com.android.systemui.media.controls.ui.animation.textPrimaryFromScheme -import com.android.systemui.media.controls.ui.animation.textSecondaryFromScheme import com.android.systemui.media.controls.ui.controller.MediaViewController.Companion.GUTS_ANIMATION_DURATION -import com.android.systemui.media.controls.ui.util.MediaArtworkHelper import com.android.systemui.media.controls.util.MediaDataUtils import com.android.systemui.media.controls.util.MediaSmartspaceLogger.Companion.SMARTSPACE_CARD_CLICK_EVENT import com.android.systemui.media.controls.util.MediaSmartspaceLogger.Companion.SMARTSPACE_CARD_DISMISS_EVENT import com.android.systemui.media.controls.util.MediaUiEventLogger -import com.android.systemui.monet.ColorScheme -import com.android.systemui.monet.Style import com.android.systemui.res.R import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher @@ -59,7 +45,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map -import kotlinx.coroutines.withContext /** Models UI state and handles user input for media recommendations */ @SysUISingleton @@ -92,7 +77,7 @@ constructor( uid: Int, packageName: String, dismissIntent: Intent?, - instanceId: InstanceId? + instanceId: InstanceId?, ) { logger.logLongPressDismiss(uid, packageName, instanceId) interactor.removeMediaRecommendations( @@ -100,7 +85,7 @@ constructor( dismissIntent, GUTS_DISMISS_DELAY_MS_DURATION, SMARTSPACE_CARD_DISMISS_EVENT, - location + location, ) } @@ -109,7 +94,7 @@ constructor( intent: Intent?, packageName: String, instanceId: InstanceId?, - index: Int + index: Int, ) { if (intent == null || intent.extras == null) { Log.e(TAG, "No tap action can be set up") @@ -131,7 +116,7 @@ constructor( SMARTSPACE_CARD_CLICK_EVENT, location, index, - NUM_REQUIRED_RECOMMENDATIONS + NUM_REQUIRED_RECOMMENDATIONS, ) } @@ -145,22 +130,7 @@ constructor( return null } - val scheme = - MediaArtworkHelper.getColorScheme(applicationContext, model.packageName, TAG) - ?: return null - - // Capture width & height from views in foreground for artwork scaling in background - val width = - applicationContext.resources.getDimensionPixelSize(R.dimen.qs_media_rec_album_width) - val height = - applicationContext.resources.getDimensionPixelSize( - R.dimen.qs_media_rec_album_height_expanded - ) - - val appIcon = applicationContext.packageManager.getApplicationIcon(model.packageName) - val textPrimaryColor = textPrimaryFromScheme(scheme) - val textSecondaryColor = textSecondaryFromScheme(scheme) - val backgroundColor = surfaceFromScheme(scheme) + val appIcon = getIconFromApp(model.packageName) ?: return null var areTitlesVisible = false var areSubtitlesVisible = false @@ -173,17 +143,9 @@ constructor( contentDescription = setUpMediaRecContentDescription(mediaRecModel, model.appName), title = mediaRecModel.title ?: "", - titleColor = textPrimaryColor, subtitle = mediaRecModel.subtitle ?: "", - subtitleColor = textSecondaryColor, progress = (progress * 100).toInt(), - progressColor = textPrimaryColor, - albumIcon = - getRecCoverBackground( - mediaRecModel.icon, - width, - height, - ), + albumIcon = mediaRecModel.icon, appIcon = appIcon, onClicked = { expandable, index -> onClicked( @@ -193,7 +155,7 @@ constructor( model.instanceId, index, ) - } + }, ) } // Subtitles should only be visible if titles are visible. @@ -204,21 +166,19 @@ constructor( if (gutsVisible) { applicationContext.getString( R.string.controls_media_close_session, - model.appName + model.appName, ) } else { applicationContext.getString(R.string.controls_media_smartspace_rec_header) } }, - cardColor = backgroundColor, - cardTitleColor = textPrimaryColor, onClicked = { expandable -> onClicked( expandable, model.dismissIntent, model.packageName, model.instanceId, - index = -1 + index = -1, ) }, onLongClicked = { @@ -227,28 +187,22 @@ constructor( mediaRecs = mediaRecs, areTitlesVisible = areTitlesVisible, areSubtitlesVisible = areSubtitlesVisible, - gutsMenu = toGutsViewModel(model, scheme), - onLocationChanged = { location = it } + gutsMenu = toGutsViewModel(model), + onLocationChanged = { location = it }, ) } - private fun toGutsViewModel( - model: MediaRecommendationsModel, - scheme: ColorScheme - ): GutsViewModel { + private fun toGutsViewModel(model: MediaRecommendationsModel): GutsViewModel { return GutsViewModel( gutsText = applicationContext.getString(R.string.controls_media_close_session, model.appName), - textPrimaryColor = textPrimaryFromScheme(scheme), - accentPrimaryColor = accentPrimaryFromScheme(scheme), - surfaceColor = surfaceFromScheme(scheme), onDismissClicked = { onMediaRecommendationsDismissed( model.key, model.uid, model.packageName, model.dismissIntent, - model.instanceId + model.instanceId, ) }, cancelTextBackground = @@ -260,56 +214,9 @@ constructor( ) } - /** Returns the recommendation album cover of [width]x[height] size. */ - private suspend fun getRecCoverBackground(icon: Icon?, width: Int, height: Int): Drawable = - withContext(backgroundDispatcher) { - return@withContext MediaArtworkHelper.getWallpaperColor( - applicationContext, - backgroundDispatcher, - icon, - TAG, - ) - ?.let { wallpaperColors -> - addGradientToRecommendationAlbum( - icon!!, - ColorScheme(wallpaperColors, true, Style.CONTENT), - width, - height - ) - } ?: ColorDrawable(Color.TRANSPARENT) - } - - private fun addGradientToRecommendationAlbum( - artworkIcon: Icon, - mutableColorScheme: ColorScheme, - width: Int, - height: Int - ): LayerDrawable { - // First try scaling rec card using bitmap drawable. - // If returns null, set drawable bounds. - val albumArt = - getScaledRecommendationCover(artworkIcon, width, height) - ?: MediaArtworkHelper.getScaledBackground( - applicationContext, - artworkIcon, - width, - height - ) - val gradient = - AppCompatResources.getDrawable(applicationContext, R.drawable.qs_media_rec_scrim) - ?.mutate() as GradientDrawable - return MediaArtworkHelper.setUpGradientColorOnDrawable( - albumArt, - gradient, - mutableColorScheme, - MEDIA_REC_SCRIM_START_ALPHA, - MEDIA_REC_SCRIM_END_ALPHA - ) - } - private fun setUpMediaRecContentDescription( mediaRec: MediaRecModel, - appName: CharSequence? + appName: CharSequence?, ): CharSequence { // Set up the accessibility label for the media item. val artistName = mediaRec.extras?.getString(KEY_SMARTSPACE_ARTIST_NAME, "") @@ -317,35 +224,23 @@ constructor( applicationContext.getString( R.string.controls_media_smartspace_rec_item_no_artist_description, mediaRec.title, - appName + appName, ) } else { applicationContext.getString( R.string.controls_media_smartspace_rec_item_description, mediaRec.title, artistName, - appName + appName, ) } } - /** Returns a [Drawable] of a given [artworkIcon] scaled to [width]x[height] size, . */ - private fun getScaledRecommendationCover( - artworkIcon: Icon, - width: Int, - height: Int - ): Drawable? { - check(width > 0) { "Width must be a positive number but was $width" } - check(height > 0) { "Height must be a positive number but was $height" } - - return if ( - artworkIcon.type == Icon.TYPE_BITMAP || artworkIcon.type == Icon.TYPE_ADAPTIVE_BITMAP - ) { - artworkIcon.bitmap?.let { - val bitmap = Bitmap.createScaledBitmap(it, width, height, false) - BitmapDrawable(applicationContext.resources, bitmap) - } - } else { + private fun getIconFromApp(packageName: String): Drawable? { + return try { + applicationContext.packageManager.getApplicationIcon(packageName) + } catch (e: PackageManager.NameNotFoundException) { + Log.w(TAG, "Cannot find icon for package $packageName", e) null } } @@ -353,8 +248,6 @@ constructor( companion object { private const val TAG = "MediaRecommendationsViewModel" private const val KEY_SMARTSPACE_ARTIST_NAME = "artist_name" - private const val MEDIA_REC_SCRIM_START_ALPHA = 0.15f - private const val MEDIA_REC_SCRIM_END_ALPHA = 1.0f /** * Delay duration is based on [GUTS_ANIMATION_DURATION], it should have 100 ms increase in * order to let the animation end. diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecsCardViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecsCardViewModel.kt index 5ecbcb20a58a..f1f7dc2195d5 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecsCardViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecsCardViewModel.kt @@ -16,14 +16,11 @@ package com.android.systemui.media.controls.ui.viewmodel -import android.annotation.ColorInt import com.android.systemui.animation.Expandable /** Models UI state for media recommendations card. */ data class MediaRecsCardViewModel( val contentDescription: (Boolean) -> CharSequence, - @ColorInt val cardColor: Int, - @ColorInt val cardTitleColor: Int, val onClicked: (Expandable) -> Unit, val onLongClicked: () -> Unit, val mediaRecs: List<MediaRecViewModel>, |