OSDN Git Service

Implementing gradual image fade for the media template
authorSelim Cinek <cinek@google.com>
Tue, 25 Apr 2017 02:48:29 +0000 (19:48 -0700)
committerSelim Cinek <cinek@google.com>
Thu, 27 Apr 2017 22:21:50 +0000 (22:21 +0000)
Test: play music
Merged-In: I525513ce1da1237c4edad32c0ed31e79d5eacd32
Change-Id: I525513ce1da1237c4edad32c0ed31e79d5eacd32
Fixes: 36561228

core/java/android/app/Notification.java
core/java/com/android/internal/widget/MediaNotificationView.java
core/res/res/layout/notification_template_material_big_media.xml
core/res/res/layout/notification_template_material_media.xml
core/res/res/values/dimens.xml
core/res/res/values/symbols.xml
packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java [new file with mode: 0644]
packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java

index d64ffa9..07e4a8f 100644 (file)
@@ -4959,6 +4959,22 @@ public class Notification implements Parcelable
         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() {
         return mLargeIcon != null || largeIcon != null;
     }
index afb2a5e..bbebcc2 100644 (file)
@@ -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());
-            layoutParams.width = size;
-            layoutParams.height = size;
-            mRightIcon.setLayoutParams(layoutParams);
+            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(
index 04ea12d..532f28e 100644 (file)
     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"
             <!-- 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>
index 4c64207..4be53e0 100644 (file)
     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>
index c5316c6..ef6c21f 100644 (file)
     <!-- The minimum height of the content if there are at least two lines or a picture-->
     <dimen name="notification_min_content_height">41dp</dimen>
 
-    <!-- The maximum size of the image in the expanded media notification -->
-    <dimen name="media_notification_expanded_image_max_size">94dp</dimen>
+    <!-- The small size of the image if the height drawing doesn't work anymore -->
+    <dimen name="media_notification_expanded_image_small_size">72dp</dimen>
 
     <!-- The maximum size of the image in the expanded media notification -->
     <dimen name="media_notification_expanded_image_margin_bottom">20dp</dimen>
index 63a5cfd..9a31a39 100644 (file)
   <java-symbol type="string" name="new_sms_notification_title" />
   <java-symbol type="string" name="new_sms_notification_content" />
 
-  <java-symbol type="dimen" name="media_notification_expanded_image_max_size" />
+  <java-symbol type="dimen" name="media_notification_expanded_image_small_size" />
   <java-symbol type="dimen" name="media_notification_expanded_image_margin_bottom" />
   <java-symbol type="dimen" name="notification_content_image_margin_end" />
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
new file mode 100644 (file)
index 0000000..82910b8
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Shader;
+import android.graphics.Xfermode;
+import android.graphics.drawable.Drawable;
+
+/**
+ * A utility class to colorize bitmaps with a color gradient and a special blending mode
+ */
+public class ImageGradientColorizer {
+    public Bitmap colorize(Drawable drawable, int backgroundColor) {
+        int width = drawable.getIntrinsicWidth();
+        int height = drawable.getIntrinsicHeight();
+        int size = Math.min(width, height);
+        int widthInset = (width - size) / 2;
+        int heightInset = (height - size) / 2;
+        drawable = drawable.mutate();
+        drawable.setBounds(- widthInset, - heightInset, width - widthInset, height - heightInset);
+        Bitmap newBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(newBitmap);
+
+        // Values to calculate the luminance of a color
+        float lr = 0.2126f;
+        float lg = 0.7152f;
+        float lb = 0.0722f;
+
+        // Extract the red, green, blue components of the color extraction color in
+        // float and int form
+        int tri = Color.red(backgroundColor);
+        int tgi = Color.green(backgroundColor);
+        int tbi = Color.blue(backgroundColor);
+
+        float tr = tri / 255f;
+        float tg = tgi / 255f;
+        float tb = tbi / 255f;
+
+        // Calculate the luminance of the color extraction color
+        float cLum = (tr * lr + tg * lg + tb * lb) * 255;
+
+        ColorMatrix m = new ColorMatrix(new float[] {
+                lr, lg, lb, 0, tri - cLum,
+                lr, lg, lb, 0, tgi - cLum,
+                lr, lg, lb, 0, tbi - cLum,
+                0, 0, 0, 1, 0,
+        });
+
+        drawable.setColorFilter(new ColorMatrixColorFilter(m));
+        drawable.draw(canvas);
+        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        LinearGradient linearGradient =  new LinearGradient(0, 0, size, 0,
+                new int[] {0, Color.argb(0.5f, 1, 1, 1), Color.BLACK},
+                new float[] {0.0f, 0.4f, 1.0f}, Shader.TileMode.CLAMP);
+        paint.setShader(linearGradient);
+        Bitmap fadeIn = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+        Canvas fadeInCanvas = new Canvas(fadeIn);
+        drawable.clearColorFilter();
+        drawable.draw(fadeInCanvas);
+        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
+        fadeInCanvas.drawPaint(paint);
+        canvas.drawBitmap(fadeIn, 0, 0, null);
+
+        linearGradient = new LinearGradient(0, 0, size, 0,
+                new int[] {backgroundColor, Color.argb(0.5f, tr, tg, tb), 0},
+                new float[] {0.0f, 0.6f, 1.0f}, Shader.TileMode.CLAMP);
+        paint.setShader(linearGradient);
+        paint.setXfermode(null);
+        canvas.drawPaint(paint);
+        return newBitmap;
+    }
+}
index ccba664..cef225b 100644 (file)
@@ -26,6 +26,8 @@ import android.graphics.drawable.Icon;
 import android.support.v4.graphics.ColorUtils;
 import android.support.v7.graphics.Palette;
 
+import com.android.systemui.R;
+
 import java.util.List;
 
 /**
@@ -41,6 +43,8 @@ public class MediaNotificationProcessor {
     private static final float BLACK_MAX_LIGHTNESS = 0.08f;
     private static final float WHITE_MIN_LIGHTNESS = 0.92f;
     private static final int RESIZE_BITMAP_AREA = 150 * 150;
+    private final ImageGradientColorizer mColorizer;
+    private final Context mContext;
     private float[] mFilteredBackgroundHsl = null;
     private Palette.Filter mBlackWhiteFilter = (rgb, hsl) -> !isWhiteOrBlack(hsl);
 
@@ -48,10 +52,13 @@ public class MediaNotificationProcessor {
      * The context of the notification. This is the app context of the package posting the
      * notification.
      */
-    private final Context mContext;
+    private final Context mPackageContext;
+    private boolean mIsLowPriority;
 
-    public MediaNotificationProcessor(Context context) {
+    public MediaNotificationProcessor(Context context, Context packageContext) {
         mContext = context;
+        mPackageContext = packageContext;
+        mColorizer = new ImageGradientColorizer();
     }
 
     /**
@@ -64,114 +71,124 @@ public class MediaNotificationProcessor {
     public void processNotification(Notification notification, Notification.Builder builder) {
         Icon largeIcon = notification.getLargeIcon();
         Bitmap bitmap = null;
+        Drawable drawable = null;
         if (largeIcon != null) {
-            Drawable drawable = largeIcon.loadDrawable(mContext);
-            int width = drawable.getIntrinsicWidth();
-            int height = drawable.getIntrinsicHeight();
-            int area = width * height;
-            if (area > RESIZE_BITMAP_AREA) {
-                double factor = Math.sqrt((float) RESIZE_BITMAP_AREA / area);
-                width = (int) (factor * width);
-                height = (int) (factor * height);
-            }
-            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(bitmap);
-            drawable.setBounds(0, 0, width, height);
-            drawable.draw(canvas);
-        }
-        if (bitmap != null) {
-            // for the background we only take the left side of the image to ensure
-            // a smooth transition
-            Palette.Builder paletteBuilder = Palette.from(bitmap)
-                    .setRegion(0, 0, bitmap.getWidth() / 2, bitmap.getHeight())
-                    .clearFilters() // we want all colors, red / white / black ones too!
-                    .resizeBitmapArea(RESIZE_BITMAP_AREA);
-            Palette palette = paletteBuilder.generate();
-            int backgroundColor = findBackgroundColorAndFilter(palette);
-            // we want the full region again
-            paletteBuilder.setRegion(0, 0, bitmap.getWidth(), bitmap.getHeight());
-            if (mFilteredBackgroundHsl != null) {
-                paletteBuilder.addFilter((rgb, hsl) -> {
-                    // at least 10 degrees hue difference
-                    float diff = Math.abs(hsl[0] - mFilteredBackgroundHsl[0]);
-                    return diff > 10 && diff < 350;
-                });
-            }
-            paletteBuilder.addFilter(mBlackWhiteFilter);
-            palette = paletteBuilder.generate();
-            int foregroundColor;
-            if (ColorUtils.calculateLuminance(backgroundColor) > 0.5) {
-                Palette.Swatch first = palette.getDarkVibrantSwatch();
-                Palette.Swatch second = palette.getVibrantSwatch();
-                if (first != null && second != null) {
-                    int firstPopulation = first.getPopulation();
-                    int secondPopulation = second.getPopulation();
-                    if (firstPopulation / secondPopulation
-                            < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
-                        foregroundColor = second.getRgb();
-                    } else {
-                        foregroundColor = first.getRgb();
-                    }
-                } else if (first != null) {
-                    foregroundColor = first.getRgb();
-                } else if (second != null) {
-                    foregroundColor = second.getRgb();
-                } else {
-                    first = palette.getMutedSwatch();
-                    second = palette.getDarkMutedSwatch();
+            drawable = largeIcon.loadDrawable(mPackageContext);
+            int backgroundColor = 0;
+            if (notification.isColorizedMedia()) {
+                int width = drawable.getIntrinsicWidth();
+                int height = drawable.getIntrinsicHeight();
+                int area = width * height;
+                if (area > RESIZE_BITMAP_AREA) {
+                    double factor = Math.sqrt((float) RESIZE_BITMAP_AREA / area);
+                    width = (int) (factor * width);
+                    height = (int) (factor * height);
+                }
+                bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+                Canvas canvas = new Canvas(bitmap);
+                drawable.setBounds(0, 0, width, height);
+                drawable.draw(canvas);
+
+                // for the background we only take the left side of the image to ensure
+                // a smooth transition
+                Palette.Builder paletteBuilder = Palette.from(bitmap)
+                        .setRegion(0, 0, bitmap.getWidth() / 2, bitmap.getHeight())
+                        .clearFilters() // we want all colors, red / white / black ones too!
+                        .resizeBitmapArea(RESIZE_BITMAP_AREA);
+                Palette palette = paletteBuilder.generate();
+                backgroundColor = findBackgroundColorAndFilter(palette);
+                // we want the full region again
+                paletteBuilder.setRegion(0, 0, bitmap.getWidth(), bitmap.getHeight());
+                if (mFilteredBackgroundHsl != null) {
+                    paletteBuilder.addFilter((rgb, hsl) -> {
+                        // at least 10 degrees hue difference
+                        float diff = Math.abs(hsl[0] - mFilteredBackgroundHsl[0]);
+                        return diff > 10 && diff < 350;
+                    });
+                }
+                paletteBuilder.addFilter(mBlackWhiteFilter);
+                palette = paletteBuilder.generate();
+                int foregroundColor;
+                if (ColorUtils.calculateLuminance(backgroundColor) > 0.5) {
+                    Palette.Swatch first = palette.getDarkVibrantSwatch();
+                    Palette.Swatch second = palette.getVibrantSwatch();
                     if (first != null && second != null) {
-                        float firstSaturation = first.getHsl()[1];
-                        float secondSaturation = second.getHsl()[1];
-                        if (firstSaturation > secondSaturation) {
-                            foregroundColor = first.getRgb();
-                        } else {
+                        int firstPopulation = first.getPopulation();
+                        int secondPopulation = second.getPopulation();
+                        if (firstPopulation / secondPopulation
+                                < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
                             foregroundColor = second.getRgb();
+                        } else {
+                            foregroundColor = first.getRgb();
                         }
                     } else if (first != null) {
                         foregroundColor = first.getRgb();
                     } else if (second != null) {
                         foregroundColor = second.getRgb();
                     } else {
-                        foregroundColor = Color.BLACK;
-                    }
-                }
-            } else {
-                Palette.Swatch first = palette.getLightVibrantSwatch();
-                Palette.Swatch second = palette.getVibrantSwatch();
-                if (first != null && second != null) {
-                    int firstPopulation = first.getPopulation();
-                    int secondPopulation = second.getPopulation();
-                    if (firstPopulation / secondPopulation
-                            < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
-                        foregroundColor = second.getRgb();
-                    } else {
-                        foregroundColor = first.getRgb();
+                        first = palette.getMutedSwatch();
+                        second = palette.getDarkMutedSwatch();
+                        if (first != null && second != null) {
+                            float firstSaturation = first.getHsl()[1];
+                            float secondSaturation = second.getHsl()[1];
+                            if (firstSaturation > secondSaturation) {
+                                foregroundColor = first.getRgb();
+                            } else {
+                                foregroundColor = second.getRgb();
+                            }
+                        } else if (first != null) {
+                            foregroundColor = first.getRgb();
+                        } else if (second != null) {
+                            foregroundColor = second.getRgb();
+                        } else {
+                            foregroundColor = Color.BLACK;
+                        }
                     }
-                } else if (first != null) {
-                    foregroundColor = first.getRgb();
-                } else if (second != null) {
-                    foregroundColor = second.getRgb();
                 } else {
-                    first = palette.getMutedSwatch();
-                    second = palette.getLightMutedSwatch();
+                    Palette.Swatch first = palette.getLightVibrantSwatch();
+                    Palette.Swatch second = palette.getVibrantSwatch();
                     if (first != null && second != null) {
-                        float firstSaturation = first.getHsl()[1];
-                        float secondSaturation = second.getHsl()[1];
-                        if (firstSaturation > secondSaturation) {
-                            foregroundColor = first.getRgb();
-                        } else {
+                        int firstPopulation = first.getPopulation();
+                        int secondPopulation = second.getPopulation();
+                        if (firstPopulation / secondPopulation
+                                < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
                             foregroundColor = second.getRgb();
+                        } else {
+                            foregroundColor = first.getRgb();
                         }
                     } else if (first != null) {
                         foregroundColor = first.getRgb();
                     } else if (second != null) {
                         foregroundColor = second.getRgb();
                     } else {
-                        foregroundColor = Color.WHITE;
+                        first = palette.getMutedSwatch();
+                        second = palette.getLightMutedSwatch();
+                        if (first != null && second != null) {
+                            float firstSaturation = first.getHsl()[1];
+                            float secondSaturation = second.getHsl()[1];
+                            if (firstSaturation > secondSaturation) {
+                                foregroundColor = first.getRgb();
+                            } else {
+                                foregroundColor = second.getRgb();
+                            }
+                        } else if (first != null) {
+                            foregroundColor = first.getRgb();
+                        } else if (second != null) {
+                            foregroundColor = second.getRgb();
+                        } else {
+                            foregroundColor = Color.WHITE;
+                        }
                     }
                 }
+                builder.setColorPalette(backgroundColor, foregroundColor);
+            } else {
+                int id = mIsLowPriority
+                        ? R.color.notification_material_background_low_priority_color
+                        : R.color.notification_material_background_color;
+                backgroundColor = mContext.getColor(id);
             }
-            builder.setColorPalette(backgroundColor, foregroundColor);
+            Bitmap colorized = mColorizer.colorize(drawable, backgroundColor);
+            builder.setLargeIcon(Icon.createWithBitmap(colorized));
         }
     }
 
@@ -235,4 +252,8 @@ public class MediaNotificationProcessor {
     private boolean isWhite(float[] hslColor) {
         return hslColor[2] >= WHITE_MIN_LIGHTNESS;
     }
+
+    public void setIsLowPriority(boolean isLowPriority) {
+        mIsLowPriority = isLowPriority;
+    }
 }
index 77fc5e6..6c6dfa4 100644 (file)
@@ -310,9 +310,10 @@ public class NotificationInflater {
                         mSbn.getNotification());
                 mPackageContext = mSbn.getPackageContext(mContext);
                 Notification notification = mSbn.getNotification();
-                if (notification.isColorizedMedia()) {
-                    MediaNotificationProcessor processor = new MediaNotificationProcessor(
+                if (notification.isMediaNotification()) {
+                    MediaNotificationProcessor processor = new MediaNotificationProcessor(mContext,
                             mPackageContext);
+                    processor.setIsLowPriority(mIsLowPriority);
                     processor.processNotification(notification, recoveredBuilder);
                 }
                 return recoveredBuilder;