Get person avatar icon on a bg thread
We're making a binder call to launcher, and it shouldn't block the main
thread.
Tracking this change and the other changes in the child bugs of b/315143361
under the same generic flag.
Fix: 320274812
Bug: 315143361
Test: posted a few high prio conversation notifs and checked that they
look good on aod, the shelf and status bar
Flag: ACONFIG com.android.systemui.notifications_background_icons DEVELOPMENT
Change-Id: Ie03cf3698c2d46c75012792a5628a5b1068b244b
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 8c8975f..56e8c677 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -105,10 +105,10 @@
}
flag {
- name: "notifications_background_media_icons"
+ name: "notifications_background_icons"
namespace: "systemui"
- description: "Updates icons for media notifications in the background."
- bug: "315143160"
+ description: "Moves part of the notification icon updates to the background."
+ bug: "315143361"
metadata {
purpose: PURPOSE_BUGFIX
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index a4011fd..1003050 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -69,6 +69,7 @@
import com.android.systemui.toast.ToastModule;
import com.android.systemui.unfold.SysUIUnfoldStartableModule;
import com.android.systemui.unfold.UnfoldTransitionModule;
+import com.android.systemui.util.kotlin.SysUICoroutinesModule;
import com.android.systemui.volume.dagger.VolumeModule;
import com.android.systemui.wallpapers.dagger.WallpaperModule;
@@ -117,6 +118,7 @@
ShadeModule.class,
StartCentralSurfacesModule.class,
SceneContainerFrameworkModule.class,
+ SysUICoroutinesModule.class,
SysUIUnfoldStartableModule.class,
UnfoldTransitionModule.Startables.class,
ToastModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinator.java
index 072f56d..dcfccd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinator.java
@@ -61,7 +61,7 @@
return false;
}
- if (!Flags.notificationsBackgroundMediaIcons()) {
+ if (!Flags.notificationsBackgroundIcons()) {
inflateOrUpdateIcons(entry);
}
@@ -73,14 +73,14 @@
@Override
public void onEntryInit(@NonNull NotificationEntry entry) {
// We default to STATE_ICONS_UNINFLATED anyway, so there's no need to initialize it.
- if (!Flags.notificationsBackgroundMediaIcons()) {
+ if (!Flags.notificationsBackgroundIcons()) {
mIconsState.put(entry, STATE_ICONS_UNINFLATED);
}
}
@Override
public void onEntryAdded(@NonNull NotificationEntry entry) {
- if (Flags.notificationsBackgroundMediaIcons()) {
+ if (Flags.notificationsBackgroundIcons()) {
if (isMediaNotification(entry.getSbn())) {
inflateOrUpdateIcons(entry);
}
@@ -94,7 +94,7 @@
mIconsState.put(entry, STATE_ICONS_UNINFLATED);
}
- if (Flags.notificationsBackgroundMediaIcons()) {
+ if (Flags.notificationsBackgroundIcons()) {
if (isMediaNotification(entry.getSbn())) {
inflateOrUpdateIcons(entry);
}
@@ -120,7 +120,7 @@
break;
case STATE_ICONS_INFLATED:
try {
- mIconManager.updateIcons(entry);
+ mIconManager.updateIcons(entry, /* usingCache = */ false);
} catch (InflationException e) {
reportInflationError(entry, e);
mIconsState.put(entry, STATE_ICONS_ERROR);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index c5b55c7..332b49c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -138,7 +138,7 @@
if (entry.rowExists()) {
mLogger.logUpdatingRow(entry, params);
- mIconManager.updateIcons(entry);
+ mIconManager.updateIcons(entry, /* usingCache = */ false);
ExpandableNotificationRow row = entry.getRow();
row.reset();
updateRow(entry, row);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
index a5f42bb..a900e45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
@@ -28,14 +28,24 @@
import android.widget.ImageView
import com.android.app.tracing.traceSection
import com.android.internal.statusbar.StatusBarIcon
+import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.notification.InflationException
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
/**
* Inflates and updates icons associated with notifications
@@ -53,9 +63,18 @@
constructor(
private val notifCollection: CommonNotifCollection,
private val launcherApps: LauncherApps,
- private val iconBuilder: IconBuilder
+ private val iconBuilder: IconBuilder,
+ @Application private val applicationCoroutineScope: CoroutineScope,
+ @Background private val bgCoroutineContext: CoroutineContext,
+ @Main private val mainCoroutineContext: CoroutineContext,
) : ConversationIconManager {
private var unimportantConversationKeys: Set<String> = emptySet()
+ /**
+ * A map of running jobs for fetching the person avatar from launcher. The key is the
+ * notification entry key.
+ */
+ private var launcherPeopleAvatarIconJobs: ConcurrentHashMap<String, Job> =
+ ConcurrentHashMap<String, Job>()
fun attach() {
notifCollection.addCollectionListener(entryListener)
@@ -136,13 +155,23 @@
* @throws InflationException Exception if required icons are not valid or specified
*/
@Throws(InflationException::class)
- fun updateIcons(entry: NotificationEntry) =
+ fun updateIcons(entry: NotificationEntry, usingCache: Boolean = false) =
traceSection("IconManager.updateIcons") {
if (!entry.icons.areIconsAvailable) {
return@traceSection
}
- entry.icons.smallIconDescriptor = null
- entry.icons.peopleAvatarDescriptor = null
+
+ if (usingCache && !Flags.notificationsBackgroundIcons()) {
+ Log.wtf(
+ TAG,
+ "Updating using the cache is not supported when the " +
+ "notifications_background_conversation_icons flag is off"
+ )
+ }
+ if (!usingCache || !Flags.notificationsBackgroundIcons()) {
+ entry.icons.smallIconDescriptor = null
+ entry.icons.peopleAvatarDescriptor = null
+ }
val (normalIconDescriptor, sensitiveIconDescriptor) = getIconDescriptors(entry)
val notificationContentDescription =
@@ -188,7 +217,7 @@
@Throws(InflationException::class)
private fun getIconDescriptor(entry: NotificationEntry, redact: Boolean): StatusBarIcon {
val n = entry.sbn.notification
- val showPeopleAvatar = isImportantConversation(entry) && !redact
+ val showPeopleAvatar = !redact && isImportantConversation(entry)
val peopleAvatarDescriptor = entry.icons.peopleAvatarDescriptor
val smallIconDescriptor = entry.icons.smallIconDescriptor
@@ -208,26 +237,18 @@
})
?: throw InflationException("No icon in notification from " + entry.sbn.packageName)
- val ic =
- StatusBarIcon(
- entry.sbn.user,
- entry.sbn.packageName,
- icon,
- n.iconLevel,
- n.number,
- iconBuilder.getIconContentDescription(n)
- )
+ val sbi = icon.toStatusBarIcon(entry)
// Cache if important conversation.
if (isImportantConversation(entry)) {
if (showPeopleAvatar) {
- entry.icons.peopleAvatarDescriptor = ic
+ entry.icons.peopleAvatarDescriptor = sbi
} else {
- entry.icons.smallIconDescriptor = ic
+ entry.icons.smallIconDescriptor = sbi
}
}
- return ic
+ return sbi
}
@Throws(InflationException::class)
@@ -243,16 +264,69 @@
}
}
- @Throws(InflationException::class)
- private fun createPeopleAvatar(entry: NotificationEntry): Icon? {
- var ic: Icon? = null
+ private fun Icon.toStatusBarIcon(entry: NotificationEntry): StatusBarIcon {
+ val n = entry.sbn.notification
+ return StatusBarIcon(
+ entry.sbn.user,
+ entry.sbn.packageName,
+ /* icon = */ this,
+ n.iconLevel,
+ n.number,
+ iconBuilder.getIconContentDescription(n)
+ )
+ }
- val shortcut = entry.ranking.conversationShortcutInfo
- if (shortcut != null) {
- ic = launcherApps.getShortcutIcon(shortcut)
+ private suspend fun getLauncherShortcutIconForPeopleAvatar(entry: NotificationEntry) =
+ withContext(bgCoroutineContext) {
+ var icon: Icon? = null
+ val shortcut = entry.ranking.conversationShortcutInfo
+ if (shortcut != null) {
+ try {
+ icon = launcherApps.getShortcutIcon(shortcut)
+ } catch (e: Exception) {
+ Log.e(
+ TAG,
+ "Error calling LauncherApps#getShortcutIcon for notification $entry: $e"
+ )
+ }
+ }
+
+ // Once we have the icon, updating it should happen on the main thread.
+ if (icon != null) {
+ withContext(mainCoroutineContext) {
+ val iconDescriptor = icon.toStatusBarIcon(entry)
+
+ // Cache the value
+ entry.icons.peopleAvatarDescriptor = iconDescriptor
+
+ // Update the icons using the cached value
+ updateIcons(entry = entry, usingCache = true)
+ }
+ }
}
- // Fall back to extract from message
+ @Throws(InflationException::class)
+ private fun createPeopleAvatar(entry: NotificationEntry): Icon {
+ var ic: Icon? = null
+
+ if (Flags.notificationsBackgroundIcons()) {
+ // Ideally we want to get the icon from launcher, but this is a binder transaction that
+ // may take longer so let's kick it off on a background thread and use a placeholder in
+ // the meantime.
+ // Cancel the previous job if necessary.
+ launcherPeopleAvatarIconJobs[entry.key]?.cancel()
+ launcherPeopleAvatarIconJobs[entry.key] =
+ applicationCoroutineScope
+ .launch { getLauncherShortcutIconForPeopleAvatar(entry) }
+ .apply { invokeOnCompletion { launcherPeopleAvatarIconJobs.remove(entry.key) } }
+ } else {
+ val shortcut = entry.ranking.conversationShortcutInfo
+ if (shortcut != null) {
+ ic = launcherApps.getShortcutIcon(shortcut)
+ }
+ }
+
+ // Try to extract from message
if (ic == null) {
val extras: Bundle = entry.sbn.notification.extras
val messages =
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/SysUICoroutinesModule.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/SysUICoroutinesModule.kt
index cabe831..d10554f 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/SysUICoroutinesModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/SysUICoroutinesModule.kt
@@ -32,7 +32,7 @@
private const val LIMIT_BACKGROUND_DISPATCHER_THREADS = true
-/** Providers for various SystemIU specific coroutines-related constructs. */
+/** Providers for various SystemUI-specific coroutines-related constructs. */
@Module
class SysUICoroutinesModule {
@Provides
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinatorTest.java
index b548117..e90a3ac8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/MediaCoordinatorTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
@@ -157,52 +158,52 @@
}
@Test
- @DisableFlags(Flags.FLAG_NOTIFICATIONS_BACKGROUND_MEDIA_ICONS)
+ @DisableFlags(Flags.FLAG_NOTIFICATIONS_BACKGROUND_ICONS)
public void inflateMediaNotificationIconsMediaEnabled_old() throws InflationException {
finishSetupWithMediaFeatureFlagEnabled(true);
mListener.onEntryInit(mMediaEntry);
mListener.onEntryAdded(mMediaEntry);
verify(mIconManager, never()).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
mFilter.shouldFilterOut(mMediaEntry, 0);
verify(mIconManager, times(1)).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
mFilter.shouldFilterOut(mMediaEntry, 0);
verify(mIconManager, times(1)).createIcons(eq(mMediaEntry));
- verify(mIconManager, times(1)).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, times(1)).updateIcons(eq(mMediaEntry), /* usingCache = */ eq(false));
mListener.onEntryRemoved(mMediaEntry, NotificationListenerService.REASON_CANCEL);
mListener.onEntryCleanUp(mMediaEntry);
mListener.onEntryInit(mMediaEntry);
verify(mIconManager, times(1)).createIcons(eq(mMediaEntry));
- verify(mIconManager, times(1)).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, times(1)).updateIcons(eq(mMediaEntry), /* usingCache = */ eq(false));
mFilter.shouldFilterOut(mMediaEntry, 0);
verify(mIconManager, times(2)).createIcons(eq(mMediaEntry));
- verify(mIconManager, times(1)).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, times(1)).updateIcons(eq(mMediaEntry), /* usingCache = */ eq(false));
}
@Test
- @EnableFlags(Flags.FLAG_NOTIFICATIONS_BACKGROUND_MEDIA_ICONS)
+ @EnableFlags(Flags.FLAG_NOTIFICATIONS_BACKGROUND_ICONS)
public void inflateMediaNotificationIconsMediaEnabled_new() throws InflationException {
finishSetupWithMediaFeatureFlagEnabled(true);
mListener.onEntryInit(mMediaEntry);
mListener.onEntryAdded(mMediaEntry);
verify(mIconManager).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
clearInvocations(mIconManager);
mFilter.shouldFilterOut(mMediaEntry, 0);
verify(mIconManager, never()).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
mListener.onEntryUpdated(mMediaEntry);
verify(mIconManager, never()).createIcons(eq(mMediaEntry));
- verify(mIconManager).updateIcons(eq(mMediaEntry));
+ verify(mIconManager).updateIcons(eq(mMediaEntry), /* usingCache = */ eq(false));
mListener.onEntryRemoved(mMediaEntry, NotificationListenerService.REASON_CANCEL);
mListener.onEntryCleanUp(mMediaEntry);
@@ -211,40 +212,40 @@
mListener.onEntryInit(mMediaEntry);
mListener.onEntryAdded(mMediaEntry);
verify(mIconManager).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
}
@Test
- @DisableFlags(Flags.FLAG_NOTIFICATIONS_BACKGROUND_MEDIA_ICONS)
+ @DisableFlags(Flags.FLAG_NOTIFICATIONS_BACKGROUND_ICONS)
public void inflationException_old() throws InflationException {
finishSetupWithMediaFeatureFlagEnabled(true);
mListener.onEntryInit(mMediaEntry);
mListener.onEntryAdded(mMediaEntry);
verify(mIconManager, never()).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
doThrow(InflationException.class).when(mIconManager).createIcons(eq(mMediaEntry));
mFilter.shouldFilterOut(mMediaEntry, 0);
verify(mIconManager, times(1)).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
mFilter.shouldFilterOut(mMediaEntry, 0);
verify(mIconManager, times(1)).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), /* usingCache = */ eq(false));
mListener.onEntryUpdated(mMediaEntry);
verify(mIconManager, times(1)).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
doNothing().when(mIconManager).createIcons(eq(mMediaEntry));
mFilter.shouldFilterOut(mMediaEntry, 0);
verify(mIconManager, times(2)).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
}
@Test
- @EnableFlags(Flags.FLAG_NOTIFICATIONS_BACKGROUND_MEDIA_ICONS)
+ @EnableFlags(Flags.FLAG_NOTIFICATIONS_BACKGROUND_ICONS)
public void inflationException_new() throws InflationException {
finishSetupWithMediaFeatureFlagEnabled(true);
@@ -253,19 +254,19 @@
mListener.onEntryInit(mMediaEntry);
mListener.onEntryAdded(mMediaEntry);
verify(mIconManager).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
clearInvocations(mIconManager);
mListener.onEntryUpdated(mMediaEntry);
verify(mIconManager).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
clearInvocations(mIconManager);
doNothing().when(mIconManager).createIcons(eq(mMediaEntry));
mListener.onEntryUpdated(mMediaEntry);
verify(mIconManager).createIcons(eq(mMediaEntry));
- verify(mIconManager, never()).updateIcons(eq(mMediaEntry));
+ verify(mIconManager, never()).updateIcons(eq(mMediaEntry), anyBoolean());
}
private void finishSetupWithMediaFeatureFlagEnabled(boolean mediaFeatureFlagEnabled) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
index a12806b..4ac9dc2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
package com.android.systemui.statusbar.notification.icon
import android.app.ActivityManager
@@ -38,6 +40,10 @@
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -69,6 +75,11 @@
@Mock private lateinit var notifCollection: CommonNotifCollection
@Mock private lateinit var launcherApps: LauncherApps
+ private val testDispatcher = StandardTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+ private val mainContext = testScope.coroutineContext
+ private val bgContext = testScope.backgroundScope.coroutineContext
+
private val iconBuilder = IconBuilder(context)
private lateinit var iconManager: IconManager
@@ -85,7 +96,15 @@
`when`(shortcut.icon).thenReturn(shortcutIc)
`when`(launcherApps.getShortcutIcon(shortcut)).thenReturn(shortcutIc)
- iconManager = IconManager(notifCollection, launcherApps, iconBuilder)
+ iconManager =
+ IconManager(
+ notifCollection,
+ launcherApps,
+ iconBuilder,
+ testScope,
+ bgContext,
+ mainContext,
+ )
}
@Test
@@ -94,6 +113,7 @@
notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = true)
entry?.channel?.isImportantConversation = true
entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(shortcutIc)
}
@@ -103,6 +123,7 @@
notificationEntry(hasShortcut = false, hasMessageSenderIcon = true, hasLargeIcon = true)
entry?.channel?.isImportantConversation = true
entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(messageIc)
}
@@ -116,6 +137,7 @@
)
entry?.channel?.isImportantConversation = true
entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(largeIc)
}
@@ -129,6 +151,7 @@
)
entry?.channel?.isImportantConversation = true
entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(smallIc)
}
@@ -143,6 +166,7 @@
)
entry?.channel?.isImportantConversation = true
entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(smallIc)
}
@@ -161,6 +185,7 @@
entry?.setSensitive(true, true)
entry?.channel?.isImportantConversation = true
entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(shortcutIc)
assertThat(entry?.icons?.shelfIcon?.sourceIcon).isEqualTo(smallIc)
assertThat(entry?.icons?.aodIcon?.sourceIcon).isEqualTo(smallIc)
@@ -175,6 +200,7 @@
entry?.let { iconManager.createIcons(it) }
// Updating the icons after creation shouldn't break anything
entry?.let { iconManager.updateIcons(it) }
+ testScope.runCurrent()
assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(shortcutIc)
assertThat(entry?.icons?.shelfIcon?.sourceIcon).isEqualTo(smallIc)
assertThat(entry?.icons?.aodIcon?.sourceIcon).isEqualTo(smallIc)
@@ -187,9 +213,11 @@
entry?.channel?.isImportantConversation = true
entry?.setSensitive(true, true)
entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
assertThat(entry?.icons?.aodIcon?.sourceIcon).isEqualTo(smallIc)
entry?.setSensitive(false, false)
entry?.let { iconManager.updateIcons(it) }
+ testScope.runCurrent()
assertThat(entry?.icons?.shelfIcon?.sourceIcon).isEqualTo(shortcutIc)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index fb49499f..2786733 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -53,6 +53,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.keyguard.TestScopeProvider;
import com.android.systemui.TestableDependency;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.flags.FakeFeatureFlags;
@@ -102,6 +103,9 @@
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+import kotlin.coroutines.CoroutineContext;
+import kotlinx.coroutines.test.TestScope;
+
/**
* A helper class to create {@link ExpandableNotificationRow} (for both individual and group
* notifications).
@@ -140,6 +144,10 @@
private final FakeFeatureFlags mFeatureFlags;
private final SystemClock mSystemClock;
private final RowInflaterTaskLogger mRowInflaterTaskLogger;
+ private final TestScope mTestScope = TestScopeProvider.getTestScope();
+ private final CoroutineContext mBgCoroutineContext =
+ mTestScope.getBackgroundScope().getCoroutineContext();
+ private final CoroutineContext mMainCoroutineContext = mTestScope.getCoroutineContext();
public NotificationTestHelper(
Context context,
@@ -169,7 +177,10 @@
mIconManager = new IconManager(
mock(CommonNotifCollection.class),
mock(LauncherApps.class),
- new IconBuilder(mContext));
+ new IconBuilder(mContext),
+ mTestScope,
+ mBgCoroutineContext,
+ mMainCoroutineContext);
NotificationContentInflater contentBinder = new NotificationContentInflater(
mock(NotifRemoteViewCache.class),
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt
index 0b13858..b34681a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt
@@ -2,6 +2,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
@@ -9,3 +10,7 @@
var Kosmos.testScope by Fixture { TestScope(testDispatcher) }
var Kosmos.applicationCoroutineScope by Fixture { testScope.backgroundScope }
var Kosmos.testCase: SysuiTestCase by Fixture()
+var Kosmos.backgroundCoroutineContext: CoroutineContext by Fixture {
+ testScope.backgroundScope.coroutineContext
+}
+var Kosmos.mainCoroutineContext: CoroutineContext by Fixture { testScope.coroutineContext }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconManagerKosmos.kt
index d3a8e0c..0950f04 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconManagerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconManagerKosmos.kt
@@ -18,7 +18,19 @@
import android.content.pm.launcherApps
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.backgroundCoroutineContext
+import com.android.systemui.kosmos.mainCoroutineContext
import com.android.systemui.statusbar.notification.collection.notifcollection.commonNotifCollection
val Kosmos.iconManager by
- Kosmos.Fixture { IconManager(commonNotifCollection, launcherApps, iconBuilder) }
+ Kosmos.Fixture {
+ IconManager(
+ commonNotifCollection,
+ launcherApps,
+ iconBuilder,
+ applicationCoroutineScope,
+ backgroundCoroutineContext,
+ mainCoroutineContext,
+ )
+ }