Split the reply icon permanently from the right icon

Previously these would overlap, but they are now completely
separate.

Test: ensure that all notification styles still work with the new affordance.
Change-Id: I16f5f863b4afac27494a4a7615631bca240ca532
Fixes: 72750728
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4f88a03..a69bd8d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4278,7 +4278,6 @@
 
         private void resetStandardTemplate(RemoteViews contentView) {
             resetNotificationHeader(contentView);
-            resetContentMargins(contentView);
             contentView.setViewVisibility(R.id.right_icon, View.GONE);
             contentView.setViewVisibility(R.id.title, View.GONE);
             contentView.setTextViewText(R.id.title, null);
@@ -4310,24 +4309,23 @@
             mN.mUsesStandardHeader = false;
         }
 
-        private void resetContentMargins(RemoteViews contentView) {
-            contentView.setViewLayoutMarginEndDimen(R.id.line1, 0);
-            contentView.setViewLayoutMarginEndDimen(R.id.text, 0);
-        }
-
-        private RemoteViews applyStandardTemplate(int resId) {
-            return applyStandardTemplate(resId, mParams.reset().fillTextsFrom(this));
+        private RemoteViews applyStandardTemplate(int resId, TemplateBindResult result) {
+            return applyStandardTemplate(resId, mParams.reset().fillTextsFrom(this),
+                    result);
         }
 
         /**
          * @param hasProgress whether the progress bar should be shown and set
+         * @param result
          */
-        private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
+        private RemoteViews applyStandardTemplate(int resId, boolean hasProgress,
+                TemplateBindResult result) {
             return applyStandardTemplate(resId, mParams.reset().hasProgress(hasProgress)
-                    .fillTextsFrom(this));
+                    .fillTextsFrom(this), result);
         }
 
-        private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p) {
+        private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p,
+                TemplateBindResult result) {
             RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
 
             resetStandardTemplate(contentView);
@@ -4335,7 +4333,7 @@
             final Bundle ex = mN.extras;
             updateBackgroundColor(contentView);
             bindNotificationHeader(contentView, p.ambient, p.headerTextSecondary);
-            bindLargeIcon(contentView, p.hideLargeIcon || p.ambient, p.alwaysShowReply);
+            bindLargeIconAndReply(contentView, p, result);
             boolean showProgress = handleProgressBar(p.hasProgress, contentView, ex);
             if (p.title != null) {
                 contentView.setViewVisibility(R.id.title, View.VISIBLE);
@@ -4531,8 +4529,31 @@
             }
         }
 
-        private void bindLargeIcon(RemoteViews contentView, boolean hideLargeIcon,
-                boolean alwaysShowReply) {
+        private void bindLargeIconAndReply(RemoteViews contentView, StandardTemplateParams p,
+                TemplateBindResult result) {
+            boolean largeIconShown = bindLargeIcon(contentView, p.hideLargeIcon || p.ambient);
+            boolean showReplyIcon = bindReplyIcon(contentView, p.hideReplyIcon || p.ambient);
+            contentView.setViewVisibility(R.id.right_icon_container,
+                    largeIconShown || showReplyIcon ? View.VISIBLE : View.GONE);
+            int marginEndDimen = 0;
+            if (largeIconShown && showReplyIcon) {
+                marginEndDimen = R.dimen.notification_content_picture_and_reply_margin;
+            } else if (largeIconShown || showReplyIcon) {
+                marginEndDimen = R.dimen.notification_content_picture_margin;
+            }
+            contentView.setViewLayoutMarginEndDimen(R.id.line1, marginEndDimen);
+            contentView.setViewLayoutMarginEndDimen(R.id.text, marginEndDimen);
+            contentView.setViewLayoutMarginEndDimen(R.id.progress, marginEndDimen);
+            if (result != null) {
+                result.setIconMarginEndDimen(marginEndDimen);
+            }
+        }
+
+        /**
+         * Bind the large icon.
+         * @return if the largeIcon is visible
+         */
+        private boolean bindLargeIcon(RemoteViews contentView, boolean hideLargeIcon) {
             if (mN.mLargeIcon == null && mN.largeIcon != null) {
                 mN.mLargeIcon = Icon.createWithBitmap(mN.largeIcon);
             }
@@ -4541,51 +4562,35 @@
                 contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
                 contentView.setImageViewIcon(R.id.right_icon, mN.mLargeIcon);
                 processLargeLegacyIcon(mN.mLargeIcon, contentView);
-                int endMargin = R.dimen.notification_content_picture_margin;
-                contentView.setViewLayoutMarginEndDimen(R.id.line1, endMargin);
-                contentView.setViewLayoutMarginEndDimen(R.id.text, endMargin);
-                contentView.setViewLayoutMarginEndDimen(R.id.progress, endMargin);
             }
-            // Bind the reply action
-            Action action = findReplyAction();
+            return showLargeIcon;
+        }
 
-            boolean actionVisible = action != null && (showLargeIcon || alwaysShowReply);
-            int replyId = showLargeIcon ? R.id.reply_icon_action : R.id.right_icon;
+        /**
+         * Bind the reply icon.
+         * @return if the reply icon is visible
+         */
+        private boolean bindReplyIcon(RemoteViews contentView, boolean hideReplyIcon) {
+            boolean actionVisible = !hideReplyIcon;
+            Action action = null;
             if (actionVisible) {
-                // We're only showing the icon as big if we're hiding the large icon
-                int contrastColor = resolveContrastColor();
-                int iconColor;
-                if (showLargeIcon) {
-                    contentView.setDrawableTint(R.id.reply_icon_action,
-                            true /* targetBackground */,
-                            contrastColor, PorterDuff.Mode.SRC_ATOP);
-                    contentView.setOnClickPendingIntent(R.id.right_icon,
-                            action.actionIntent);
-                    contentView.setRemoteInputs(R.id.right_icon, action.mRemoteInputs);
-                    iconColor = NotificationColorUtil.isColorLight(contrastColor)
-                            ? Color.BLACK : Color.WHITE;
-                } else {
-                    contentView.setImageViewResource(R.id.right_icon,
-                            R.drawable.ic_reply_notification_large);
-                    contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
-                    iconColor = contrastColor;
-                }
-                contentView.setDrawableTint(replyId,
-                        false /* targetBackground */,
-                        iconColor,
-                        PorterDuff.Mode.SRC_ATOP);
-                contentView.setOnClickPendingIntent(replyId,
-                        action.actionIntent);
-                contentView.setRemoteInputs(replyId, action.mRemoteInputs);
-            } else {
-                contentView.setRemoteInputs(R.id.right_icon, null);
+                action = findReplyAction();
+                actionVisible = action != null;
             }
-            contentView.setViewVisibility(R.id.reply_icon_action, actionVisible && showLargeIcon
-                    ? View.VISIBLE
-                    : View.GONE);
-            contentView.setViewVisibility(R.id.right_icon_container, actionVisible || showLargeIcon
-                    ? View.VISIBLE
-                    : View.GONE);
+            if (actionVisible) {
+                contentView.setViewVisibility(R.id.reply_icon_action, View.VISIBLE);
+                contentView.setDrawableTint(R.id.reply_icon_action,
+                        false /* targetBackground */,
+                        getPrimaryTextColor(),
+                        PorterDuff.Mode.SRC_ATOP);
+                contentView.setOnClickPendingIntent(R.id.reply_icon_action, action.actionIntent);
+                contentView.setRemoteInputs(R.id.reply_icon_action, action.mRemoteInputs);
+            } else {
+                contentView.setRemoteInputs(R.id.reply_icon_action, null);
+            }
+            contentView.setViewVisibility(R.id.reply_icon_action,
+                    actionVisible ? View.VISIBLE : View.GONE);
+            return actionVisible;
         }
 
         private Action findReplyAction() {
@@ -4770,13 +4775,15 @@
                     R.dimen.notification_content_margin);
         }
 
-        private RemoteViews applyStandardTemplateWithActions(int layoutId) {
-            return applyStandardTemplateWithActions(layoutId, mParams.reset().fillTextsFrom(this));
+        private RemoteViews applyStandardTemplateWithActions(int layoutId,
+                TemplateBindResult result) {
+            return applyStandardTemplateWithActions(layoutId, mParams.reset().fillTextsFrom(this),
+                    result);
         }
 
         private RemoteViews applyStandardTemplateWithActions(int layoutId,
-            StandardTemplateParams p) {
-            RemoteViews big = applyStandardTemplate(layoutId, p);
+                StandardTemplateParams p, TemplateBindResult result) {
+            RemoteViews big = applyStandardTemplate(layoutId, p, result);
 
             resetStandardTemplateWithActions(big);
 
@@ -4883,7 +4890,7 @@
                     return styleView;
                 }
             }
-            return applyStandardTemplate(getBaseLayoutResource());
+            return applyStandardTemplate(getBaseLayoutResource(), null /* result */);
         }
 
         private boolean useExistingRemoteView() {
@@ -4902,7 +4909,8 @@
                 result = mStyle.makeBigContentView();
                 hideLine1Text(result);
             } else if (mActions.size() != 0) {
-                result = applyStandardTemplateWithActions(getBigBaseLayoutResource());
+                result = applyStandardTemplateWithActions(getBigBaseLayoutResource(),
+                        null /* result */);
             }
             makeHeaderExpanded(result);
             return result;
@@ -4939,7 +4947,8 @@
         public RemoteViews makeAmbientNotification() {
             RemoteViews ambient = applyStandardTemplateWithActions(
                     R.layout.notification_template_material_ambient,
-                    mParams.reset().ambient(true).fillTextsFrom(this).hasProgress(false));
+                    mParams.reset().ambient(true).fillTextsFrom(this).hasProgress(false),
+                    null /* result */);
             return ambient;
         }
 
@@ -4982,7 +4991,7 @@
                 return null;
             }
 
-            return applyStandardTemplateWithActions(getBigBaseLayoutResource());
+            return applyStandardTemplateWithActions(getBigBaseLayoutResource(), null /* result */);
         }
 
         /**
@@ -5863,6 +5872,18 @@
         }
 
         protected RemoteViews getStandardView(int layoutId) {
+            return getStandardView(layoutId, null);
+        }
+
+        /**
+         * Get the standard view for this style.
+         *
+         * @param layoutId The layout id to use
+         * @param result The result where template bind information is saved.
+         * @return A remoteView for this style.
+         * @hide
+         */
+        protected RemoteViews getStandardView(int layoutId, TemplateBindResult result) {
             checkBuilder();
 
             // Nasty.
@@ -5872,7 +5893,7 @@
                 mBuilder.setContentTitle(mBigContentTitle);
             }
 
-            RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId);
+            RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId, result);
 
             mBuilder.getAllExtras().putCharSequence(EXTRA_TITLE, oldBuilderContentTitle);
 
@@ -6169,7 +6190,8 @@
                 mBuilder.mN.largeIcon = null;
             }
 
-            RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource());
+            RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource(),
+                    null /* result */);
             if (mSummaryTextSet) {
                 contentView.setTextViewText(R.id.text, mBuilder.processTextSpans(
                         mBuilder.processLegacyText(mSummaryText)));
@@ -6356,7 +6378,9 @@
             CharSequence text = mBuilder.getAllExtras().getCharSequence(EXTRA_TEXT);
             mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
 
-            RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
+            TemplateBindResult result = new TemplateBindResult();
+            RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource(), result);
+            contentView.setInt(R.id.big_text, "setImageEndMarginDimen", result.getIconMarginEndDimen());
 
             mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, text);
 
@@ -6739,7 +6763,7 @@
             mBuilder.mOriginalActions = mBuilder.mActions;
             mBuilder.mActions = new ArrayList<>();
             RemoteViews remoteViews = makeMessagingView(true /* displayImagesAtEnd */,
-                    true /* showReplyIcon */);
+                    false /* hideLargeIcon */);
             mBuilder.mActions = mBuilder.mOriginalActions;
             mBuilder.mOriginalActions = null;
             return remoteViews;
@@ -6826,7 +6850,7 @@
          */
         @Override
         public RemoteViews makeBigContentView() {
-            return makeMessagingView(false /* displayImagesAtEnd */, false /* showReplyIcon */);
+            return makeMessagingView(false /* displayImagesAtEnd */, true /* hideLargeIcon */);
         }
 
         /**
@@ -6834,11 +6858,11 @@
          *
          * @param displayImagesAtEnd should images be displayed at the end of the content instead
          *                           of inline.
-         * @param showReplyIcon Should the reply affordance be shown at the end of the notification
+         * @param hideRightIcons Should the reply affordance be shown at the end of the notification
          * @return the created remoteView.
          */
         @NonNull
-        private RemoteViews makeMessagingView(boolean displayImagesAtEnd, boolean showReplyIcon) {
+        private RemoteViews makeMessagingView(boolean displayImagesAtEnd, boolean hideRightIcons) {
             CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle)
                     ? super.mBigContentTitle
                     : mConversationTitle;
@@ -6849,20 +6873,18 @@
                 nameReplacement = conversationTitle;
                 conversationTitle = null;
             }
-            boolean hideLargeIcon = !showReplyIcon || isOneToOne;
+            TemplateBindResult bindResult = new TemplateBindResult();
             RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
                     mBuilder.getMessagingLayoutResource(),
                     mBuilder.mParams.reset().hasProgress(false).title(conversationTitle).text(null)
-                            .hideLargeIcon(hideLargeIcon)
-                            .headerTextSecondary(conversationTitle)
-                            .alwaysShowReply(showReplyIcon));
+                            .hideLargeIcon(hideRightIcons || isOneToOne)
+                            .hideReplyIcon(hideRightIcons)
+                            .headerTextSecondary(conversationTitle),
+                    bindResult);
             addExtras(mBuilder.mN.extras);
             // also update the end margin if there is an image
-            int endMargin = R.dimen.notification_content_margin_end;
-            if (showReplyIcon) {
-                endMargin = R.dimen.notification_content_plus_picture_margin_end;
-            }
-            contentView.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
+            contentView.setViewLayoutMarginEndDimen(R.id.notification_main_column,
+                    bindResult.getIconMarginEndDimen());
             contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor",
                     mBuilder.resolveContrastColor());
             contentView.setBoolean(R.id.status_bar_latest_event_content, "setDisplayImagesAtEnd",
@@ -6934,7 +6956,7 @@
         @Override
         public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
             RemoteViews remoteViews = makeMessagingView(true /* displayImagesAtEnd */,
-                    false /* showReplyIcon */);
+                    true /* hideLargeIcon */);
             remoteViews.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1);
             return remoteViews;
         }
@@ -7275,7 +7297,8 @@
             CharSequence oldBuilderContentText = mBuilder.mN.extras.getCharSequence(EXTRA_TEXT);
             mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
 
-            RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource());
+            TemplateBindResult result = new TemplateBindResult();
+            RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource(), result);
 
             mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, oldBuilderContentText);
 
@@ -7304,7 +7327,8 @@
                             mBuilder.processTextSpans(mBuilder.processLegacyText(str)));
                     mBuilder.setTextViewColorSecondary(contentView, rowIds[i]);
                     contentView.setViewPadding(rowIds[i], 0, topPadding, 0, 0);
-                    handleInboxImageMargin(contentView, rowIds[i], first);
+                    handleInboxImageMargin(contentView, rowIds[i], first,
+                            result.getIconMarginEndDimen());
                     if (first) {
                         onlyViewId = rowIds[i];
                     } else {
@@ -7336,14 +7360,15 @@
             return !Objects.equals(getLines(), newS.getLines());
         }
 
-        private void handleInboxImageMargin(RemoteViews contentView, int id, boolean first) {
+        private void handleInboxImageMargin(RemoteViews contentView, int id, boolean first,
+                int marginEndDimen) {
             int endMargin = 0;
             if (first) {
                 final int max = mBuilder.mN.extras.getInt(EXTRA_PROGRESS_MAX, 0);
                 final boolean ind = mBuilder.mN.extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
                 boolean hasProgress = max != 0 || ind;
-                if (mBuilder.mN.hasLargeIcon() && !hasProgress) {
-                    endMargin = R.dimen.notification_content_picture_margin;
+                if (!hasProgress) {
+                    endMargin = marginEndDimen;
                 }
             }
             contentView.setViewLayoutMarginEndDimen(id, endMargin);
@@ -7535,7 +7560,8 @@
 
         private RemoteViews makeMediaContentView() {
             RemoteViews view = mBuilder.applyStandardTemplate(
-                    R.layout.notification_template_material_media, false /* hasProgress */);
+                    R.layout.notification_template_material_media, false, /* hasProgress */
+                    null /* result */);
 
             final int numActions = mBuilder.mActions.size();
             final int N = mActionsToShowInCompact == null
@@ -7559,7 +7585,7 @@
             // handle the content margin
             int endMargin = R.dimen.notification_content_margin_end;
             if (mBuilder.mN.hasLargeIcon()) {
-                endMargin = R.dimen.notification_content_plus_picture_margin_end;
+                endMargin = R.dimen.notification_media_image_margin_end;
             }
             view.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
             return view;
@@ -7580,8 +7606,7 @@
                 return null;
             }
             RemoteViews big = mBuilder.applyStandardTemplate(
-                    R.layout.notification_template_material_big_media,
-                    false);
+                    R.layout.notification_template_material_big_media, false, null /* result */);
 
             if (actionCount > 0) {
                 big.removeAllViews(com.android.internal.R.id.media_actions);
@@ -7677,16 +7702,18 @@
             if (mBuilder.mActions.size() == 0) {
                return makeStandardTemplateWithCustomContent(headsUpContentView);
             }
+            TemplateBindResult result = new TemplateBindResult();
             RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
-                        mBuilder.getBigBaseLayoutResource());
-            buildIntoRemoteViewContent(remoteViews, headsUpContentView);
+                        mBuilder.getBigBaseLayoutResource(), result);
+            buildIntoRemoteViewContent(remoteViews, headsUpContentView, result);
             return remoteViews;
         }
 
         private RemoteViews makeStandardTemplateWithCustomContent(RemoteViews customContent) {
+            TemplateBindResult result = new TemplateBindResult();
             RemoteViews remoteViews = mBuilder.applyStandardTemplate(
-                    mBuilder.getBaseLayoutResource());
-            buildIntoRemoteViewContent(remoteViews, customContent);
+                    mBuilder.getBaseLayoutResource(), result);
+            buildIntoRemoteViewContent(remoteViews, customContent, result);
             return remoteViews;
         }
 
@@ -7697,14 +7724,15 @@
             if (mBuilder.mActions.size() == 0) {
                 return makeStandardTemplateWithCustomContent(bigContentView);
             }
+            TemplateBindResult result = new TemplateBindResult();
             RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
-                    mBuilder.getBigBaseLayoutResource());
-            buildIntoRemoteViewContent(remoteViews, bigContentView);
+                    mBuilder.getBigBaseLayoutResource(), result);
+            buildIntoRemoteViewContent(remoteViews, bigContentView, result);
             return remoteViews;
         }
 
         private void buildIntoRemoteViewContent(RemoteViews remoteViews,
-                RemoteViews customContent) {
+                RemoteViews customContent, TemplateBindResult result) {
             if (customContent != null) {
                 // Need to clone customContent before adding, because otherwise it can no longer be
                 // parceled independently of remoteViews.
@@ -7714,11 +7742,14 @@
                 remoteViews.setReapplyDisallowed();
             }
             // also update the end margin if there is an image
-            int endMargin = R.dimen.notification_content_margin_end;
-            if (mBuilder.mN.hasLargeIcon()) {
-                endMargin = R.dimen.notification_content_plus_picture_margin_end;
+            Resources resources = mBuilder.mContext.getResources();
+            int endMargin = resources.getDimensionPixelSize(
+                    R.dimen.notification_content_margin_end);
+            int marginEndDimen = result.getIconMarginEndDimen();
+            if (marginEndDimen != 0) {
+                endMargin += resources.getDimensionPixelSize(marginEndDimen);
             }
-            remoteViews.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
+            remoteViews.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin);
         }
 
         /**
@@ -9322,6 +9353,25 @@
         }
     }
 
+    /**
+     * A result object where information about the template that was created is saved.
+     */
+    private static class TemplateBindResult {
+        int mIconMarginEndDimen;
+
+        /**
+         * Get the margin end dimension that needs to be added to any fields that may overlap
+         * with the right actions.
+         */
+        public int getIconMarginEndDimen() {
+            return mIconMarginEndDimen;
+        }
+
+        public void setIconMarginEndDimen(int iconMarginEndDimen) {
+            this.mIconMarginEndDimen = iconMarginEndDimen;
+        }
+    }
+
     private static class StandardTemplateParams {
         boolean hasProgress = true;
         boolean ambient = false;
@@ -9329,7 +9379,7 @@
         CharSequence text;
         CharSequence headerTextSecondary;
         boolean hideLargeIcon;
-        public boolean alwaysShowReply;
+        boolean hideReplyIcon;
 
         final StandardTemplateParams reset() {
             hasProgress = true;
@@ -9360,13 +9410,13 @@
             return this;
         }
 
-        final StandardTemplateParams alwaysShowReply(boolean alwaysShowReply) {
-            this.alwaysShowReply = alwaysShowReply;
+        final StandardTemplateParams hideLargeIcon(boolean hideLargeIcon) {
+            this.hideLargeIcon = hideLargeIcon;
             return this;
         }
 
-        final StandardTemplateParams hideLargeIcon(boolean hideLargeIcon) {
-            this.hideLargeIcon = hideLargeIcon;
+        final StandardTemplateParams hideReplyIcon(boolean hideReplyIcon) {
+            this.hideReplyIcon = hideReplyIcon;
             return this;
         }