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

Commit 63cc7448 authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

[Media] Background loading improvements.

Changes the background to a snapshot state. This simplifies the compose
logic so it doesn't need to kick off a coroutine to load the background
and can more easily watch for new background images as they come in.

Also adds a crossfade effect between the unloaded/old and new art as it
comes in.

Bug: 397989775
Test: manually verified in the compose gallery app
Flag: EXEMPT the code is not yet used
Change-Id: Ieacc6e2f2656485fa2dbeee9cad77450a0384546
parent f3490d1e
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.systemui.media.remedia.domain.interactor

import android.graphics.Bitmap
import com.android.systemui.media.remedia.domain.model.MediaSessionModel

/**
@@ -28,14 +27,6 @@ interface MediaInteractor {
    /** The list of sessions. Needs to be backed by a compose snapshot state. */
    val sessions: List<MediaSessionModel>

    /**
     * Loads, on a background thread, the media art for a session with the given [sessionToken].
     *
     * This will be called on the main thread. It's the responsibility of the implementation to move
     * its work off the main thread.
     */
    suspend fun loadArt(sessionToken: Any): Bitmap

    /** Seek to [to], in milliseconds on the media session with the given [sessionKey]. */
    fun seek(sessionKey: Any, to: Long)

+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.media.remedia.domain.model

import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.ImageBitmap
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.media.remedia.shared.model.MediaCardActionButtonLayout
import com.android.systemui.media.remedia.shared.model.MediaSessionState
@@ -31,6 +32,8 @@ interface MediaSessionModel {

    val appIcon: Icon

    val background: ImageBitmap?

    val title: String

    val subtitle: String
+28 −38
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -68,9 +69,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -257,7 +256,7 @@ private fun Card(

    Box(modifier) {
        if (stlState.currentScene != Media.Scenes.Compact) {
            CardBackground(imageLoader = viewModel.artLoader, modifier = Modifier.matchParentSize())
            CardBackground(image = viewModel.background, modifier = Modifier.matchParentSize())
        }

        key(stlState) {
@@ -541,18 +540,18 @@ private fun ContentScope.CompactCardForeground(

/** Renders the background of a card, loading the artwork and showing an overlay on top of it. */
@Composable
private fun CardBackground(imageLoader: suspend () -> ImageBitmap, modifier: Modifier = Modifier) {
    var image: ImageBitmap? by remember { mutableStateOf(null) }
    LaunchedEffect(imageLoader) {
        image = null
        image = imageLoader()
    }

private fun CardBackground(image: ImageBitmap?, modifier: Modifier = Modifier) {
    Crossfade(targetState = image, modifier = modifier) { imageOrNull ->
        if (imageOrNull != null) {
            // Loaded art.
            val gradientBaseColor = MaterialTheme.colorScheme.onSurface
    Box(
            Image(
                bitmap = imageOrNull,
                contentDescription = null,
                contentScale = ContentScale.Crop,
                modifier =
            modifier.drawWithContent {
                // Draw the content of the box (loaded art or placeholder).
                    Modifier.fillMaxSize().drawWithContent {
                        // Draw the content (loaded art).
                        drawContent()

                        if (image != null) {
@@ -567,20 +566,11 @@ private fun CardBackground(imageLoader: suspend () -> ImageBitmap, modifier: Mod
                                    )
                            )
                        }
            }
    ) {
        image?.let { loadedImage ->
            // Loaded art.
            Image(
                bitmap = loadedImage,
                contentDescription = null,
                contentScale = ContentScale.Crop,
                modifier = Modifier.matchParentSize(),
                    },
            )
        }
            ?: run {
        } else {
            // Placeholder.
                Box(Modifier.background(MaterialTheme.colorScheme.onSurface).matchParentSize())
            Box(Modifier.background(MaterialTheme.colorScheme.onSurface).fillMaxSize())
        }
    }
}
+1 −6
Original line number Diff line number Diff line
@@ -32,12 +32,7 @@ interface MediaCardViewModel {

    val icon: Icon

    /**
     * A callback to load the artwork for the media shown on this card. This callback will be
     * invoked on the main thread, it's up to the implementation to move the loading off the main
     * thread.
     */
    val artLoader: suspend () -> ImageBitmap
    val background: ImageBitmap?

    val title: String

+4 −2
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.ImageBitmap
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.lifecycle.ExclusiveActivatable
@@ -63,7 +63,9 @@ constructor(
            object : MediaCardViewModel {
                override val key = session.key
                override val icon = session.appIcon
                override val artLoader = suspend { interactor.loadArt(session.key).asImageBitmap() }
                override val background: ImageBitmap?
                    get() = session.background

                override val title = session.title
                override val subtitle = session.subtitle
                override val actionButtonLayout = session.actionButtonLayout