From 052e4b00a0dc432558dcb947666c1925154a18c6 Mon Sep 17 00:00:00 2001 From: Ioana Alexandru Date: Tue, 16 Apr 2024 22:11:12 +0200 Subject: Prototype replacing small icons with app icons. This would replace the small icon in the notification shelf, AOD and status bar, as well as the notification itself. As this is just a simple prototype, it's not particularly optimal since we just want to see what this will look like before investing time in a proper solution. Bug: 335211019 Test: manual; no automated tests yet as this is just a prototype Flag: ACONFIG android.app.notifications_use_app_icon DEVELOPMENT Change-Id: I0ae3070339efa4558cf97fad3a20b9fe69641cd8 --- core/java/android/app/Notification.java | 35 ++++++++++++++++++++-- core/java/android/app/notification.aconfig | 11 +++++++ .../statusbar/notification/icon/IconManager.kt | 10 +++---- .../icon/ui/viewbinder/StatusBarIconViewBinder.kt | 25 ++++++++++------ 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index fe261bee41d8..97136f38d5c9 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3077,6 +3077,25 @@ public class Notification implements Parcelable } } + /** + * @hide + */ + public int loadHeaderAppIconRes(Context context) { + ApplicationInfo info = null; + if (extras.containsKey(EXTRA_BUILDER_APPLICATION_INFO)) { + info = extras.getParcelable( + EXTRA_BUILDER_APPLICATION_INFO, + ApplicationInfo.class); + } + if (info == null) { + info = context.getApplicationInfo(); + } + if (info != null) { + return info.icon; + } + return 0; + } + /** * Removes heavyweight parts of the Notification object for archival or for sending to * listeners when the full contents are not necessary. @@ -5891,12 +5910,21 @@ public class Notification implements Parcelable } private void bindSmallIcon(RemoteViews contentView, StandardTemplateParams p) { - if (mN.mSmallIcon == null && mN.icon != 0) { + if (Flags.notificationsUseAppIcon()) { + // Override small icon with app icon + mN.mSmallIcon = Icon.createWithResource(mContext, + mN.loadHeaderAppIconRes(mContext)); + } else if (mN.mSmallIcon == null && mN.icon != 0) { mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon); } + contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon); contentView.setInt(R.id.icon, "setImageLevel", mN.iconLevel); - processSmallIconColor(mN.mSmallIcon, contentView, p); + + // Don't change color if we're using the app icon. + if (!Flags.notificationsUseAppIcon()) { + processSmallIconColor(mN.mSmallIcon, contentView, p); + } } /** @@ -6696,7 +6724,8 @@ public class Notification implements Parcelable */ private void processSmallIconColor(Icon smallIcon, RemoteViews contentView, StandardTemplateParams p) { - boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon); + boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, + smallIcon); int color = getSmallIconColor(p); contentView.setInt(R.id.icon, "setBackgroundColor", getBackgroundColor(p)); diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig index 00827321e18f..074e204c884a 100644 --- a/core/java/android/app/notification.aconfig +++ b/core/java/android/app/notification.aconfig @@ -1,6 +1,10 @@ package: "android.app" container: "system" +# Note: When adding a new flag here, consider including the word "notification(s)" in the flag name +# when appropriate, as it's not currently part of the namespace so it may not be obvious what the +# flag relates to. + flag { name: "modes_api" is_exported: true @@ -41,6 +45,13 @@ flag { bug: "281044385" } +flag { + name: "notifications_use_app_icon" + namespace: "systemui" + description: "Experiment to replace the small icon in a notification with the app icon." + bug: "335211019" +} + flag { name: "keyguard_private_notifications" namespace: "systemui" 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 4ebb6998b8c7..271b0a86ca12 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 @@ -39,13 +39,13 @@ 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 -import java.util.concurrent.ConcurrentHashMap -import javax.inject.Inject -import kotlin.coroutines.CoroutineContext /** * Inflates and updates icons associated with notifications @@ -239,8 +239,8 @@ constructor( val sbi = icon.toStatusBarIcon(entry) - // Cache if important conversation. - if (isImportantConversation(entry)) { + // Cache if important conversation or app icon. + if (isImportantConversation(entry) || android.app.Flags.notificationsUseAppIcon()) { if (showPeopleAvatar) { entry.icons.peopleAvatarDescriptor = sbi } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt index bfeaced72162..2fdd2c6434cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt @@ -20,6 +20,7 @@ import android.graphics.Rect import android.view.View import com.android.app.tracing.traceSection import com.android.internal.util.ContrastColorUtil +import com.android.systemui.Flags import com.android.systemui.res.R import com.android.systemui.statusbar.StatusBarIconView import com.android.systemui.statusbar.StatusBarIconView.NO_COLOR @@ -34,9 +35,12 @@ object StatusBarIconViewBinder { // view-model (which, at the time of this writing, does not yet exist). suspend fun bindColor(view: StatusBarIconView, color: Flow) { - color.collectTracingEach("SBIV#bindColor") { color -> - view.staticDrawableColor = color - view.setDecorColor(color) + // Don't change the icon color if an app icon experiment is enabled. + if (!android.app.Flags.notificationsUseAppIcon()) { + color.collectTracingEach("SBIV#bindColor") { color -> + view.staticDrawableColor = color + view.setDecorColor(color) + } } } @@ -53,12 +57,15 @@ object StatusBarIconViewBinder { iconColors: Flow, contrastColorUtil: ContrastColorUtil, ) { - iconColors.collectTracingEach("SBIV#bindIconColors") { colors -> - val isPreL = java.lang.Boolean.TRUE == view.getTag(R.id.icon_is_pre_L) - val isColorized = !isPreL || NotificationUtils.isGrayscale(view, contrastColorUtil) - view.staticDrawableColor = - if (isColorized) colors.staticDrawableColor(view.viewBounds) else NO_COLOR - view.setDecorColor(colors.tint) + // Don't change the icon color if an app icon experiment is enabled. + if (!android.app.Flags.notificationsUseAppIcon()) { + iconColors.collectTracingEach("SBIV#bindIconColors") { colors -> + val isPreL = java.lang.Boolean.TRUE == view.getTag(R.id.icon_is_pre_L) + val isColorized = !isPreL || NotificationUtils.isGrayscale(view, contrastColorUtil) + view.staticDrawableColor = + if (isColorized) colors.staticDrawableColor(view.viewBounds) else NO_COLOR + view.setDecorColor(colors.tint) + } } } } -- cgit v1.2.3-59-g8ed1b