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

Commit de71cb1c authored by Julia Tuttle's avatar Julia Tuttle Committed by Android (Google) Code Review
Browse files

Merge "Continue fleshing out progress bars on AOD RONs" into main

parents 9fbb1d1c 359caa79
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 }
}