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

Commit 359caa79 authored by Julia Tuttle's avatar Julia Tuttle
Browse files

Continue fleshing out progress bars on AOD RONs

Bug: 369151941
Flag: com.android.systemui.aod_ui_rich_ongoing
Test: manual
Change-Id: I83dc009b73c1a6cd91d95774ee87cc5715dda295
parent ad2a2509
Loading
Loading
Loading
Loading
+43 −3
Original line number Diff line number Diff line
@@ -237,9 +237,9 @@ class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {

        assertThat(content).isNotNull()
        assertThat(content?.style).isEqualTo(Style.Progress)
        assertThat(content?.progress).isNotNull()
        assertThat(content?.progress?.progress).isEqualTo(75)
        assertThat(content?.progress?.progressMax).isEqualTo(100)
        assertThat(content?.newProgress).isNotNull()
        assertThat(content?.newProgress?.progress).isEqualTo(75)
        assertThat(content?.newProgress?.progressMax).isEqualTo(100)
    }

    @Test
@@ -255,6 +255,43 @@ class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {
        assertThat(content?.style).isEqualTo(Style.Ineligible)
    }

    @Test
    @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
    fun extractsContent_fromOldProgressDeterminate() {
        val entry = createEntry {
            setProgress(TEST_PROGRESS_MAX, TEST_PROGRESS, /* indeterminate= */ false)
        }

        val content = extractContent(entry)

        assertThat(content).isNotNull()

        val oldProgress = content?.oldProgress
        assertThat(oldProgress).isNotNull()

        assertThat(content).isNotNull()
        assertThat(content?.oldProgress).isNotNull()
        assertThat(content?.oldProgress?.progress).isEqualTo(TEST_PROGRESS)
        assertThat(content?.oldProgress?.max).isEqualTo(TEST_PROGRESS_MAX)
        assertThat(content?.oldProgress?.isIndeterminate).isFalse()
    }

    @Test
    @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
    fun extractsContent_fromOldProgressIndeterminate() {
        val entry = createEntry {
            setProgress(TEST_PROGRESS_MAX, TEST_PROGRESS, /* indeterminate= */ true)
        }

        val content = extractContent(entry)

        assertThat(content).isNotNull()
        assertThat(content?.oldProgress).isNotNull()
        assertThat(content?.oldProgress?.progress).isEqualTo(TEST_PROGRESS)
        assertThat(content?.oldProgress?.max).isEqualTo(TEST_PROGRESS_MAX)
        assertThat(content?.oldProgress?.isIndeterminate).isTrue()
    }

    private fun extractContent(entry: NotificationEntry): PromotedNotificationContentModel? {
        val recoveredBuilder = Notification.Builder(context, entry.sbn.notification)
        return underTest.extractContent(entry, recoveredBuilder)
@@ -277,6 +314,9 @@ class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {
        private const val TEST_CONTENT_TEXT = "content text"
        private const val TEST_SHORT_CRITICAL_TEXT = "short"

        private const val TEST_PROGRESS = 50
        private const val TEST_PROGRESS_MAX = 100

        private const val TEST_PERSON_NAME = "person name"
        private const val TEST_PERSON_KEY = "person key"
        private val TEST_PERSON =
+85 −16
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.promoted

import android.app.Flags
import android.app.Notification
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
@@ -49,6 +50,7 @@ import com.android.internal.widget.CachingIconView
import com.android.internal.widget.ImageFloatingTextView
import com.android.internal.widget.NotificationExpandButton
import com.android.internal.widget.NotificationProgressBar
import com.android.internal.widget.NotificationProgressModel
import com.android.internal.widget.NotificationRowIconView
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.res.R as systemuiR
@@ -176,17 +178,17 @@ private class AODPromotedNotificationViewUpdater(root: View) {
    private val verificationIcon: ImageView? = root.findViewById(R.id.verification_icon)
    private val verificationText: TextView? = root.findViewById(R.id.verification_text)

    private var oldProgressStub = root.findViewById<View>(R.id.progress) as? ViewStub
    private var oldProgress: ProgressBar? = null
    private val newProgress = root.findViewById<View>(R.id.progress) as? NotificationProgressBar
    private var oldProgressBarStub = root.findViewById<View>(R.id.progress) as? ViewStub
    private var oldProgressBar: ProgressBar? = null
    private val newProgressBar = root.findViewById<View>(R.id.progress) as? NotificationProgressBar

    fun update(content: PromotedNotificationContentModel) {
        when (content.style) {
            Style.Base -> updateBase(content)
            Style.BigPicture -> updateBigPicture(content)
            Style.BigText -> updateBigText(content)
            Style.Call -> updateCall(content)
            Style.Progress -> updateProgress(content)
            Style.BigPicture -> updateBigPictureStyle(content)
            Style.BigText -> updateBigTextStyle(content)
            Style.Call -> updateCallStyle(content)
            Style.Progress -> updateProgressStyle(content)
            Style.Ineligible -> {}
        }
    }
@@ -194,42 +196,72 @@ private class AODPromotedNotificationViewUpdater(root: View) {
    private fun updateBase(
        content: PromotedNotificationContentModel,
        textView: ImageFloatingTextView? = null,
        showOldProgress: Boolean = true,
    ) {
        updateHeader(content)

        updateTitle(title, content)
        updateText(textView ?: text, content)

        if (showOldProgress) {
            updateOldProgressBar(content)
        }
    }

    private fun updateBigPicture(content: PromotedNotificationContentModel) {
    private fun updateBigPictureStyle(content: PromotedNotificationContentModel) {
        updateBase(content)

        bigPicture?.visibility = GONE
    }

    private fun updateBigText(content: PromotedNotificationContentModel) {
    private fun updateBigTextStyle(content: PromotedNotificationContentModel) {
        updateBase(content, textView = bigText)
    }

    private fun updateCall(content: PromotedNotificationContentModel) {
    private fun updateCallStyle(content: PromotedNotificationContentModel) {
        updateConversationHeader(content)

        updateText(text, content)
    }

    private fun updateProgress(content: PromotedNotificationContentModel) {
        updateBase(content)
    private fun updateProgressStyle(content: PromotedNotificationContentModel) {
        updateBase(content, showOldProgress = false)

        updateNewProgressBar(content)
    }

    private fun updateOldProgressBar(content: PromotedNotificationContentModel) {
        if (
            content.oldProgress == null ||
                content.oldProgress.max == 0 ||
                content.oldProgress.isIndeterminate
        ) {
            oldProgressBar?.visibility = GONE
            return
        }

        inflateOldProgressBar()

        val oldProgressBar = oldProgressBar ?: return

        oldProgressBar.progress = content.oldProgress.progress
        oldProgressBar.max = content.oldProgress.max
        oldProgressBar.isIndeterminate = content.oldProgress.isIndeterminate
        oldProgressBar.visibility = VISIBLE
    }

    private fun updateNewProgressBar(content: PromotedNotificationContentModel) {
        notificationProgressStartIcon?.visibility = GONE
        notificationProgressEndIcon?.visibility = GONE
        content.progress?.let {
            newProgress?.setProgressModel(it.toBundle())
            newProgress?.visibility = VISIBLE
        } ?: run { newProgress?.visibility = GONE }

        val newProgressBar = newProgressBar ?: return

        if (content.newProgress != null && !content.newProgress.isIndeterminate) {
            newProgressBar.setProgressModel(content.newProgress.toSkeleton().toBundle())
            newProgressBar.visibility = VISIBLE
        } else {
            newProgressBar.visibility = GONE
        }
    }

    private fun updateHeader(content: PromotedNotificationContentModel) {
@@ -335,6 +367,15 @@ private class AODPromotedNotificationViewUpdater(root: View) {
        chronometerStub = null
    }

    private fun inflateOldProgressBar() {
        if (oldProgressBar != null) {
            return
        }

        oldProgressBar = oldProgressBarStub?.inflate() as ProgressBar
        oldProgressBarStub = null
    }

    private fun updateText(
        view: ImageFloatingTextView?,
        content: PromotedNotificationContentModel,
@@ -368,6 +409,34 @@ private fun CharSequence.toSkeleton(): CharSequence {
    return this.toString()
}

private fun NotificationProgressModel.toSkeleton(): NotificationProgressModel {
    if (isIndeterminate) {
        return NotificationProgressModel(/* indeterminateColor= */ SecondaryText.colorInt)
    }

    return NotificationProgressModel(
        listOf(Notification.ProgressStyle.Segment(progressMax).toSkeleton()),
        points.map { it.toSkeleton() }.toList(),
        progress,
        /* isStyledByProgress = */ true,
        /* segmentsFallbackColor = */ SecondaryText.colorInt,
    )
}

private fun Notification.ProgressStyle.Segment.toSkeleton(): Notification.ProgressStyle.Segment {
    return Notification.ProgressStyle.Segment(length).also {
        it.id = id
        it.color = SecondaryText.colorInt
    }
}

private fun Notification.ProgressStyle.Point.toSkeleton(): Notification.ProgressStyle.Point {
    return Notification.ProgressStyle.Point(position).also {
        it.id = id
        it.color = SecondaryText.colorInt
    }
}

private enum class AodPromotedNotificationColor(colorUInt: UInt) {
    Background(0x00000000u),
    PrimaryText(0xFFFFFFFFu),
+21 −1
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@ import android.app.Notification.BigPictureStyle
import android.app.Notification.BigTextStyle
import android.app.Notification.CallStyle
import android.app.Notification.EXTRA_CHRONOMETER_COUNT_DOWN
import android.app.Notification.EXTRA_PROGRESS
import android.app.Notification.EXTRA_PROGRESS_INDETERMINATE
import android.app.Notification.EXTRA_PROGRESS_MAX
import android.app.Notification.EXTRA_SUB_TEXT
import android.app.Notification.EXTRA_TEXT
import android.app.Notification.EXTRA_TITLE
@@ -34,6 +37,7 @@ import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCo
import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_WAS_AUTOMATICALLY_PROMOTED
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Companion.isPromotedForStatusBarChip
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.OldProgress
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.When
import javax.inject.Inject
@@ -90,6 +94,7 @@ constructor(
        contentBuilder.title = notification.title()
        contentBuilder.text = notification.text()
        contentBuilder.skeletonLargeIcon = null // TODO
        contentBuilder.oldProgress = notification.oldProgress()

        val colorsFromNotif = recoveredBuilder.getColors(/* header= */ false)
        contentBuilder.colors =
@@ -126,6 +131,21 @@ private fun Notification.shortCriticalText(): String? {
private fun Notification.chronometerCountDown(): Boolean =
    extras?.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN, /* defaultValue= */ false) ?: false

private fun Notification.oldProgress(): OldProgress? {
    val progress = progress() ?: return null
    val max = progressMax() ?: return null
    val isIndeterminate = progressIndeterminate() ?: return null

    return OldProgress(progress = progress, max = max, isIndeterminate = isIndeterminate)
}

private fun Notification.progress(): Int? = extras?.getInt(EXTRA_PROGRESS)

private fun Notification.progressMax(): Int? = extras?.getInt(EXTRA_PROGRESS_MAX)

private fun Notification.progressIndeterminate(): Boolean? =
    extras?.getBoolean(EXTRA_PROGRESS_INDETERMINATE)

private fun Notification.extractWhen(): When? {
    val time = `when`
    val showsTime = showsTime()
@@ -191,5 +211,5 @@ private fun CallStyle.extractContent(contentBuilder: PromotedNotificationContent

private fun ProgressStyle.extractContent(contentBuilder: PromotedNotificationContentModel.Builder) {
    // TODO: Create NotificationProgressModel.toSkeleton, or something similar.
    contentBuilder.progress = createProgressModel(0xffffffff.toInt(), 0xff000000.toInt())
    contentBuilder.newProgress = createProgressModel(0xffffffff.toInt(), 0xff000000.toInt())
}
+9 −3
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ data class PromotedNotificationContentModel(
    val title: CharSequence?,
    val text: CharSequence?,
    val skeletonLargeIcon: Icon?, // TODO(b/377568176): Make into an IconModel.
    val oldProgress: OldProgress?,
    val colors: Colors,
    val style: Style,

@@ -61,7 +62,7 @@ data class PromotedNotificationContentModel(
    val verificationText: CharSequence?,

    // for ProgressStyle:
    val progress: NotificationProgressModel?,
    val newProgress: NotificationProgressModel?,
) {
    class Builder(val key: String) {
        var wasPromotedAutomatically: Boolean = false
@@ -75,6 +76,7 @@ data class PromotedNotificationContentModel(
        var title: CharSequence? = null
        var text: CharSequence? = null
        var skeletonLargeIcon: Icon? = null
        var oldProgress: OldProgress? = null
        var style: Style = Style.Ineligible
        var colors: Colors = Colors(backgroundColor = 0, primaryTextColor = 0)

@@ -85,7 +87,7 @@ data class PromotedNotificationContentModel(
        var verificationText: CharSequence? = null

        // for ProgressStyle:
        var progress: NotificationProgressModel? = null
        var newProgress: NotificationProgressModel? = null

        fun build() =
            PromotedNotificationContentModel(
@@ -101,13 +103,14 @@ data class PromotedNotificationContentModel(
                title = title,
                text = text,
                skeletonLargeIcon = skeletonLargeIcon,
                oldProgress = oldProgress,
                colors = colors,
                style = style,
                personIcon = personIcon,
                personName = personName,
                verificationIcon = verificationIcon,
                verificationText = verificationText,
                progress = progress,
                newProgress = newProgress,
            )
    }

@@ -129,6 +132,9 @@ data class PromotedNotificationContentModel(
    /** The colors used to display the notification. */
    data class Colors(@ColorInt val backgroundColor: Int, @ColorInt val primaryTextColor: Int)

    /** The fields needed to render the old-style progress bar. */
    data class OldProgress(val progress: Int, val max: Int, val isIndeterminate: Boolean)

    /** The promotion-eligible style of a notification, or [Style.Ineligible] if not. */
    enum class Style {
        Base, // style == null
+1 −1
Original line number Diff line number Diff line
@@ -54,5 +54,5 @@ class PromotedNotificationViewModel(
    val verificationText: Flow<CharSequence?> = content.map { it.verificationText }

    // for ProgressStyle:
    val progress: Flow<NotificationProgressModel?> = content.map { it.progress }
    val progress: Flow<NotificationProgressModel?> = content.map { it.newProgress }
}