summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff DeCew <jeffdq@google.com> 2025-03-04 09:11:28 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-03-04 09:11:28 -0800
commitc86d8f05ee722b28f311b7c604d6f2cdd0b12e49 (patch)
treeedd1c2466317a3f99b6b2ac44cddb89d5875d160
parent08328b6c5984a39c4e6987f70a3d7098cf56e174 (diff)
parenta0e53b545266e293f6e2c135fa9133aad72cda2b (diff)
Merge "[RONs] Do not use cached images when reinflating a notification." into main
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt51
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt3
7 files changed, 83 insertions, 38 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
index 216fd2d54a1e..3116143504eb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
@@ -57,7 +57,8 @@ class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {
private val underTest = kosmos.promotedNotificationContentExtractor
private val systemClock = kosmos.fakeSystemClock
- private val rowImageInflater = RowImageInflater.newInstance(previousIndex = null)
+ private val rowImageInflater =
+ RowImageInflater.newInstance(previousIndex = null, reinflating = false)
private val imageModelProvider by lazy { rowImageInflater.useForContentModel() }
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
index ce3aee1d88d2..31413b06e5fd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
@@ -41,7 +41,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTIO
import com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor
-import com.android.systemui.statusbar.notification.collection.EntryAdapter
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.promoted.FakePromotedNotificationContentExtractor
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUi
@@ -204,7 +203,7 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() {
val result =
NotificationRowContentBinderImpl.InflationProgress(
packageContext = mContext,
- rowImageInflater = RowImageInflater.newInstance(null),
+ rowImageInflater = RowImageInflater.newInstance(null, reinflating = false),
remoteViews = NewRemoteViews(),
contentModel = NotificationContentModel(headsUpStatusBarModel),
promotedContent = null,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index daa598b5f297..51569c1596ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -57,7 +57,6 @@ import com.android.systemui.statusbar.notification.ConversationNotificationProce
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NmSummarizationUiFlag;
import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.notification.collection.EntryAdapter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractor;
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiForceExpanded;
@@ -441,8 +440,12 @@ public class NotificationContentInflater implements NotificationRowContentBinder
NotificationRowContentBinderLogger logger) {
return TraceUtils.trace("NotificationContentInflater.createRemoteViews", () -> {
InflationProgress result = new InflationProgress();
+
+ // inflating the contracted view is the legacy invalidation trigger
+ boolean reinflating = (reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0;
// create an image inflater
- result.mRowImageInflater = RowImageInflater.newInstance(row.mImageModelIndex);
+ result.mRowImageInflater = RowImageInflater.newInstance(row.mImageModelIndex,
+ reinflating);
if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
logger.logAsyncTaskProgress(row.getLoggingKey(), "creating contracted remote view");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
index 3586078c9e82..482b315aa14d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
@@ -499,7 +499,10 @@ constructor(
logger.logAsyncTaskProgress(entry.logKey, "loading RON images")
inflationProgress.rowImageInflater.loadImagesSynchronously(packageContext)
- logger.logAsyncTaskProgress(entry.logKey, "getting row image resolver (on wrong thread!)")
+ logger.logAsyncTaskProgress(
+ entry.logKey,
+ "getting row image resolver (on wrong thread!)",
+ )
val imageResolver = row.imageResolver
// wait for image resolver to finish preloading
logger.logAsyncTaskProgress(entry.logKey, "waiting for preloaded images")
@@ -685,13 +688,17 @@ constructor(
logger: NotificationRowContentBinderLogger,
): InflationProgress {
val rowImageInflater =
- RowImageInflater.newInstance(previousIndex = row.mImageModelIndex)
+ RowImageInflater.newInstance(
+ previousIndex = row.mImageModelIndex,
+ // inflating the contracted view is the legacy invalidation trigger
+ reinflating = reInflateFlags and FLAG_CONTENT_VIEW_CONTRACTED != 0,
+ )
val promotedContent =
if (PromotedNotificationContentModel.featureFlagEnabled()) {
logger.logAsyncTaskProgress(
entry.logKey,
- "extracting promoted notification content"
+ "extracting promoted notification content",
)
val imageModelProvider = rowImageInflater.useForContentModel()
promotedNotificationContentExtractor
@@ -750,7 +757,7 @@ constructor(
) {
logger.logAsyncTaskProgress(
entry.logKey,
- "inflating public single line view model"
+ "inflating public single line view model",
)
if (bindParams.redactionType == REDACTION_TYPE_SENSITIVE_CONTENT) {
SingleLineViewInflater.inflateSingleLineViewModel(
@@ -852,18 +859,12 @@ constructor(
} else null
val expanded =
if (reInflateFlags and FLAG_CONTENT_VIEW_EXPANDED != 0) {
- logger.logAsyncTaskProgress(
- row.loggingKey,
- "creating expanded remote view",
- )
+ logger.logAsyncTaskProgress(row.loggingKey, "creating expanded remote view")
createExpandedView(builder, bindParams.isMinimized)
} else null
val headsUp =
if (reInflateFlags and FLAG_CONTENT_VIEW_HEADS_UP != 0) {
- logger.logAsyncTaskProgress(
- row.loggingKey,
- "creating heads up remote view",
- )
+ logger.logAsyncTaskProgress(row.loggingKey, "creating heads up remote view")
val isHeadsUpCompact = headsUpStyleProvider.shouldApplyCompactStyle()
if (isHeadsUpCompact) {
builder.createCompactHeadsUpContentView()
@@ -873,10 +874,7 @@ constructor(
} else null
val public =
if (reInflateFlags and FLAG_CONTENT_VIEW_PUBLIC != 0) {
- logger.logAsyncTaskProgress(
- row.loggingKey,
- "creating public remote view"
- )
+ logger.logAsyncTaskProgress(row.loggingKey, "creating public remote view")
if (
LockscreenOtpRedaction.isEnabled &&
bindParams.redactionType == REDACTION_TYPE_SENSITIVE_CONTENT
@@ -1142,7 +1140,7 @@ constructor(
override fun setResultView(v: View) {
logger.logAsyncTaskProgress(
entry.logKey,
- "group header view applied"
+ "group header view applied",
)
result.inflatedGroupHeaderView = v as NotificationHeaderView?
}
@@ -1198,7 +1196,7 @@ constructor(
}
logger.logAsyncTaskProgress(
entry.logKey,
- "applying low priority group header view"
+ "applying low priority group header view",
)
applyRemoteView(
inflationExecutor = inflationExecutor,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt
index 95ef60fdcefe..7bac17f4c227 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowImageInflater.kt
@@ -83,9 +83,9 @@ interface RowImageInflater {
inline fun featureFlagEnabled() = PromotedNotificationUiAod.isEnabled
@JvmStatic
- fun newInstance(previousIndex: ImageModelIndex?): RowImageInflater =
+ fun newInstance(previousIndex: ImageModelIndex?, reinflating: Boolean): RowImageInflater =
if (featureFlagEnabled()) {
- RowImageInflaterImpl(previousIndex)
+ RowImageInflaterImpl(previousIndex, reinflating)
} else {
RowImageInflaterStub
}
@@ -110,7 +110,8 @@ private object RowImageInflaterStub : RowImageInflater {
override fun getNewImageIndex(): ImageModelIndex? = null
}
-class RowImageInflaterImpl(private val previousIndex: ImageModelIndex?) : RowImageInflater {
+class RowImageInflaterImpl(private val previousIndex: ImageModelIndex?, val reinflating: Boolean) :
+ RowImageInflater {
private val providedImages = mutableListOf<LazyImage>()
/**
@@ -139,10 +140,15 @@ class RowImageInflaterImpl(private val previousIndex: ImageModelIndex?) : RowIma
// ensure all entries are stored
providedImages.add(newImage)
// load the image result from the index into our new object
- previousIndex?.findImage(iconData, sizeClass, transform)?.let {
- // copy the result into our new object
- newImage.result = it
- }
+ previousIndex
+ // skip the cached image when we are "reinflating" to avoid stale content
+ // being displayed from the same URI after the app updated the notif
+ ?.takeUnless { reinflating }
+ ?.findImage(iconData, sizeClass, transform)
+ ?.let {
+ // copy the result into our new object
+ newImage.result = it
+ }
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt
index 86689cb88569..d0357603665d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowImageInflaterTest.kt
@@ -21,6 +21,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiAod
+import com.android.systemui.statusbar.notification.row.shared.IconData
import com.android.systemui.statusbar.notification.row.shared.ImageModel
import com.android.systemui.statusbar.notification.row.shared.ImageModelProvider.ImageSizeClass.SmallSquare
import com.google.common.truth.Truth.assertThat
@@ -38,20 +39,22 @@ class RowImageInflaterTest : SysuiTestCase() {
private val resIcon2 = Icon.createWithResource(context, android.R.drawable.ic_delete)
private val badUriIcon = Icon.createWithContentUri("content://com.test/does_not_exist")
+ private var latestImageModelIndex: ImageModelIndex? = null
+
@Before
fun setUp() {
- rowImageInflater = RowImageInflater.newInstance(null)
+ rowImageInflater = RowImageInflater.newInstance(null, reinflating = false)
}
@Test
fun getNewImageIndex_returnsNullWhenUnused() {
- assertThat(rowImageInflater.getNewImageIndex()).isNull()
+ assertThat(getNewImageIndex()).isNull()
}
@Test
fun getNewImageIndex_returnsEmptyIndexWhenZeroImagesLoaded() {
assertThat(getImageModelsForIcons()).isEmpty()
- val result = rowImageInflater.getNewImageIndex()
+ val result = getNewImageIndex()
assertThat(result).isNotNull()
assertThat(result?.contentsForTesting).isEmpty()
}
@@ -59,7 +62,7 @@ class RowImageInflaterTest : SysuiTestCase() {
@Test
fun getNewImageIndex_returnsSingleImageWhenOneImageLoaded() {
assertThat(getImageModelsForIcons(resIcon1)).hasSize(1)
- val result = rowImageInflater.getNewImageIndex()
+ val result = getNewImageIndex()
assertThat(result).isNotNull()
assertThat(result?.contentsForTesting).hasSize(1)
}
@@ -85,7 +88,7 @@ class RowImageInflaterTest : SysuiTestCase() {
assertThat(providedModels[3].drawable).isNotNull()
// VERIFY the returned index has all 3 entries, 2 of which have drawables
- val indexGen1 = rowImageInflater.getNewImageIndex()
+ val indexGen1 = getNewImageIndex()
assertThat(indexGen1).isNotNull()
assertThat(indexGen1?.contentsForTesting).hasSize(3)
assertThat(indexGen1?.contentsForTesting?.mapNotNull { it.drawable }).hasSize(2)
@@ -96,7 +99,7 @@ class RowImageInflaterTest : SysuiTestCase() {
exampleFirstGeneration()
// THEN start a new generation of the inflation
- rowImageInflater = RowImageInflater.newInstance(rowImageInflater.getNewImageIndex())
+ rowImageInflater = RowImageInflater.newInstance(getNewImageIndex(), reinflating = false)
getNewImageIndex_returnsEmptyIndexWhenZeroImagesLoaded()
}
@@ -104,13 +107,47 @@ class RowImageInflaterTest : SysuiTestCase() {
@Test
fun exampleSecondGeneration_whichLoadsOneImage() {
exampleFirstGeneration()
+ val gen1Index = latestImageModelIndex!!
// THEN start a new generation of the inflation
- rowImageInflater = RowImageInflater.newInstance(rowImageInflater.getNewImageIndex())
+ rowImageInflater = RowImageInflater.newInstance(gen1Index, reinflating = false)
getNewImageIndex_returnsSingleImageWhenOneImageLoaded()
+ val gen2Index = latestImageModelIndex!!
+
+ // VERIFY that the drawable was copied from the previous index
+ val gen1model = gen1Index.findModel(resIcon1)
+ val gen2model = gen2Index.findModel(resIcon1)
+ assertThat(gen2model).isNotSameInstanceAs(gen1model)
+ assertThat(gen2model.drawable).isSameInstanceAs(gen1model.drawable)
}
+ @Test
+ fun exampleSecondGeneration_reinflating_whichLoadsOneImage() {
+ exampleFirstGeneration()
+ val gen1Index = latestImageModelIndex!!
+
+ // THEN start a new generation of the inflation
+ rowImageInflater = RowImageInflater.newInstance(gen1Index, reinflating = true)
+
+ getNewImageIndex_returnsSingleImageWhenOneImageLoaded()
+ val gen2Index = latestImageModelIndex!!
+
+ // VERIFY that the drawable was reloaded rather than copied from the previous index
+ val gen1model = gen1Index.findModel(resIcon1)
+ val gen2model = gen2Index.findModel(resIcon1)
+ assertThat(gen2model).isNotSameInstanceAs(gen1model)
+ assertThat(gen2model.drawable).isNotSameInstanceAs(gen1model.drawable)
+ }
+
+ private fun ImageModelIndex.findModel(icon: Icon): LazyImage =
+ IconData.fromIcon(icon)
+ .let { iconData -> contentsForTesting.find { it.icon == iconData } }
+ .also { assertThat(it).isNotNull() }!!
+
+ private fun getNewImageIndex(): ImageModelIndex? =
+ rowImageInflater.getNewImageIndex().also { latestImageModelIndex = it }
+
private fun getImageModelsForIcons(vararg icons: Icon): List<ImageModel> {
val provider = rowImageInflater.useForContentModel()
return icons.map { icon ->
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
index da879d9e314d..2b3158da38f9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
@@ -39,7 +39,8 @@ fun Kosmos.setPromotedContent(entry: NotificationEntry) {
promotedNotificationContentExtractor.extractContent(
entry,
Notification.Builder.recoverBuilder(applicationContext, entry.sbn.notification),
- RowImageInflater.newInstance(null).useForContentModel(),
+ RowImageInflater.newInstance(previousIndex = null, reinflating = false)
+ .useForContentModel(),
)
entry.promotedNotificationContentModel =
requireNotNull(extractedContent) { "extractContent returned null" }