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

Commit e44061f9 authored by Selim Cinek's avatar Selim Cinek Committed by Android (Google) Code Review
Browse files

Merge changes from topic 'music_extraction' into oc-dev

* changes:
  Make music notifications not dimmable
  Implementing gradual image fade for the media template
  Extracting the notification colors based on the album art
  Moved notification builder creation to the background
parents fc61f373 63edaf2a
Loading
Loading
Loading
Loading
+103 −6
Original line number Diff line number Diff line
@@ -2681,6 +2681,8 @@ public class Notification implements Parcelable
        private int mPrimaryTextColor = COLOR_INVALID;
        private int mSecondaryTextColor = COLOR_INVALID;
        private int mActionBarColor = COLOR_INVALID;
        private int mBackgroundColor = COLOR_INVALID;
        private int mForegroundColor = COLOR_INVALID;

        /**
         * Constructs a new Builder with the defaults:
@@ -3854,10 +3856,62 @@ public class Notification implements Parcelable
                    || mActionBarColor == COLOR_INVALID
                    || mTextColorsAreForBackground != backgroundColor) {
                mTextColorsAreForBackground = backgroundColor;
                mPrimaryTextColor = NotificationColorUtil.resolvePrimaryColor(
                        mContext, backgroundColor);
                mSecondaryTextColor = NotificationColorUtil.resolveSecondaryColor(
                        mContext, backgroundColor);
                if (mForegroundColor == COLOR_INVALID || !isColorized()) {
                    mPrimaryTextColor = NotificationColorUtil.resolvePrimaryColor(mContext,
                            backgroundColor);
                    mSecondaryTextColor = NotificationColorUtil.resolveSecondaryColor(mContext,
                            backgroundColor);
                } else {
                    double backLum = NotificationColorUtil.calculateLuminance(backgroundColor);
                    double textLum = NotificationColorUtil.calculateLuminance(mForegroundColor);
                    double contrast = NotificationColorUtil.calculateContrast(mForegroundColor,
                            backgroundColor);
                    boolean textDark = backLum > textLum;
                    if (contrast < 4.5f) {
                        if (textDark) {
                            mSecondaryTextColor = NotificationColorUtil.findContrastColor(
                                    mForegroundColor,
                                    backgroundColor,
                                    true /* findFG */,
                                    4.5f);
                            mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
                                    mSecondaryTextColor, -20);
                        } else {
                            mSecondaryTextColor =
                                    NotificationColorUtil.findContrastColorAgainstDark(
                                    mForegroundColor,
                                    backgroundColor,
                                    true /* findFG */,
                                    4.5f);
                            mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
                                    mSecondaryTextColor, 10);
                        }
                    } else {
                        mPrimaryTextColor = mForegroundColor;
                        mSecondaryTextColor = NotificationColorUtil.changeColorLightness(
                                mPrimaryTextColor, textDark ? 10 : -20);
                        if (NotificationColorUtil.calculateContrast(mSecondaryTextColor,
                                backgroundColor) < 4.5f) {
                            // oh well the secondary is not good enough
                            if (textDark) {
                                mSecondaryTextColor = NotificationColorUtil.findContrastColor(
                                        mSecondaryTextColor,
                                        backgroundColor,
                                        true /* findFG */,
                                        4.5f);
                            } else {
                                mSecondaryTextColor
                                        = NotificationColorUtil.findContrastColorAgainstDark(
                                        mSecondaryTextColor,
                                        backgroundColor,
                                        true /* findFG */,
                                        4.5f);
                            }
                            mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
                                    mSecondaryTextColor, textDark ? -20 : 10);
                        }
                    }
                }
                mActionBarColor = NotificationColorUtil.resolveActionBarColor(mContext,
                        backgroundColor);
            }
@@ -4845,7 +4899,7 @@ public class Notification implements Parcelable

        private int getBackgroundColor() {
            if (isColorized()) {
                return mN.color;
                return mBackgroundColor != COLOR_INVALID ? mBackgroundColor : mN.color;
            } else {
                return COLOR_DEFAULT;
            }
@@ -4863,6 +4917,21 @@ public class Notification implements Parcelable
            return targetSdkVersion > Build.VERSION_CODES.M
                    && targetSdkVersion < Build.VERSION_CODES.O;
        }

        /**
         * Set a color palette to be used as the background and textColors
         *
         * @param backgroundColor the color to be used as the background
         * @param foregroundColor the color to be used as the foreground
         *
         * @hide
         */
        public void setColorPalette(int backgroundColor, int foregroundColor) {
            mBackgroundColor = backgroundColor;
            mForegroundColor = foregroundColor;
            mTextColorsAreForBackground = COLOR_INVALID;
            ensureColors();
        }
    }

    /**
@@ -4899,6 +4968,18 @@ public class Notification implements Parcelable
     * @hide
     */
    public boolean isColorized() {
        if (isColorizedMedia()) {
            return true;
        }
        return extras.getBoolean(EXTRA_COLORIZED) && isForegroundService();
    }

    /**
     * @return true if this notification is colorized and it is a media notification
     *
     * @hide
     */
    public boolean isColorizedMedia() {
        Class<? extends Style> style = getNotificationStyle();
        if (MediaStyle.class.equals(style)) {
            Boolean colorized = (Boolean) extras.get(EXTRA_COLORIZED);
@@ -4910,7 +4991,23 @@ public class Notification implements Parcelable
                return true;
            }
        }
        return extras.getBoolean(EXTRA_COLORIZED) && isForegroundService();
        return false;
    }


    /**
     * @return true if this is a media notification
     *
     * @hide
     */
    public boolean isMediaNotification() {
        Class<? extends Style> style = getNotificationStyle();
        if (MediaStyle.class.equals(style)) {
            return true;
        } else if (DecoratedMediaCustomViewStyle.class.equals(style)) {
            return true;
        }
        return false;
    }

    private boolean hasLargeIcon() {
+16 −6
Original line number Diff line number Diff line
@@ -257,7 +257,7 @@ public class NotificationColorUtil {
     * @return a color with the same hue as {@param color}, potentially darkened to meet the
     *          contrast ratio.
     */
    private static int findContrastColor(int color, int other, boolean findFg, double minRatio) {
    public static int findContrastColor(int color, int other, boolean findFg, double minRatio) {
        int fg = findFg ? color : other;
        int bg = findFg ? other : color;
        if (ColorUtilsFromCompat.calculateContrast(fg, bg) >= minRatio) {
@@ -402,16 +402,17 @@ public class NotificationColorUtil {
    }

    /**
     * Lighten a color by a specified value
     * Change a color by a specified value
     * @param baseColor the base color to lighten
     * @param amount the amount to lighten the color from 0 to 100. This corresponds to the L
     *               increase in the LAB color space.
     * @return the lightened color
     *               increase in the LAB color space. A negative value will darken the color and
     *               a positive will lighten it.
     * @return the changed color
     */
    public static int lightenColor(int baseColor, int amount) {
    public static int changeColorLightness(int baseColor, int amount) {
        final double[] result = ColorUtilsFromCompat.getTempDouble3Array();
        ColorUtilsFromCompat.colorToLAB(baseColor, result);
        result[0] = Math.min(100, result[0] + amount);
        result[0] = Math.max(Math.min(100, result[0] + amount), 0);
        return ColorUtilsFromCompat.LABToColor(result[0], result[1], result[2]);
    }

@@ -491,6 +492,15 @@ public class NotificationColorUtil {
        return useDark;
    }

    public static double calculateLuminance(int backgroundColor) {
        return ColorUtilsFromCompat.calculateLuminance(backgroundColor);
    }


    public static double calculateContrast(int foregroundColor, int backgroundColor) {
        return ColorUtilsFromCompat.calculateContrast(foregroundColor, backgroundColor);
    }

    /**
     * Framework copy of functions needed from android.support.v4.graphics.ColorUtils.
     */
+35 −46
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RemoteViews;

/**
@@ -34,8 +33,7 @@ import android.widget.RemoteViews;
@RemoteViews.RemoteView
public class MediaNotificationView extends FrameLayout {

    private final int mMaxImageSize;
    private final int mImageMinTopMargin;
    private final int mSmallImageSize;
    private final int mNotificationContentMarginEnd;
    private final int mNotificationContentImageMarginEnd;
    private ImageView mRightIcon;
@@ -57,72 +55,68 @@ public class MediaNotificationView extends FrameLayout {

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        boolean hasIcon = mRightIcon.getVisibility() != GONE;
        if (!hasIcon) {
            resetHeaderIndention();
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        boolean reMeasure = false;
        if (hasIcon && mode != MeasureSpec.UNSPECIFIED) {
            measureChild(mActions, widthMeasureSpec, heightMeasureSpec);
            int size = MeasureSpec.getSize(widthMeasureSpec);
            size = size - mActions.getMeasuredWidth();
            ViewGroup.MarginLayoutParams layoutParams =
                    (MarginLayoutParams) mRightIcon.getLayoutParams();
            int imageEndMargin = layoutParams.getMarginEnd();
            size -= imageEndMargin;
            size = Math.min(size, mMaxImageSize);
            size = Math.max(size, mRightIcon.getMinimumWidth());
            int fullHeight = getMeasuredHeight();
            if (size < fullHeight) {
                size = mSmallImageSize;
            } else {
                size = fullHeight;
            }
            if (layoutParams.width != size || layoutParams.height != size) {
                layoutParams.width = size;
                layoutParams.height = size;
                mRightIcon.setLayoutParams(layoutParams);
                reMeasure = true;
            }

            // lets ensure that the main column doesn't run into the image
            ViewGroup.MarginLayoutParams mainParams
            ViewGroup.MarginLayoutParams params
                    = (MarginLayoutParams) mMainColumn.getLayoutParams();
            int marginEnd = size + imageEndMargin + mNotificationContentMarginEnd;
            if (marginEnd != mainParams.getMarginEnd()) {
                mainParams.setMarginEnd(marginEnd);
                mMainColumn.setLayoutParams(mainParams);
            }

            if (marginEnd != params.getMarginEnd()) {
                params.setMarginEnd(marginEnd);
                mMainColumn.setLayoutParams(params);
                reMeasure = true;
            }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        ViewGroup.MarginLayoutParams iconParams =
                (MarginLayoutParams) mRightIcon.getLayoutParams();
        int topMargin = getMeasuredHeight() - mRightIcon.getMeasuredHeight()
                - iconParams.bottomMargin;
        // If the topMargin is high enough we can also remove the header constraint!
        boolean reMeasure = false;
        if (!hasIcon || topMargin >= mImageMinTopMargin) {
            reMeasure = resetHeaderIndention();
        } else {
            int paddingEnd = mNotificationContentImageMarginEnd;
            ViewGroup.MarginLayoutParams headerParams =
                    (MarginLayoutParams) mHeader.getLayoutParams();
            int newMarginEnd = mRightIcon.getMeasuredWidth() + iconParams.getMarginEnd();
            if (headerParams.getMarginEnd() != newMarginEnd) {
                headerParams.setMarginEnd(newMarginEnd);
                mHeader.setLayoutParams(headerParams);
            int headerMarginEnd = size + imageEndMargin;
            params = (MarginLayoutParams) mHeader.getLayoutParams();
            if (params.getMarginEnd() != headerMarginEnd) {
                params.setMarginEnd(headerMarginEnd);
                mHeader.setLayoutParams(params);
                reMeasure = true;
            }
            if (mHeader.getPaddingEnd() != paddingEnd) {
            if (mHeader.getPaddingEnd() != mNotificationContentImageMarginEnd) {
                mHeader.setPaddingRelative(mHeader.getPaddingStart(),
                        mHeader.getPaddingTop(),
                        paddingEnd,
                        mNotificationContentImageMarginEnd,
                        mHeader.getPaddingBottom());
                reMeasure = true;
            }
        }
        if (reMeasure) {
            measureChildWithMargins(mHeader, widthMeasureSpec, 0, heightMeasureSpec, 0);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    private boolean resetHeaderIndention() {
        boolean remeasure = false;
    private void resetHeaderIndention() {
        if (mHeader.getPaddingEnd() != mNotificationContentMarginEnd) {
            mHeader.setPaddingRelative(mHeader.getPaddingStart(),
                    mHeader.getPaddingTop(),
                    mNotificationContentMarginEnd,
                    mHeader.getPaddingBottom());
            remeasure = true;
        }
        ViewGroup.MarginLayoutParams headerParams =
                (MarginLayoutParams) mHeader.getLayoutParams();
@@ -130,19 +124,14 @@ public class MediaNotificationView extends FrameLayout {
        if (headerParams.getMarginEnd() != 0) {
            headerParams.setMarginEnd(0);
            mHeader.setLayoutParams(headerParams);
            remeasure = true;
        }
        return remeasure;
    }

    public MediaNotificationView(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mMaxImageSize = context.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.media_notification_expanded_image_max_size);
        mImageMinTopMargin = (int) (context.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.notification_content_margin_top)
                + getResources().getDisplayMetrics().density * 2);
        mSmallImageSize = context.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.media_notification_expanded_image_small_size);
        mNotificationContentMarginEnd = context.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.notification_content_margin_end);
        mNotificationContentImageMarginEnd = context.getResources().getDimensionPixelSize(
+7 −10
Original line number Diff line number Diff line
@@ -23,6 +23,13 @@
    android:background="#00000000"
    android:tag="bigMediaNarrow"
    >
    <!-- The size will actually be determined at runtime -->
    <ImageView android:id="@+id/right_icon"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_gravity="top|end"
        android:scaleType="centerCrop"
    />
    <include layout="@layout/notification_template_header"
        android:layout_width="match_parent"
        android:layout_height="53dp"
@@ -60,14 +67,4 @@
            <!-- media buttons will be added here -->
        </LinearLayout>
    </LinearLayout>

    <ImageView android:id="@+id/right_icon"
        android:layout_width="@dimen/media_notification_expanded_image_max_size"
        android:layout_height="@dimen/media_notification_expanded_image_max_size"
        android:minWidth="40dp"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="20dp"
        android:layout_gravity="bottom|end"
        android:scaleType="centerCrop"
        />
</com.android.internal.widget.MediaNotificationView>
+7 −1
Original line number Diff line number Diff line
@@ -23,6 +23,13 @@
    android:background="#00000000"
    android:tag="media"
    >
    <ImageView android:id="@+id/right_icon"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:layout_gravity="top|end"
        android:scaleType="centerCrop"
    />
    <include layout="@layout/notification_template_header"
        android:layout_width="fill_parent"
        android:layout_height="53dp" />
@@ -61,5 +68,4 @@
            <!-- media buttons will be added here -->
        </LinearLayout>
    </LinearLayout>
    <include layout="@layout/notification_template_right_icon" />
</FrameLayout>
Loading