Merge changes I66f2c52b,I95f72c9d into oc-dr1-dev

* changes:
  Fixed the accessibility of the reply button
  Avoiding weird icon positions
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index aa4e05b..fbf7538 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -26,8 +26,9 @@
                android:layout_gravity="top|end"
                android:layout_marginTop="36dp"
                android:layout_marginEnd="@dimen/notification_content_margin_end"
-               android:scaleType="centerCrop"/>
-    <ImageView android:id="@+id/reply_icon_action"
+               android:scaleType="centerCrop"
+               android:importantForAccessibility="no" />
+    <ImageButton android:id="@+id/reply_icon_action"
                android:layout_width="16dp"
                android:layout_height="16dp"
                android:layout_gravity="top|end"
@@ -36,6 +37,7 @@
                android:background="@drawable/notification_reply_background"
                android:src="@drawable/ic_reply_notification"
                android:scaleType="center"
+               android:contentDescription="@string/notification_reply_button_accessibility"
                visiblity="gone"/>
 </FrameLayout>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ce701a7..bd8e14ea 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4713,6 +4713,9 @@
     <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for test -->
     <string name="etws_primary_default_message_test">Emergency messages test</string>
 
+    <!-- Content description for the reply button in the notification area [CHAR LIMIT=NONE]-->
+    <string name="notification_reply_button_accessibility">Reply</string>
+
     <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for others -->
     <string name="etws_primary_default_message_others"></string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 97e2f6d..7abceaf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -16,15 +16,18 @@
 
 package com.android.systemui.statusbar;
 
+import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState.NO_VALUE;
+import static com.android.systemui.statusbar.phone.NotificationIconContainer.OVERFLOW_EARLY_AMOUNT;
+
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.SystemProperties;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityNodeInfo;
+
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.ViewInvertHelper;
@@ -315,26 +318,65 @@
     private float updateIconAppearance(ExpandableNotificationRow row, float expandAmount,
             boolean scrolling, boolean scrollingFast, boolean expandingAnimated,
             boolean isLastChild) {
+        StatusBarIconView icon = row.getEntry().expandedIcon;
+        NotificationIconContainer.IconState iconState = getIconState(icon);
+        if (iconState == null) {
+            return 0.0f;
+        }
+
         // Let calculate how much the view is in the shelf
         float viewStart = row.getTranslationY();
         int fullHeight = row.getActualHeight() + mPaddingBetweenElements;
         float iconTransformDistance = getIntrinsicHeight() * 1.5f;
         iconTransformDistance *= NotificationUtils.interpolate(1.f, 1.5f, expandAmount);
+        iconTransformDistance = Math.min(iconTransformDistance, fullHeight);
         if (isLastChild) {
             fullHeight = Math.min(fullHeight, row.getMinHeight() - getIntrinsicHeight());
             iconTransformDistance = Math.min(iconTransformDistance, row.getMinHeight()
                     - getIntrinsicHeight());
         }
         float viewEnd = viewStart + fullHeight;
+        if (expandingAnimated && mAmbientState.getScrollY() == 0
+                && !mAmbientState.isOnKeyguard() && !iconState.isLastExpandIcon) {
+            // We are expanding animated. Because we switch to a linear interpolation in this case,
+            // the last icon may be stuck in between the shelf position and the notification
+            // position, which looks pretty bad. We therefore optimize this case by applying a
+            // shorter transition such that the icon is either fully in the notification or we clamp
+            // it into the shelf if it's close enough.
+            // We need to persist this, since after the expansion, the behavior should still be the
+            // same.
+            float position = mAmbientState.getIntrinsicPadding()
+                    + mHostLayout.getPositionInLinearLayout(row);
+            int maxShelfStart = mMaxLayoutHeight - getIntrinsicHeight();
+            if (position < maxShelfStart && position + row.getIntrinsicHeight() >= maxShelfStart
+                    && row.getTranslationY() < position) {
+                iconState.isLastExpandIcon = true;
+                iconState.customTransformHeight = NO_VALUE;
+                // Let's check if we're close enough to snap into the shelf
+                boolean forceInShelf = mMaxLayoutHeight - getIntrinsicHeight() - position
+                        < getIntrinsicHeight();
+                if (!forceInShelf) {
+                    // We are overlapping the shelf but not enough, so the icon needs to be
+                    // repositioned
+                    iconState.customTransformHeight = (int) (mMaxLayoutHeight
+                            - getIntrinsicHeight() - position);
+                }
+            }
+        }
         float fullTransitionAmount;
         float iconTransitionAmount;
         float shelfStart = getTranslationY();
+        if (iconState.hasCustomTransformHeight()) {
+            fullHeight = iconState.customTransformHeight;
+            iconTransformDistance = iconState.customTransformHeight;
+        }
+        boolean fullyInOrOut = true;
         if (viewEnd >= shelfStart && (!mAmbientState.isUnlockHintRunning() || row.isInShelf())
                 && (mAmbientState.isShadeExpanded()
                         || (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) {
             if (viewStart < shelfStart) {
-
                 float fullAmount = (shelfStart - viewStart) / fullHeight;
+                fullAmount = Math.min(1.0f, fullAmount);
                 float interpolatedAmount =  Interpolators.ACCELERATE_DECELERATE.getInterpolation(
                         fullAmount);
                 interpolatedAmount = NotificationUtils.interpolate(
@@ -344,7 +386,7 @@
                 iconTransitionAmount = (shelfStart - viewStart) / iconTransformDistance;
                 iconTransitionAmount = Math.min(1.0f, iconTransitionAmount);
                 iconTransitionAmount = 1.0f - iconTransitionAmount;
-
+                fullyInOrOut = false;
             } else {
                 fullTransitionAmount = 1.0f;
                 iconTransitionAmount = 1.0f;
@@ -353,6 +395,10 @@
             fullTransitionAmount = 0.0f;
             iconTransitionAmount = 0.0f;
         }
+        if (fullyInOrOut && !expandingAnimated && iconState.isLastExpandIcon) {
+            iconState.isLastExpandIcon = false;
+            iconState.customTransformHeight = NO_VALUE;
+        }
         updateIconPositioning(row, iconTransitionAmount, fullTransitionAmount,
                 iconTransformDistance, scrolling, scrollingFast, expandingAnimated, isLastChild);
         return fullTransitionAmount;
@@ -366,9 +412,10 @@
         if (iconState == null) {
             return;
         }
+        boolean forceInShelf = iconState.isLastExpandIcon && !iconState.hasCustomTransformHeight();
         float clampedAmount = iconTransitionAmount > 0.5f ? 1.0f : 0.0f;
         if (clampedAmount == fullTransitionAmount) {
-            iconState.noAnimations = scrollingFast || expandingAnimated;
+            iconState.noAnimations = (scrollingFast || expandingAnimated) && !forceInShelf;
             iconState.useFullTransitionAmount = iconState.noAnimations
                 || (!ICON_ANMATIONS_WHILE_SCROLLING && fullTransitionAmount == 0.0f && scrolling);
             iconState.useLinearTransitionAmount = !ICON_ANMATIONS_WHILE_SCROLLING
@@ -376,12 +423,18 @@
             iconState.translateContent = mMaxLayoutHeight - getTranslationY()
                     - getIntrinsicHeight() > 0;
         }
-        if (scrollingFast || (expandingAnimated && iconState.useFullTransitionAmount
-                && !ViewState.isAnimatingY(icon))) {
+        if (!forceInShelf && (scrollingFast || (expandingAnimated
+                && iconState.useFullTransitionAmount && !ViewState.isAnimatingY(icon)))) {
             iconState.cancelAnimations(icon);
             iconState.useFullTransitionAmount = true;
             iconState.noAnimations = true;
         }
+        if (iconState.hasCustomTransformHeight()) {
+            iconState.useFullTransitionAmount = true;
+        }
+        if (iconState.isLastExpandIcon) {
+            iconState.translateContent = false;
+        }
         float transitionAmount;
         if (isLastChild || !USE_ANIMATIONS_WHEN_OPENING || iconState.useFullTransitionAmount
                 || iconState.useLinearTransitionAmount) {
@@ -548,8 +601,7 @@
         if (!hasOverflow) {
             // we have to ensure that adding the low priority notification won't lead to an
             // overflow
-            collapsedPadding -= (1.0f + NotificationIconContainer.OVERFLOW_EARLY_AMOUNT)
-                    * mCollapsedIcons.getIconSize();
+            collapsedPadding -= (1.0f + OVERFLOW_EARLY_AMOUNT) * mCollapsedIcons.getIconSize();
         }
         float padding = NotificationUtils.interpolate(collapsedPadding,
                 mShelfIcons.getPaddingEnd(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 021e11a..6f5ad96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -526,6 +526,7 @@
     }
 
     public class IconState extends ViewState {
+        public static final int NO_VALUE = NotificationIconContainer.NO_VALUE;
         public float iconAppearAmount = 1.0f;
         public float clampedAppearAmount = 1.0f;
         public int visibleState;
@@ -538,6 +539,8 @@
         public boolean justUndarkened;
         public int iconColor = StatusBarIconView.NO_COLOR;
         public boolean noAnimations;
+        public boolean isLastExpandIcon;
+        public int customTransformHeight = NO_VALUE;
 
         @Override
         public void applyToView(View view) {
@@ -615,6 +618,10 @@
             justUndarkened = false;
         }
 
+        public boolean hasCustomTransformHeight() {
+            return isLastExpandIcon && customTransformHeight != NO_VALUE;
+        }
+
         @Override
         public void initFrom(View view) {
             super.initFrom(view);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index b7b991e..ba1e7c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -62,6 +62,7 @@
     private boolean mHasPulsingNotifications;
     private boolean mUnlockHintRunning;
     private boolean mQsCustomizerShowing;
+    private int mIntrinsicPadding;
 
     public AmbientState(Context context) {
         reload(context);
@@ -323,4 +324,12 @@
     public void setQsCustomizerShowing(boolean qsCustomizerShowing) {
         mQsCustomizerShowing = qsCustomizerShowing;
     }
+
+    public void setIntrinsicPadding(int intrinsicPadding) {
+        mIntrinsicPadding = intrinsicPadding;
+    }
+
+    public int getIntrinsicPadding() {
+        return mIntrinsicPadding;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index cbd315b..41cde9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2735,7 +2735,7 @@
         return view.getHeight();
     }
 
-    private int getPositionInLinearLayout(View requestedView) {
+    public int getPositionInLinearLayout(View requestedView) {
         ExpandableNotificationRow childInGroup = null;
         ExpandableNotificationRow requestedRow = null;
         if (isChildInGroup(requestedView)) {
@@ -3650,6 +3650,7 @@
 
     public void setIntrinsicPadding(int intrinsicPadding) {
         mIntrinsicPadding = intrinsicPadding;
+        mAmbientState.setIntrinsicPadding(intrinsicPadding);
     }
 
     public int getIntrinsicPadding() {