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

Commit 39a5685e authored by Ioana Alexandru's avatar Ioana Alexandru Committed by Android (Google) Code Review
Browse files

Merge changes I3ba415f9,I4be70d14 into main

* changes:
  [AOD RONs] Show profile badge
  [AOD RONs] Use packageContext instead of SystemUI context
parents d74b68fa 2d50a68e
Loading
Loading
Loading
Loading
+47 −41
Original line number Diff line number Diff line
@@ -3248,6 +3248,52 @@ public class Notification implements Parcelable
        }
    }
    /**
     * Get profile badge to be shown in the header (e.g. the briefcase icon for work profile).
     *
     * @param context the package context used to obtain the badge
     * @hide
     */
    public static Bitmap getProfileBadge(Context context) {
        Drawable badge = getProfileBadgeDrawable(context);
        if (badge == null) {
            return null;
        }
        final int size = context.getResources().getDimensionPixelSize(
                Flags.notificationsRedesignTemplates()
                        ? R.dimen.notification_2025_badge_size
                        : R.dimen.notification_badge_size);
        Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        badge.setBounds(0, 0, size, size);
        badge.draw(canvas);
        return bitmap;
    }
    private static Drawable getProfileBadgeDrawable(Context context) {
        if (context.getUserId() == UserHandle.USER_SYSTEM) {
            // This user can never be a badged profile,
            // and also includes USER_ALL system notifications.
            return null;
        }
        // Note: This assumes that the current user can read the profile badge of the
        // originating user.
        DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
        return dpm.getResources().getDrawable(
                getUpdatableProfileBadgeId(context), SOLID_COLORED, NOTIFICATION,
                () -> getDefaultProfileBadgeDrawable(context));
    }
    private static String getUpdatableProfileBadgeId(Context context) {
        return context.getSystemService(UserManager.class).isManagedProfile()
                ? WORK_PROFILE_ICON : UNDEFINED;
    }
    private static Drawable getDefaultProfileBadgeDrawable(Context context) {
        return context.getPackageManager().getUserBadgeForDensityNoBackground(
                new UserHandle(context.getUserId()), 0);
    }
    /**
     * @hide
     */
@@ -5954,48 +6000,8 @@ public class Notification implements Parcelable
                    PorterDuff.Mode.SRC_ATOP);
        }
        private Drawable getProfileBadgeDrawable() {
            if (mContext.getUserId() == UserHandle.USER_SYSTEM) {
                // This user can never be a badged profile,
                // and also includes USER_ALL system notifications.
                return null;
            }
            // Note: This assumes that the current user can read the profile badge of the
            // originating user.
            DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
            return dpm.getResources().getDrawable(
                    getUpdatableProfileBadgeId(), SOLID_COLORED, NOTIFICATION,
                    this::getDefaultProfileBadgeDrawable);
        }
        private String getUpdatableProfileBadgeId() {
            return mContext.getSystemService(UserManager.class).isManagedProfile()
                    ? WORK_PROFILE_ICON : UNDEFINED;
        }
        private Drawable getDefaultProfileBadgeDrawable() {
            return mContext.getPackageManager().getUserBadgeForDensityNoBackground(
                    new UserHandle(mContext.getUserId()), 0);
        }
        private Bitmap getProfileBadge() {
            Drawable badge = getProfileBadgeDrawable();
            if (badge == null) {
                return null;
            }
            final int size = mContext.getResources().getDimensionPixelSize(
                    Flags.notificationsRedesignTemplates()
                            ? R.dimen.notification_2025_badge_size
                            : R.dimen.notification_badge_size);
            Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            badge.setBounds(0, 0, size, size);
            badge.draw(canvas);
            return bitmap;
        }
        private void bindProfileBadge(RemoteViews contentView, StandardTemplateParams p) {
            Bitmap profileBadge = getProfileBadge();
            Bitmap profileBadge = Notification.getProfileBadge(mContext);
            if (profileBadge != null) {
                contentView.setImageViewBitmap(R.id.profile_badge, profileBadge);
+7 −1
Original line number Diff line number Diff line
@@ -648,7 +648,13 @@ class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {
        redactionType: Int = REDACTION_TYPE_PUBLIC,
    ): PromotedNotificationContentModels? {
        val recoveredBuilder = Notification.Builder(context, entry.sbn.notification)
        return underTest.extractContent(entry, recoveredBuilder, redactionType, imageModelProvider)
        return underTest.extractContent(
            entry,
            recoveredBuilder,
            redactionType,
            imageModelProvider,
            context,
        )
    }

    private fun Kosmos.createEntry(
+2 −1
Original line number Diff line number Diff line
@@ -324,7 +324,8 @@ public interface NotificationsModule {
        if (PromotedNotificationContentModel.featureFlagEnabled()) {
            return implProvider.get();
        } else {
            return (entry, recoveredBuilder, redactionType, imageModelProvider) -> null;
            return (entry, recoveredBuilder, redactionType, imageModelProvider,
                    packageContext) -> null;
        }
    }

+10 −0
Original line number Diff line number Diff line
@@ -460,6 +460,7 @@ private class AODPromotedNotificationViewUpdater(root: View) {
        updateTextView(headerTextSecondary, content.subText)
        updateTitle(titleView, content)
        updateTimeAndChronometer(content)
        updateProfileBadge(content)

        updateHeaderDividers(content, hideTitle = !hasTitle, hideAppName = hideAppName)

@@ -495,6 +496,7 @@ private class AODPromotedNotificationViewUpdater(root: View) {
    ) {
        updateAppName(content, forceHide = collapsed)
        updateTimeAndChronometer(content)
        updateProfileBadge(content)

        updateImageView(verificationIcon, content.verificationIcon)
        updateTextView(verificationText, content.verificationText)
@@ -571,6 +573,14 @@ private class AODPromotedNotificationViewUpdater(root: View) {
        chronometer?.isVisible = (content.time is When.Chronometer)
    }

    private fun updateProfileBadge(content: PromotedNotificationContentModel) {
        if (content.profileBadgeBitmap != null) {
            profileBadge?.setImageBitmap(content.profileBadgeBitmap)
            profileBadge?.visibility = VISIBLE
            profileBadge?.setColorFilter(PrimaryText.colorInt, PorterDuff.Mode.SRC_IN)
        }
    }

    private fun updateNotifIcon(
        smallIconView: CachingIconView?,
        notifIcon: PromotedNotificationContentModel.NotifIcon?,
+16 −19
Original line number Diff line number Diff line
@@ -36,12 +36,10 @@ import android.app.Notification.InboxStyle
import android.app.Notification.ProgressStyle
import android.app.Person
import android.content.Context
import android.content.pm.PackageManager.NameNotFoundException
import android.graphics.drawable.Icon
import android.service.notification.StatusBarNotification
import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE
import com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType
import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -69,6 +67,7 @@ interface PromotedNotificationContentExtractor {
        recoveredBuilder: Notification.Builder,
        @RedactionType redactionType: Int,
        imageModelProvider: ImageModelProvider,
        packageContext: Context,
    ): PromotedNotificationContentModels?
}

@@ -76,7 +75,6 @@ interface PromotedNotificationContentExtractor {
class PromotedNotificationContentExtractorImpl
@Inject
constructor(
    @ShadeDisplayAware private val context: Context,
    private val notificationIconStyleProvider: NotificationIconStyleProvider,
    private val appIconProvider: AppIconProvider,
    private val skeletonImageTransform: SkeletonImageTransform,
@@ -88,6 +86,7 @@ constructor(
        recoveredBuilder: Notification.Builder,
        @RedactionType redactionType: Int,
        imageModelProvider: ImageModelProvider,
        packageContext: Context,
    ): PromotedNotificationContentModels? {
        if (!PromotedNotificationContentModel.featureFlagEnabled()) {
            if (LOG_NOT_EXTRACTED) {
@@ -118,6 +117,7 @@ constructor(
                recoveredBuilder = recoveredBuilder,
                lastAudiblyAlertedMs = entry.lastAudiblyAlertedMs,
                imageModelProvider = imageModelProvider,
                packageContext = packageContext,
            )
        val publicVersion =
            if (redactionType == REDACTION_TYPE_NONE) {
@@ -128,6 +128,7 @@ constructor(
                        privateModel = privateVersion,
                        publicNotification = publicNotification,
                        imageModelProvider = imageModelProvider,
                        packageContext = packageContext,
                    )
                } ?: createDefaultPublicVersion(privateModel = privateVersion)
            }
@@ -147,7 +148,7 @@ constructor(
        publicBuilder.appName = privateModel.appName
        publicBuilder.time = privateModel.time
        publicBuilder.lastAudiblyAlertedMs = privateModel.lastAudiblyAlertedMs
        publicBuilder.profileBadgeResId = privateModel.profileBadgeResId
        publicBuilder.profileBadgeBitmap = privateModel.profileBadgeBitmap
        publicBuilder.colors = privateModel.colors
    }

@@ -166,6 +167,7 @@ constructor(
        privateModel: PromotedNotificationContentModel,
        publicNotification: Notification,
        imageModelProvider: ImageModelProvider,
        packageContext: Context,
    ): PromotedNotificationContentModel =
        PromotedNotificationContentModel.Builder(key = privateModel.identity.key)
            .also { publicBuilder ->
@@ -198,6 +200,7 @@ constructor(
        recoveredBuilder: Notification.Builder,
        lastAudiblyAlertedMs: Long,
        imageModelProvider: ImageModelProvider,
        packageContext: Context,
    ): PromotedNotificationContentModel {
        val notification = sbn.notification

@@ -210,15 +213,16 @@ constructor(
            notification.extras.getBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, false)

        contentBuilder.skeletonNotifIcon =
            sbn.skeletonAppIcon() ?: notification.skeletonSmallIcon(imageModelProvider)
            sbn.skeletonAppIcon(packageContext)
                ?: notification.skeletonSmallIcon(imageModelProvider)

        contentBuilder.iconLevel = notification.iconLevel
        contentBuilder.appName = notification.loadHeaderAppName(context)
        contentBuilder.appName = notification.loadHeaderAppName(packageContext)
        contentBuilder.subText = notification.subText()
        contentBuilder.time = notification.extractWhen()
        contentBuilder.shortCriticalText = notification.shortCriticalText()
        contentBuilder.lastAudiblyAlertedMs = lastAudiblyAlertedMs
        contentBuilder.profileBadgeResId = null // TODO
        contentBuilder.profileBadgeBitmap = Notification.getProfileBadge(packageContext)
        contentBuilder.title = notification.title(recoveredBuilder.style?.javaClass)
        contentBuilder.text = notification.text(recoveredBuilder.style?.javaClass)
        contentBuilder.skeletonLargeIcon = notification.skeletonLargeIcon(imageModelProvider)
@@ -241,19 +245,12 @@ constructor(
    ): NotifIcon.SmallIcon? =
        imageModelProvider.getImageModel(smallIcon, SmallSquare)?.let { NotifIcon.SmallIcon(it) }

    private fun StatusBarNotification.skeletonAppIcon(): NotifIcon.AppIcon? {
    private fun StatusBarNotification.skeletonAppIcon(packageContext: Context): NotifIcon.AppIcon? {
        if (!android.app.Flags.notificationsRedesignAppIcons()) return null
        if (!notificationIconStyleProvider.shouldShowAppIcon(this, context)) return null
        return try {
            NotifIcon.AppIcon(appIconProvider.getOrFetchSkeletonAppIcon(packageName, context))
        } catch (e: NameNotFoundException) {
            // TODO: b/416215382 - Because we're passing the SystemUI context to AppIconProvider
            //  instead of the app's context, the fetch method can throw a NameNotFoundException
            //  if the app is not installed on the main profile. When this happens, we fall back to
            //  the small icon here as a temporary workaround, but this will be removed when the
            //  AppIconProvided is updated to receive a userId instead of a context.
            null
        }
        if (!notificationIconStyleProvider.shouldShowAppIcon(this, packageContext)) return null
        return NotifIcon.AppIcon(
            appIconProvider.getOrFetchSkeletonAppIcon(packageName, packageContext)
        )
    }

    private fun Notification.title(): CharSequence? = getCharSequenceExtraUnlessEmpty(EXTRA_TITLE)
Loading