Update the notification templates

Most of the notification templates have been updated.
Some cases like media notifications don't yet work well
but will be fixed in a later CL.

Bug: 25376106
Change-Id: I26c366e58ebba3852cea20de6fca311bd302bb24
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index a12a3f1..19b65f7 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -36,7 +36,6 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
-import android.view.View;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -162,9 +161,6 @@
                 .setColor(mContext.getColor(
                         com.android.internal.R.color.system_notification_accent_color));
         final Notification n = nb.build();
-        if (n.headsUpContentView != null) {
-            n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE);
-        }
         mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
     }
 
@@ -200,9 +196,6 @@
             mPlaySound = false;
         }
         final Notification n = nb.build();
-        if (n.headsUpContentView != null) {
-            n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE);
-        }
         mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 723989a..182fc1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -40,7 +40,6 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.AsyncTask;
@@ -1498,18 +1497,6 @@
 
             Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic);
             icon.setImageDrawable(iconDrawable);
-            if (entry.targetSdk >= Build.VERSION_CODES.LOLLIPOP
-                    || mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) {
-                icon.setBackgroundResource(
-                        com.android.internal.R.drawable.notification_icon_legacy_bg);
-                int padding = mContext.getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.notification_large_icon_circle_padding);
-                icon.setPadding(padding, padding, padding, padding);
-                if (sbn.getNotification().color != Notification.COLOR_DEFAULT) {
-                    icon.getBackground().setColorFilter(
-                            sbn.getNotification().color, PorterDuff.Mode.SRC_ATOP);
-                }
-            }
 
             if (profileBadge != null) {
                 Drawable profileDrawable = mContext.getPackageManager().getUserBadgeForDensity(
@@ -1536,11 +1523,6 @@
                         R.style.TextAppearance_Material_Notification_Parenthetical);
             }
 
-            int topPadding = Notification.Builder.calculateTopPadding(mContext,
-                    false /* hasThreeLines */,
-                    mContext.getResources().getConfiguration().fontScale);
-            title.setPadding(0, topPadding, 0, 0);
-
             contentContainerPublic.setContractedChild(publicViewLocal);
             entry.autoRedacted = true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 3603900..02632d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -452,6 +452,8 @@
         super.onFinishInflate();
         mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
         mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
+        mPublicLayout.setContainingNotification(this);
+        mPrivateLayout.setContainingNotification(this);
         mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
         mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
             @Override
@@ -534,6 +536,7 @@
 
     public void setExpandable(boolean expandable) {
         mExpandable = expandable;
+        mPrivateLayout.updateExpandButtons();
     }
 
     /**
@@ -686,6 +689,7 @@
         if (mIsSummaryWithChildren && mChildrenContainer == null) {
             mChildrenContainerStub.inflate();
         }
+        mPrivateLayout.updateExpandButtons();
         updateNotificationHeader();
         updateChildrenVisibility(true);
     }
@@ -771,6 +775,7 @@
             animateShowingPublic(delay, duration);
         }
 
+        mPrivateLayout.updateExpandButtons();
         updateVetoButton();
         mShowingPublicInitialized = true;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 5aedaf1..17d9856 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -77,7 +77,9 @@
     private boolean mIsHeadsUp;
     private boolean mShowingLegacyBackground;
     private boolean mIsChildInGroup;
+    private ExpandableNotificationRow mContainingNotification;
     private StatusBarNotification mStatusBarNotification;
+    private NotificationGroupManager mGroupManager;
 
     private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
             = new ViewTreeObserver.OnPreDrawListener() {
@@ -96,7 +98,17 @@
                     mRoundRectRadius);
         }
     };
-    private NotificationGroupManager mGroupManager;
+    private OnClickListener mExpandClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
+                mGroupManager.toggleGroupExpansion(mStatusBarNotification);
+            } else {
+                mContainingNotification.setUserExpanded(!mContainingNotification.isExpanded());
+                mContainingNotification.notifyHeightChanged(true);
+            }
+        }
+    };
 
     public NotificationContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -488,6 +500,10 @@
         updateSingleLineView();
     }
 
+    public void setContainingNotification(ExpandableNotificationRow notification) {
+        mContainingNotification = notification;
+    }
+
     public void setStatusBarNotification(StatusBarNotification statusBarNotification) {
         mStatusBarNotification = statusBarNotification;
         updateSingleLineView();
@@ -515,4 +531,19 @@
     public void setGroupManager(NotificationGroupManager groupManager) {
         mGroupManager = groupManager;
     }
+
+    public void updateExpandButtons() {
+        if (mExpandedChild != null) {
+            mExpandedWrapper.updateExpandability(mContainingNotification.isExpandable(),
+                    mExpandClickListener);
+        }
+        if (mContractedChild != null) {
+            mContractedWrapper.updateExpandability(mContainingNotification.isExpandable(),
+                    mExpandClickListener);
+        }
+        if (mHeadsUpChild != null) {
+            mHeadsUpWrapper.updateExpandability(mContainingNotification.isExpandable(),
+                    mExpandClickListener);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java
index af6ccd8..dff3500 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java
@@ -26,9 +26,12 @@
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.ImageView;
@@ -38,6 +41,8 @@
 import com.android.systemui.ViewInvertHelper;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
 
+import java.util.ArrayList;
+
 /**
  * Wraps a notification view inflated from a template.
  */
@@ -47,26 +52,32 @@
     private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter(
             0, PorterDuff.Mode.SRC_ATOP);
     private final int mIconDarkAlpha;
-    private final int mIconBackgroundDarkColor;
+    private final int mIconDarkColor;
     private final Interpolator mLinearOutSlowInInterpolator;
 
-    private int mIconBackgroundColor;
+    private int mColor;
     private ViewInvertHelper mInvertHelper;
     private ImageView mIcon;
     protected ImageView mPicture;
 
-    /** Whether the icon needs to be forced grayscale when in dark mode. */
+    /**
+     * Whether the icon needs to be forced grayscale when in dark mode.
+     */
     private boolean mIconForceGraysaleWhenDark;
     private TextView mSubText;
     private TextView mInfoText;
     private View mProfileBadge;
     private View mThirdLineDivider;
     private View mThirdLine;
+    private ImageView mExpandButton;
+    private View mNotificationHeader;
+    private View.OnClickListener mExpandClickListener;
+    private HeaderTouchListener mHeaderTouchListener;
 
     protected NotificationTemplateViewWrapper(Context ctx, View view) {
         super(view);
         mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
-        mIconBackgroundDarkColor =
+        mIconDarkColor =
                 ctx.getColor(R.color.doze_small_icon_background_color);
         mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(ctx,
                 android.R.interpolator.linear_out_slow_in);
@@ -78,16 +89,25 @@
         mInvertHelper = mainColumn != null
                 ? new ViewInvertHelper(mainColumn, NotificationPanelView.DOZE_ANIMATION_DURATION)
                 : null;
-        ImageView largeIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon);
-        ImageView rightIcon = (ImageView) mView.findViewById(com.android.internal.R.id.right_icon);
-        mIcon = resolveIcon(largeIcon, rightIcon);
-        mPicture = resolvePicture(largeIcon);
-        mIconBackgroundColor = resolveBackgroundColor(mIcon);
+        mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon);
+        mPicture = (ImageView) mView.findViewById(com.android.internal.R.id.right_icon);
         mSubText = (TextView) mView.findViewById(com.android.internal.R.id.text);
         mInfoText = (TextView) mView.findViewById(com.android.internal.R.id.info);
         mProfileBadge = mView.findViewById(com.android.internal.R.id.profile_badge_line3);
         mThirdLineDivider = mView.findViewById(com.android.internal.R.id.overflow_divider);
         mThirdLine = mView.findViewById(com.android.internal.R.id.line3);
+        mExpandButton = (ImageView) mView.findViewById(com.android.internal.R.id.expand_button);
+        mColor = resolveColor(mExpandButton);
+        mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
+        // Post to make sure the parent lays out its children before we get their bounds
+        mHeaderTouchListener = new HeaderTouchListener();
+        mExpandButton.post(new Runnable() {
+            @Override
+            public void run() {
+                // let's set up our touch regions
+                mHeaderTouchListener.bindTouchRects(mNotificationHeader, mIcon, mExpandButton);
+            }
+        });
 
         // If the icon already has a color filter, we assume that we already forced the icon to be
         // white when we created the notification.
@@ -95,21 +115,9 @@
         mIconForceGraysaleWhenDark = iconDrawable != null && iconDrawable.getColorFilter() != null;
     }
 
-    private ImageView resolveIcon(ImageView largeIcon, ImageView rightIcon) {
-        return largeIcon != null && largeIcon.getBackground() != null ? largeIcon
-                : rightIcon != null && rightIcon.getVisibility() == View.VISIBLE ? rightIcon
-                : null;
-    }
-
-    private ImageView resolvePicture(ImageView largeIcon) {
-        return largeIcon != null && largeIcon.getBackground() == null
-                ? largeIcon
-                : null;
-    }
-
-    private int resolveBackgroundColor(ImageView icon) {
-        if (icon != null && icon.getBackground() != null) {
-            ColorFilter filter = icon.getBackground().getColorFilter();
+    private int resolveColor(ImageView icon) {
+        if (icon != null && icon.getDrawable() != null) {
+            ColorFilter filter = icon.getDrawable().getColorFilter();
             if (filter instanceof PorterDuffColorFilter) {
                 return ((PorterDuffColorFilter) filter).getColor();
             }
@@ -218,14 +226,14 @@
     }
 
     private void updateIconColorFilter(ImageView target, float intensity) {
-        int color = interpolateColor(mIconBackgroundColor, mIconBackgroundDarkColor, intensity);
+        int color = interpolateColor(mColor, mIconDarkColor, intensity);
         mIconColorFilter.setColor(color);
-        Drawable background = target.getBackground();
+        Drawable iconDrawable = target.getDrawable();
 
         // The background might be null for legacy notifications. Also, the notification might have
         // been modified during the animation, so background might be null here.
-        if (background != null) {
-            background.mutate().setColorFilter(mIconColorFilter);
+        if (iconDrawable != null) {
+            iconDrawable.mutate().setColorFilter(mIconColorFilter);
         }
     }
 
@@ -279,6 +287,13 @@
         }
     }
 
+    @Override
+    public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {
+        mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE);
+        mNotificationHeader.setOnTouchListener(expandable ? mHeaderTouchListener : null);
+        mExpandClickListener = onClickListener;
+    }
+
     private void updateGrayscaleMatrix(float intensity) {
         mGrayscaleColorMatrix.setSaturation(1 - intensity);
     }
@@ -298,4 +313,91 @@
                 (int) (gSource * (1f - t) + gTarget * t),
                 (int) (bSource * (1f - t) + bTarget * t));
     }
+
+    public class HeaderTouchListener implements View.OnTouchListener {
+
+        private final ArrayList<Rect> mTouchRects = new ArrayList<>();
+        private int mTouchSlop;
+        private boolean mTrackGesture;
+        private float mDownX;
+        private float mDownY;
+
+        public HeaderTouchListener() {
+        }
+
+        public void bindTouchRects(View parent, View icon, View expandButton) {
+            mTouchRects.clear();
+            addRectAroundViewView(icon);
+            addRectAroundViewView(expandButton);
+            addInBetweenRect(parent);
+            mTouchSlop = ViewConfiguration.get(parent.getContext()).getScaledTouchSlop();
+        }
+
+        private void addInBetweenRect(View parent) {
+            final Rect r = new Rect();
+            r.top = 0;
+            r.bottom = (int) (32 * parent.getResources().getDisplayMetrics().density);
+            Rect leftRect = mTouchRects.get(0);
+            r.left = leftRect.right;
+            Rect rightRect = mTouchRects.get(1);
+            r.right = rightRect.left;
+            mTouchRects.add(r);
+        }
+
+        private void addRectAroundViewView(View view) {
+            final Rect r = getRectAroundView(view);
+            mTouchRects.add(r);
+        }
+
+        private Rect getRectAroundView(View view) {
+            float size = 48 * view.getResources().getDisplayMetrics().density;
+            final Rect r = new Rect();
+            r.top = (int) ((view.getTop() + view.getBottom()) / 2.0f - size / 2.0f);
+            r.bottom = (int) (r.top + size);
+            r.left = (int) ((view.getLeft() + view.getRight()) / 2.0f - size / 2.0f);
+            r.right = (int) (r.left + size);
+            return r;
+        }
+
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            float x = event.getX();
+            float y = event.getY();
+            switch (event.getActionMasked() & MotionEvent.ACTION_MASK) {
+                case MotionEvent.ACTION_DOWN:
+                    mTrackGesture = false;
+                    if (isInside(x, y)) {
+                        mTrackGesture = true;
+                        return true;
+                    }
+                    break;
+                case MotionEvent.ACTION_MOVE:
+                    if (mTrackGesture) {
+                        if (Math.abs(mDownX - x) > mTouchSlop
+                                || Math.abs(mDownY - y) > mTouchSlop) {
+                            mTrackGesture = false;
+                        }
+                    }
+                    break;
+                case MotionEvent.ACTION_UP:
+                    if (mTrackGesture) {
+                        mExpandClickListener.onClick(mNotificationHeader);
+                    }
+                    break;
+            }
+            return mTrackGesture;
+        }
+
+        private boolean isInside(float x, float y) {
+            for (int i = 0; i < mTouchRects.size(); i++) {
+                Rect r = mTouchRects.get(i);
+                if (r.contains((int) x, (int) y)) {
+                    mDownX = x;
+                    mDownY = y;
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewWrapper.java
index 9bce548..2fb3127 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewWrapper.java
@@ -83,4 +83,12 @@
     public void setSubTextVisible(boolean visible) {
         mSubTextVisible = visible;
     }
+
+    /**
+     * Update the appearance of the expand button.
+     *
+     * @param expandable should this view be expandable
+     * @param onClickListener the listener to invoke when the expand affordance is clicked on
+     */
+    public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {}
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 65ca95b..dba027b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -42,7 +42,7 @@
     private static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
     private static final int MAX_ITEMS_IN_TOP_STACK = 3;
 
-    public static final float DIMMED_SCALE = 0.95f;
+    public static final float DIMMED_SCALE = 0.98f;
 
     private int mPaddingBetweenElements;
     private int mCollapsedSize;