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

Commit cb3584f8 authored by Ioana Alexandru's avatar Ioana Alexandru
Browse files

Remove app icon prototypes code

Now the "real" code is behind notifications_redesign_app_icons, so we
don't need the old prototypes anymore.

I also removed two unused Notification.java fields since I was looking
for unused warnings there to make sure I didn't miss anything.

There's a change in IconManager that I wanted to keep (caching the icon
all the time as opposed to only for conversations), so I updated it to
be done behind the new flag.

Bug: 371174789
Test: builds
Flag: EXEMPT removing flagged code
Flag: android.app.notifications_redesign_app_icons
Change-Id: Icbc05f22ac03ea410e310ec31139bc7902233923
parent 5f8b3699
Loading
Loading
Loading
Loading
+4 −174
Original line number Diff line number Diff line
@@ -155,7 +155,7 @@ public class Notification implements Parcelable
            FOREGROUND_SERVICE_IMMEDIATE,
            FOREGROUND_SERVICE_DEFERRED
    })
    public @interface ServiceNotificationPolicy {};
    public @interface ServiceNotificationPolicy {}
    /**
     * If the Notification associated with starting a foreground service has been
@@ -1754,10 +1754,6 @@ public class Notification implements Parcelable
    private Icon mSmallIcon;
    @UnsupportedAppUsage
    private Icon mLargeIcon;
    private Icon mAppIcon;
    /** Cache for whether the notification was posted by a headless system app. */
    private Boolean mBelongsToHeadlessSystemApp = null;
    @UnsupportedAppUsage
    private String mChannelId;
@@ -3246,86 +3242,6 @@ public class Notification implements Parcelable
                && hasPromotableStyle();
    }
    /**
     * Whether this notification was posted by a headless system app.
     *
     * If we don't have enough information to figure this out, this will return false. Therefore,
     * false negatives are possible, but false positives should not be.
     *
     * @hide
     */
    public boolean belongsToHeadlessSystemApp(Context context) {
        Trace.beginSection("Notification#belongsToHeadlessSystemApp");
        try {
            if (mBelongsToHeadlessSystemApp != null) {
                return mBelongsToHeadlessSystemApp;
            }
            if (context == null) {
                // Without a valid context, we don't know exactly. Let's assume it doesn't belong to
                // a system app, but not cache the value.
                return false;
            }
            ApplicationInfo info = getApplicationInfo(context);
            if (info != null) {
                if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                    // It's not a system app at all.
                    mBelongsToHeadlessSystemApp = false;
                } else {
                    // If there's no launch intent, it's probably a headless app.
                    final PackageManager pm = context.getPackageManager();
                    mBelongsToHeadlessSystemApp = pm.getLaunchIntentForPackage(info.packageName)
                            == null;
                }
            } else {
                // If for some reason we don't have the app info, we don't know; best assume it's
                // not a system app.
                return false;
            }
            return mBelongsToHeadlessSystemApp;
        } finally {
            Trace.endSection();
        }
    }
    /**
     * Get the resource ID of the app icon from application info.
     * @hide
     */
    public int getHeaderAppIconRes(Context context) {
        ApplicationInfo info = getApplicationInfo(context);
        if (info != null) {
            return info.icon;
        }
        return 0;
    }
    /**
     * Load the app icon drawable from the package manager. This could result in a binder call.
     * @hide
     */
    public Drawable loadHeaderAppIcon(Context context) {
        Trace.beginSection("Notification#loadHeaderAppIcon");
        try {
            if (context == null) {
                Log.e(TAG, "Cannot load the app icon drawable with a null context");
                return null;
            }
            final PackageManager pm = context.getPackageManager();
            ApplicationInfo info = getApplicationInfo(context);
            if (info == null) {
                Log.e(TAG, "Cannot load the app icon drawable: no application info");
                return null;
            }
            return pm.getApplicationIcon(info);
        } finally {
            Trace.endSection();
        }
    }
    /**
     * Fetch the application info from the notification, or the context if that isn't available.
     */
@@ -4360,55 +4276,6 @@ public class Notification implements Parcelable
        mSmallIcon = icon;
    }
    /**
     * The colored app icon that can replace the small icon in the notification starting in V.
     *
     * Before using this value, you should first check whether it's actually being used by the
     * notification by calling {@link Notification#shouldUseAppIcon()}.
     *
     * @hide
     */
    public Icon getAppIcon() {
        if (mAppIcon != null) {
            return mAppIcon;
        }
        // If the app icon hasn't been loaded yet, check if we can load it without a context.
        if (extras.containsKey(EXTRA_BUILDER_APPLICATION_INFO)) {
            final ApplicationInfo info = extras.getParcelable(
                    EXTRA_BUILDER_APPLICATION_INFO,
                    ApplicationInfo.class);
            if (info != null) {
                int appIconRes = info.icon;
                if (appIconRes == 0) {
                    Log.w(TAG, "Failed to get the app icon: no icon in application info");
                    return null;
                }
                mAppIcon = Icon.createWithResource(info.packageName, appIconRes);
                return mAppIcon;
            } else {
                Log.e(TAG, "Failed to get the app icon: "
                        + "there's an EXTRA_BUILDER_APPLICATION_INFO in extras but it's null");
            }
        } else {
            Log.w(TAG, "Failed to get the app icon: no application info in extras");
        }
        return null;
    }
    /**
     * Whether the notification is using the app icon instead of the small icon.
     * @hide
     */
    public boolean shouldUseAppIcon() {
        if (Flags.notificationsUseAppIconInRow()) {
            if (belongsToHeadlessSystemApp(/* context = */ null)) {
                return false;
            }
            return getAppIcon() != null;
        }
        return false;
    }
    /**
     * The large icon shown in this notification's content view.
     * @see Builder#getLargeIcon()
@@ -4566,19 +4433,6 @@ public class Notification implements Parcelable
        private static final boolean USE_ONLY_TITLE_IN_LOW_PRIORITY_SUMMARY =
                SystemProperties.getBoolean("notifications.only_title", true);
        /**
         * The lightness difference that has to be added to the primary text color to obtain the
         * secondary text color when the background is light.
         */
        private static final int LIGHTNESS_TEXT_DIFFERENCE_LIGHT = 20;
        /**
         * The lightness difference that has to be added to the primary text color to obtain the
         * secondary text color when the background is dark.
         * A bit less then the above value, since it looks better on dark backgrounds.
         */
        private static final int LIGHTNESS_TEXT_DIFFERENCE_DARK = -10;
        private Context mContext;
        private Notification mN;
        private Bundle mUserExtras = new Bundle();
@@ -6451,37 +6305,13 @@ public class Notification implements Parcelable
        }
        private void bindSmallIcon(RemoteViews contentView, StandardTemplateParams p) {
            if (Flags.notificationsUseAppIcon()) {
                // Override small icon with app icon
                mN.mSmallIcon = Icon.createWithResource(mContext,
                        mN.getHeaderAppIconRes(mContext));
            } else if (mN.mSmallIcon == null && mN.icon != 0) {
            if (mN.mSmallIcon == null && mN.icon != 0) {
                mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon);
            }
            boolean usingAppIcon = false;
            if (Flags.notificationsUseAppIconInRow() && !mN.belongsToHeadlessSystemApp(mContext)) {
                // Use the app icon in the view
                int appIconRes = mN.getHeaderAppIconRes(mContext);
                if (appIconRes != 0) {
                    mN.mAppIcon = Icon.createWithResource(mContext, appIconRes);
                    contentView.setImageViewIcon(R.id.icon, mN.mAppIcon);
                    contentView.setBoolean(R.id.icon, "setShouldShowAppIcon", true);
                    usingAppIcon = true;
                } else {
                    Log.w(TAG, "bindSmallIcon: could not get the app icon");
                }
            }
            if (!usingAppIcon) {
            contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon);
            }
            contentView.setInt(R.id.icon, "setImageLevel", mN.iconLevel);
            // Don't change color if we're using the app icon.
            if (!Flags.notificationsUseAppIcon() && !usingAppIcon) {
            processSmallIconColor(mN.mSmallIcon, contentView, p);
        }
        }
        /**
         * @return true if the built notification will show the time or the chronometer; false
+1 −27
Original line number Diff line number Diff line
@@ -8,8 +8,7 @@ container: "system"
flag {
  name: "notifications_redesign_app_icons"
  namespace: "systemui"
  description: "Notifications Redesign: Use app icons in notification rows (not to be confused with"
    " notifications_use_app_icons, notifications_use_app_icon_in_row which are just experiments)."
  description: "Notifications Redesign: Use app icons in notification rows"
  bug: "371174789"
}

@@ -110,31 +109,6 @@ flag {
  }
}

# vvv Prototypes for using app icons in notifications vvv

flag {
  name: "notifications_use_app_icon"
  namespace: "systemui"
  description: "Experiment to replace the small icon in a notification with the app icon. This includes the status bar, AOD, shelf and notification row itself."
  bug: "335211019"
}

flag {
  name: "notifications_use_app_icon_in_row"
  namespace: "systemui"
  description: "Experiment to replace the small icon in a notification row with the app icon."
  bug: "335211019"
}

flag {
  name: "notifications_use_monochrome_app_icon"
  namespace: "systemui"
  description: "Experiment to replace the notification icon in the status bar and shelf with the monochrome app icon, if available."
  bug: "335211019"
}

# ^^^ Prototypes for using app icons in notifications ^^^

flag {
  name: "notification_expansion_optional"
  namespace: "systemui"
+0 −3
Original line number Diff line number Diff line
@@ -40,9 +40,6 @@ public class StatusBarIcon implements Parcelable {
    public enum Type {
        // Notification: the sender avatar for important conversations
        PeopleAvatar,
        // Notification: the monochrome version of the app icon if available; otherwise fall back to
        // the small icon
        MaybeMonochromeAppIcon,
        // Notification: the small icon from the notification
        NotifSmallIcon,
        // The wi-fi, cellular or battery icon.
+1 −59
Original line number Diff line number Diff line
@@ -22,11 +22,7 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -35,8 +31,6 @@ import android.util.AttributeSet;
import android.view.RemotableViewMethod;
import android.widget.RemoteViews;

import com.android.internal.R;

/**
 * An image view that holds the icon displayed at the start of a notification row.
 * This can generally either display the "small icon" of a notification set via
@@ -48,7 +42,6 @@ public class NotificationRowIconView extends CachingIconView {
    private NotificationIconProvider mIconProvider;

    private boolean mApplyCircularCrop = false;
    private boolean mShouldShowAppIcon = false;
    private Drawable mAppIcon = null;

    // Padding, background and colors set on the view prior to being overridden when showing the app
@@ -77,17 +70,6 @@ public class NotificationRowIconView extends CachingIconView {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onFinishInflate() {
        // If showing the app icon, we don't need background or padding.
        if (Flags.notificationsUseAppIcon()) {
            setPadding(0, 0, 0, 0);
            setBackground(null);
        }

        super.onFinishInflate();
    }

    /**
     * Sets the icon provider for this view. This is used to determine whether we should show the
     * app icon instead of the small icon, and to fetch the app icon if needed.
@@ -153,38 +135,13 @@ public class NotificationRowIconView extends CachingIconView {
        return super.setImageIconAsync(icon);
    }

    /** Whether the icon represents the app icon (instead of the small icon). */
    @RemotableViewMethod
    public void setShouldShowAppIcon(boolean shouldShowAppIcon) {
        if (Flags.notificationsUseAppIconInRow()) {
            if (mShouldShowAppIcon == shouldShowAppIcon) {
                return; // no change
            }

            mShouldShowAppIcon = shouldShowAppIcon;
            if (mShouldShowAppIcon) {
                adjustViewForAppIcon();
            } else {
                // Restore original padding and background if needed
                restoreViewForSmallIcon();
            }
        }
    }

    /**
     * Override padding and background from the view to display the app icon.
     */
    private void adjustViewForAppIcon() {
        removePadding();

        if (Flags.notificationsUseAppIconInRow()) {
            addWhiteBackground();
        } else {
            // No need to set the background for notification redesign, since the icon
            // factory already does that for us.
        removeBackground();
    }
    }

    /**
     * Restore padding and background overridden by {@link this#adjustViewForAppIcon}.
@@ -221,21 +178,6 @@ public class NotificationRowIconView extends CachingIconView {
        setBackground(null);
    }

    private void addWhiteBackground() {
        if (mOriginalBackground == null) {
            mOriginalBackground = getBackground();
        }

        // Make the background white in case the icon itself doesn't have one.
        ColorFilter colorFilter = new PorterDuffColorFilter(Color.WHITE,
                PorterDuff.Mode.SRC_ATOP);

        if (mOriginalBackground == null) {
            setBackground(getContext().getDrawable(R.drawable.notification_icon_circle));
        }
        getBackground().mutate().setColorFilter(colorFilter);
    }

    private void restoreBackground() {
        // NOTE: This will not work if the original background was null, but that's better than
        //  accidentally clearing the background. We expect that there's generally going to be one
+4 −18
Original line number Diff line number Diff line
@@ -383,34 +383,20 @@ public class NotificationGroupingUtil {
        }

        protected boolean hasSameIcon(Object parentData, Object childData) {
            Icon parentIcon = getIcon((Notification) parentData);
            Icon childIcon = getIcon((Notification) childData);
            Icon parentIcon = ((Notification) parentData).getSmallIcon();
            Icon childIcon = ((Notification) childData).getSmallIcon();
            return parentIcon.sameAs(childIcon);
        }

        private static Icon getIcon(Notification notification) {
            if (notification.shouldUseAppIcon()) {
                return notification.getAppIcon();
            }
            return notification.getSmallIcon();
        }

        /**
         * @return whether two ImageViews have the same colorFilterSet or none at all
         */
        protected boolean hasSameColor(Object parentData, Object childData) {
            int parentColor = getColor((Notification) parentData);
            int childColor = getColor((Notification) childData);
            int parentColor = ((Notification) parentData).color;
            int childColor = ((Notification) childData).color;
            return parentColor == childColor;
        }

        private static int getColor(Notification notification) {
            if (notification.shouldUseAppIcon()) {
                return 0;  // the color filter isn't applied if using the app icon
            }
            return notification.color;
        }

        @Override
        public boolean isEmpty(View view) {
            return false;
Loading