Merge "Add Usage info for LocationManager's APIs" into qt-dev am: 11ddc8ea0b
am: 4e5d2a48c1

Change-Id: If405ba5cc7ba7507455ffc6f506c23e2d92f768e
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 54d2d93..d304b7e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -62,12 +62,10 @@
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-vianetsintää ei sallita"</string>
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Laitteelle tällä hetkellä kirjautunut käyttäjä ei voi ottaa USB-vianetsintää käyttöön. Vaihda käyttäjäksi ensisijainen käyttäjä, jotta voit käyttää tätä ominaisuutta."</string>
     <string name="usb_contaminant_title" msgid="206854874263058490">"USB-portti poistettu käytöstä"</string>
-    <!-- no translation found for usb_contaminant_message (7379089091591609111) -->
-    <skip />
+    <string name="usb_contaminant_message" msgid="7379089091591609111">"Laitteen suojaamiseksi nesteiltä ja lialta USB-portti on poistettu käytöstä, eikä se havaitse lisävarusteita.\n\nSaat ilmoituksen, kun USB-porttia voi taas käyttää."</string>
     <string name="usb_port_enabled" msgid="7906141351687694867">"USB-portti on käytössä ja voi havaita latureita sekä lisävarusteita"</string>
     <string name="usb_disable_contaminant_detection" msgid="2103905315747120033">"Ota USB käyttöön"</string>
-    <!-- no translation found for learn_more (5000517160980853569) -->
-    <skip />
+    <string name="learn_more" msgid="5000517160980853569">"Lue lisää"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomaa koko näyttöön"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venytä koko näyttöön"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Kuvakaappaus"</string>
@@ -458,10 +456,8 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Älä näytä uudelleen"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Poista kaikki"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"Muuta asetuksia"</string>
-    <!-- no translation found for notification_section_header_gentle (4372438504154095677) -->
-    <skip />
-    <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4286716295850400959) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="4372438504154095677">"Hiljaiset ilmoitukset"</string>
+    <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Tyhjennä kaikki hiljaiset ilmoitukset"</string>
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Älä häiritse ‑tila keskeytti ilmoitukset"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Aloita nyt"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Ei ilmoituksia"</string>
@@ -645,11 +641,9 @@
     <string name="inline_block_button" msgid="8735843688021655065">"Estä"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Jatka näyttämistä"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Pienennä"</string>
-    <!-- no translation found for inline_silent_button_silent (5315879183296940969) -->
-    <skip />
+    <string name="inline_silent_button_silent" msgid="5315879183296940969">"Äänetön"</string>
     <string name="inline_silent_button_stay_silent" msgid="6308371431217601009">"Jatka äänettömyyttä"</string>
-    <!-- no translation found for inline_silent_button_alert (6008435419895088034) -->
-    <skip />
+    <string name="inline_silent_button_alert" msgid="6008435419895088034">"Hälyttää"</string>
     <string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"Jatka ilmoituksista hälyttämistä"</string>
     <string name="inline_turn_off_notifications" msgid="8635596135532202355">"Poista ilmoitukset käytöstä"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Jatketaanko ilmoitusten näyttämistä tästä sovelluksesta?"</string>
@@ -908,8 +902,7 @@
     <string name="slice_permission_allow" msgid="2340244901366722709">"Salli"</string>
     <string name="slice_permission_deny" msgid="7683681514008048807">"Estä"</string>
     <string name="auto_saver_title" msgid="1217959994732964228">"Ajoita virransäästö napauttamalla"</string>
-    <!-- no translation found for auto_saver_text (2563289953551438248) -->
-    <skip />
+    <string name="auto_saver_text" msgid="2563289953551438248">"Ota käyttöön, jos akku todennäköisesti loppuu"</string>
     <string name="no_auto_saver_action" msgid="8086002101711328500">"Ei kiitos"</string>
     <string name="auto_saver_enabled_title" msgid="6726474226058316862">"Virransäästön ajoitus otettu käyttöön"</string>
     <string name="auto_saver_enabled_text" msgid="874711029884777579">"Virransäästö käynnistyy automaattisesti, kun akun lataustaso on alle <xliff:g id="PERCENTAGE">%d</xliff:g> %%."</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 7b2c6d3..b5041a7 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -62,12 +62,10 @@
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ડીબગિંગની મંજૂરી નથી"</string>
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"હાલમાં આ ઉપકરણમાં સાઇન ઇન થયેલ વપરાશકર્તા USB ડિબગીંગ ચાલુ કરી શકતા નથી. આ સુવિધાનો ઉપયોગ કરવા માટે પ્રાથમિક વપરાશકર્તા પર સ્વિચ કરો."</string>
     <string name="usb_contaminant_title" msgid="206854874263058490">"USB પોર્ટ બંધ કરવામાં આવ્યો છે"</string>
-    <!-- no translation found for usb_contaminant_message (7379089091591609111) -->
-    <skip />
+    <string name="usb_contaminant_message" msgid="7379089091591609111">"પ્રવાહી અથવા ધૂળથી તમારા ડિવાઇસનું રક્ષણ કરવા માટે, USB પોર્ટ બંધ કરવામાં આવ્યો છે અને કોઈ ઍક્સેસરી શોધશે નહીં.\n\nજ્યારે ફરીથી USB પોર્ટને ઉપયોગમાં લેવાનું સુરક્ષિત હશે ત્યારે તમને નોટિફિકેશન આપવામાં આવશે."</string>
     <string name="usb_port_enabled" msgid="7906141351687694867">"ચાર્જર અને ઍક્સેસરીની ઓળખ માટે USB પોર્ટ ચાલુ કર્યું"</string>
     <string name="usb_disable_contaminant_detection" msgid="2103905315747120033">"USB ચાલુ કરો"</string>
-    <!-- no translation found for learn_more (5000517160980853569) -->
-    <skip />
+    <string name="learn_more" msgid="5000517160980853569">"વધુ જાણો"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"સ્ક્રીન ભરવા માટે ઝૂમ કરો"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"સ્ક્રીન ભરવા માટે ખેંચો"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"સ્ક્રીનશૉટ"</string>
@@ -458,10 +456,8 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"ફરીથી બતાવશો નહીં"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"બધુ સાફ કરો"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"મેનેજ કરો"</string>
-    <!-- no translation found for notification_section_header_gentle (4372438504154095677) -->
-    <skip />
-    <!-- no translation found for accessibility_notification_section_header_gentle_clear_all (4286716295850400959) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="4372438504154095677">"સાઇલન્ટ નોટિફિકેશન"</string>
+    <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"બધા સાઇલન્ટ નોટિફિકેશન સાફ કરો"</string>
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"ખલેલ પાડશો નહીં દ્વારા થોભાવેલ નોટિફિકેશન"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"હવે પ્રારંભ કરો"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"કોઈ સૂચનાઓ નથી"</string>
@@ -645,11 +641,9 @@
     <string name="inline_block_button" msgid="8735843688021655065">"બ્લૉક કરો"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"બતાવવાનું ચાલુ રાખો"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"નાનું કરો"</string>
-    <!-- no translation found for inline_silent_button_silent (5315879183296940969) -->
-    <skip />
+    <string name="inline_silent_button_silent" msgid="5315879183296940969">"સાઇલન્ટ"</string>
     <string name="inline_silent_button_stay_silent" msgid="6308371431217601009">"સાઇલન્ટ મોડ ચાલુ રાખો"</string>
-    <!-- no translation found for inline_silent_button_alert (6008435419895088034) -->
-    <skip />
+    <string name="inline_silent_button_alert" msgid="6008435419895088034">"અલર્ટ કરતા રહો"</string>
     <string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"અલર્ટ કરવાનું ચાલુ રાખો"</string>
     <string name="inline_turn_off_notifications" msgid="8635596135532202355">"નોટિફિકેશન બંધ કરો"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"આ ઍપમાંથી નોટિફિકેશન બતાવવાનું ચાલુ રાખીએ?"</string>
@@ -908,8 +902,7 @@
     <string name="slice_permission_allow" msgid="2340244901366722709">"મંજૂરી આપો"</string>
     <string name="slice_permission_deny" msgid="7683681514008048807">"નકારો"</string>
     <string name="auto_saver_title" msgid="1217959994732964228">"બૅટરી સેવર શેડ્યૂલ કરવા માટે ટૅપ કરો"</string>
-    <!-- no translation found for auto_saver_text (2563289953551438248) -->
-    <skip />
+    <string name="auto_saver_text" msgid="2563289953551438248">"જ્યારે બૅટરી સંભવિત રૂપે પૂરી થવામાં હોય ત્યારે બૅટરી સેવર ચાલુ કરો"</string>
     <string name="no_auto_saver_action" msgid="8086002101711328500">"ના, આભાર"</string>
     <string name="auto_saver_enabled_title" msgid="6726474226058316862">"બૅટરી સેવર શેડ્યૂલ ચાલુ થયું"</string>
     <string name="auto_saver_enabled_text" msgid="874711029884777579">"બૅટરીનું સ્તર એકવાર <xliff:g id="PERCENTAGE">%d</xliff:g>%% કરતાં ઓછું થાય તે પછી બૅટરી સેવર ઑટોમૅટિક રીતે ચાલુ થશે."</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c04d28a..ae87e1f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1109,8 +1109,8 @@
     <dimen name="bubble_flyout_space_from_bubble">8dp</dimen>
     <!-- Padding around a collapsed bubble -->
     <dimen name="bubble_view_padding">0dp</dimen>
-    <!-- Padding between bubbles when displayed in expanded state -->
-    <dimen name="bubble_padding">8dp</dimen>
+    <!-- Padding between status bar and bubbles when displayed in expanded state -->
+    <dimen name="bubble_padding_top">8dp</dimen>
     <!-- Size of individual bubbles. -->
     <dimen name="individual_bubble_size">52dp</dimen>
     <!-- Size of the circle around the bubbles when they're in the dismiss target. -->
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 014baf8..560e264 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -172,7 +172,7 @@
     private float mVerticalPosPercentBeforeRotation = -1;
 
     private int mBubbleSize;
-    private int mBubblePadding;
+    private int mBubblePaddingTop;
     private int mExpandedViewPadding;
     private int mExpandedAnimateXDistance;
     private int mExpandedAnimateYDistance;
@@ -225,7 +225,7 @@
                 @Override
                 public boolean onPreDraw() {
                     getViewTreeObserver().removeOnPreDrawListener(mViewUpdater);
-                    applyCurrentState();
+                    updateExpandedView();
                     mViewUpdatedRequested = false;
                     return true;
                 }
@@ -302,7 +302,7 @@
 
         Resources res = getResources();
         mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
-        mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding);
+        mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
         mExpandedAnimateXDistance =
                 res.getDimensionPixelSize(R.dimen.bubble_expanded_animate_x_distance);
         mExpandedAnimateYDistance =
@@ -401,7 +401,7 @@
             }
             mImeVisible = keyboardHeight != 0;
 
-            float newY = getYPositionForExpandedView();
+            float newY = getExpandedViewY();
             if (newY < 0) {
                 // TODO: This means our expanded content is too big to fit on screen. Right now
                 // we'll let it translate off but we should be clipping it & pushing the header
@@ -779,25 +779,14 @@
         if (DEBUG) {
             Log.d(TAG, "setExpanded: " + shouldExpand);
         }
-        boolean wasExpanded = mIsExpanded;
-        if (shouldExpand == wasExpanded) {
+        if (shouldExpand == mIsExpanded) {
             return;
         }
-        if (wasExpanded) {
-            // Collapse the stack
-            mExpandedViewContainer.setAlpha(0.0f);
-            // TODO: In order to prevent flicker, code below should be executed after the alpha
-            // value set on the mExpandedViewContainer is reflected on the screen. However, we
-            // cannot just postpone the execution like #setSelectedBubble(), since some of member
-            // variables referred by the code are overridden before the execution.
-            if (mExpandedBubble != null) {
-                mExpandedBubble.setContentVisibility(false);
-            }
-            animateExpansion(false /* expand */);
+        if (mIsExpanded) {
+            animateCollapse();
             logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
         } else {
-            // Expand the stack
-            animateExpansion(true /* expand */);
+            animateExpansion();
             // TODO: move next line to BubbleData
             logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED);
             logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__STACK_EXPANDED);
@@ -897,64 +886,71 @@
         mBubbleData.setExpanded(true);
     }
 
-    /**
-     * Tell the stack to animate to collapsed or expanded state.
-     */
-    private void animateExpansion(boolean shouldExpand) {
-        if (DEBUG) {
-            Log.d(TAG, "animateExpansion: shouldExpand=" + shouldExpand);
-        }
-        if (mIsExpanded != shouldExpand) {
-            hideFlyoutImmediate();
+    private void beforeExpandedViewAnimation() {
+        hideFlyoutImmediate();
+        updateExpandedBubble();
+        updateExpandedView();
+        mIsExpansionAnimating = true;
+    }
 
-            mIsExpanded = shouldExpand;
-            updateExpandedBubble();
-            applyCurrentState();
+    private void afterExpandedViewAnimation() {
+        updateExpandedView();
+        mIsExpansionAnimating = false;
+        requestUpdate();
+    }
 
-            mIsExpansionAnimating = true;
+    private void animateCollapse() {
+        mIsExpanded = false;
+        beforeExpandedViewAnimation();
 
-            Runnable updateAfter = () -> {
-                applyCurrentState();
-                mIsExpansionAnimating = false;
-                requestUpdate();
-            };
+        mBubbleContainer.cancelAllAnimations();
+        mExpandedAnimationController.collapseBackToStack(
+                () -> {
+                    mBubbleContainer.setController(mStackAnimationController);
+                    afterExpandedViewAnimation();
+                });
 
-            if (shouldExpand) {
-                mBubbleContainer.setController(mExpandedAnimationController);
-                mExpandedAnimationController.expandFromStack(
-                        mStackAnimationController.getStackPositionAlongNearestHorizontalEdge()
-                        /* collapseTo */,
-                        () -> {
-                            updatePointerPosition();
-                            updateAfter.run();
-                        } /* after */);
-            } else {
-                mBubbleContainer.cancelAllAnimations();
-                mExpandedAnimationController.collapseBackToStack(
-                        () -> {
-                            mBubbleContainer.setController(mStackAnimationController);
-                            updateAfter.run();
-                        });
-            }
+        mExpandedViewXAnim.animateToFinalPosition(getCollapsedX());
+        mExpandedViewYAnim.animateToFinalPosition(getCollapsedY());
+        mExpandedViewContainer.animate()
+                .setDuration(100)
+                .alpha(0f);
+    }
 
-            final float xStart =
-                    mStackAnimationController.getStackPosition().x < getWidth() / 2
-                            ? -mExpandedAnimateXDistance
-                            : mExpandedAnimateXDistance;
+    private void animateExpansion() {
+        mIsExpanded = true;
+        beforeExpandedViewAnimation();
 
-            final float yStart = Math.min(
-                    mStackAnimationController.getStackPosition().y,
-                    mExpandedAnimateYDistance);
-            final float yDest = getYPositionForExpandedView();
+        mBubbleContainer.setController(mExpandedAnimationController);
+        mExpandedAnimationController.expandFromStack(
+                mStackAnimationController.getStackPositionAlongNearestHorizontalEdge()
+                /* collapseTo */,
+                () -> {
+                    updatePointerPosition();
+                    afterExpandedViewAnimation();
+                } /* after */);
 
-            if (shouldExpand) {
-                mExpandedViewContainer.setTranslationX(xStart);
-                mExpandedViewContainer.setTranslationY(yStart);
-            }
 
-            mExpandedViewXAnim.animateToFinalPosition(shouldExpand ? 0f : xStart);
-            mExpandedViewYAnim.animateToFinalPosition(shouldExpand ? yDest : yStart);
-        }
+        mExpandedViewContainer.setTranslationX(getCollapsedX());
+        mExpandedViewContainer.setTranslationY(getCollapsedY());
+        mExpandedViewContainer.setAlpha(0f);
+
+        mExpandedViewXAnim.animateToFinalPosition(0f);
+        mExpandedViewYAnim.animateToFinalPosition(getExpandedViewY());
+        mExpandedViewContainer.animate()
+                .setDuration(100)
+                .alpha(1f);
+    }
+
+    private float getCollapsedX() {
+        return mStackAnimationController.getStackPosition().x < getWidth() / 2
+                ? -mExpandedAnimateXDistance
+                : mExpandedAnimateXDistance;
+    }
+
+    private float getCollapsedY() {
+        return Math.min(mStackAnimationController.getStackPosition().y,
+                mExpandedAnimateYDistance);
     }
 
     private void notifyExpansionChanged(NotificationEntry entry, boolean expanded) {
@@ -1308,8 +1304,8 @@
     /**
      * Calculates the y position of the expanded view when it is expanded.
      */
-    float getYPositionForExpandedView() {
-        return getStatusBarHeight() + mBubbleSize + mBubblePadding + mPointerHeight;
+    float getExpandedViewY() {
+        return getStatusBarHeight() + mBubbleSize + mBubblePaddingTop + mPointerHeight;
     }
 
     /**
@@ -1482,9 +1478,9 @@
         }
     }
 
-    private void applyCurrentState() {
+    private void updateExpandedView() {
         if (DEBUG) {
-            Log.d(TAG, "applyCurrentState: mIsExpanded=" + mIsExpanded);
+            Log.d(TAG, "updateExpandedView: mIsExpanded=" + mIsExpanded);
         }
 
         mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
@@ -1492,7 +1488,7 @@
             // First update the view so that it calculates a new height (ensuring the y position
             // calculation is correct)
             mExpandedBubble.expandedView.updateView();
-            final float y = getYPositionForExpandedView();
+            final float y = getExpandedViewY();
             if (!mExpandedViewYAnim.isRunning()) {
                 // We're not animating so set the value
                 mExpandedViewContainer.setTranslationY(y);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 24337a3..7b879c2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -53,16 +53,14 @@
 
     /** Horizontal offset between bubbles, which we need to know to re-stack them. */
     private float mStackOffsetPx;
-    /** Spacing between bubbles in the expanded state. */
-    private float mBubblePaddingPx;
+    /** Space between status bar and bubbles in the expanded state. */
+    private float mBubblePaddingTop;
     /** Size of each bubble. */
     private float mBubbleSizePx;
     /** Height of the status bar. */
     private float mStatusBarHeight;
     /** Size of display. */
     private Point mDisplaySize;
-    /** Size of dismiss target at bottom of screen. */
-    private float mPipDismissHeight;
     /** Max number of bubbles shown in row above expanded view.*/
     private int mBubblesMaxRendered;
 
@@ -96,24 +94,16 @@
     /** The bubble currently being dragged out of the row (to potentially be dismissed). */
     private View mBubbleDraggingOut;
 
-    /**
-     * Drag velocities for the dragging-out bubble when the drag finished. These are used by
-     * {@link #onChildRemoved} to animate out the bubble while respecting touch velocity.
-     */
-    private float mBubbleDraggingOutVelX;
-    private float mBubbleDraggingOutVelY;
-
     @Override
     protected void setLayout(PhysicsAnimationLayout layout) {
         super.setLayout(layout);
 
         final Resources res = layout.getResources();
         mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
-        mBubblePaddingPx = res.getDimensionPixelSize(R.dimen.bubble_padding);
+        mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
         mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
         mStatusBarHeight =
                 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
-        mPipDismissHeight = res.getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height);
         mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
     }
 
@@ -251,13 +241,10 @@
     }
 
     /**
-     * Sets configuration variables so that when the given bubble is removed, the animations are
-     * started with the given velocities.
+     * Sets configuration variables.
      */
-    public void prepareForDismissalWithVelocity(View bubbleView, float velX, float velY) {
+    public void prepareForDismissalWithVelocity(View bubbleView) {
         mBubbleDraggingOut = bubbleView;
-        mBubbleDraggingOutVelX = velX;
-        mBubbleDraggingOutVelY = velY;
         mBubbleDraggedOutEnough = false;
     }
 
@@ -270,26 +257,13 @@
                 0, (i, anim) -> anim.translationY(getExpandedY())).startAll(after);
     }
 
-    /**
-     * Animates the bubbles, starting at the given index, to the left or right by the given number
-     * of bubble widths. Passing zero for numBubbleWidths will animate the bubbles to their normal
-     * positions.
-     */
-    private void animateStackByBubbleWidthsStartingFrom(int numBubbleWidths, int startIndex) {
-        animationsForChildrenFromIndex(
-                startIndex,
-                (index, animation) ->
-                        animation.translationX(getXForChildAtIndex(index + numBubbleWidths)))
-            .startAll();
-    }
-
     /** The Y value of the row of expanded bubbles. */
     public float getExpandedY() {
         if (mLayout == null || mLayout.getRootWindowInsets() == null) {
             return 0;
         }
         final WindowInsets insets = mLayout.getRootWindowInsets();
-        return mBubblePaddingPx + Math.max(
+        return mBubblePaddingTop + Math.max(
             mStatusBarHeight,
             insets.getDisplayCutout() != null
                 ? insets.getDisplayCutout().getSafeInsetTop()
@@ -325,8 +299,6 @@
 
     @Override
     void onChildAdded(View child, int index) {
-        child.setTranslationX(getXForChildAtIndex(index));
-
         animationForChild(child)
                 .translationY(
                         getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */
@@ -384,38 +356,59 @@
         }
     }
 
-    /** Returns the appropriate X translation value for a bubble at the given index. */
-    private float getXForChildAtIndex(int index) {
-        return mBubblePaddingPx + (mBubbleSizePx + mBubblePaddingPx) * index;
-    }
-
     /**
      * @param index Bubble index in row.
      * @return Bubble left x from left edge of screen.
      */
     public float getBubbleLeft(int index) {
-        float bubbleLeftFromRowLeft = index * (mBubbleSizePx + mBubblePaddingPx);
-        return getRowLeft() + bubbleLeftFromRowLeft;
+        float bubbleFromRowLeft = index * (mBubbleSizePx + getSpaceBetweenBubbles());
+        return getRowLeft() + bubbleFromRowLeft;
     }
 
     private float getRowLeft() {
         if (mLayout == null) {
             return 0;
         }
+
         int bubbleCount = mLayout.getChildCount();
         if (bubbleCount > mBubblesMaxRendered) {
-            // Only shown bubbles are relevant for calculating position.
+            // Only rendered bubbles are relevant for calculating row left.
             bubbleCount = mBubblesMaxRendered;
         }
-        // Width calculations.
-        double bubble = bubbleCount * mBubbleSizePx;
-        float gap = (bubbleCount - 1) * mBubblePaddingPx;
-        float row = gap + (float) bubble;
 
-        float halfRow = row / 2f;
-        float centerScreen = mDisplaySize.x / 2;
-        float rowLeftFromScreenLeft = centerScreen - halfRow;
+        final float totalBubbleWidth = bubbleCount * mBubbleSizePx;
+        final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles();
+        final float rowWidth = totalGapWidth + totalBubbleWidth;
 
-        return rowLeftFromScreenLeft;
+        final float centerScreen = mDisplaySize.x / 2f;
+        final float halfRow = rowWidth / 2f;
+        final float rowLeft = centerScreen - halfRow;
+
+        return rowLeft;
+    }
+
+    /**
+     * @return Space between bubbles in row above expanded view.
+     */
+    private float getSpaceBetweenBubbles() {
+        /**
+         * Ordered left to right:
+         *  Screen edge
+         *      [mExpandedViewPadding]
+         *  Expanded view edge
+         *      [launcherGridDiff] --- arbitrary value until launcher exports widths
+         *  Launcher's app icon grid edge that we must match
+         */
+        final float launcherGridDiff = mBubbleSizePx / 2f;
+        final float rowMargins = (mExpandedViewPadding + launcherGridDiff) * 2;
+        final float maxRowWidth = mDisplaySize.x - rowMargins;
+
+        final float totalBubbleWidth = mBubblesMaxRendered * mBubbleSizePx;
+        final float totalGapWidth = maxRowWidth - totalBubbleWidth;
+
+        final int gapCount = mBubblesMaxRendered - 1;
+        final float gapWidth = totalGapWidth / gapCount;
+
+        return gapWidth;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index b9cdc844..7997dcb 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -146,7 +146,7 @@
      * the screen or the IME. This does not apply to the left/right sides of the screen since the
      * stack goes offscreen intentionally.
      */
-    private int mBubblePadding;
+    private int mBubblePaddingTop;
     /** How far offscreen the stack rests. */
     private int mBubbleOffscreen;
     /** How far down the screen the stack starts, when there is no pre-existing location. */
@@ -161,7 +161,7 @@
         Resources res = layout.getResources();
         mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
         mIndividualBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
-        mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding);
+        mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
         mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
         mStackStartingVerticalOffset =
                 res.getDimensionPixelSize(R.dimen.bubble_stack_starting_offset_y);
@@ -449,7 +449,7 @@
                                     : 0);
 
             allowableRegion.top =
-                    mBubblePadding
+                    mBubblePaddingTop
                             + Math.max(
                             mStatusBarHeight,
                             insets.getDisplayCutout() != null
@@ -458,8 +458,8 @@
             allowableRegion.bottom =
                     mLayout.getHeight()
                             - mIndividualBubbleSize
-                            - mBubblePadding
-                            - (mImeHeight > Float.MIN_VALUE ? mImeHeight + mBubblePadding : 0f)
+                            - mBubblePaddingTop
+                            - (mImeHeight > Float.MIN_VALUE ? mImeHeight + mBubblePaddingTop : 0f)
                             - Math.max(
                             insets.getSystemWindowInsetBottom(),
                             insets.getDisplayCutout() != null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index 756cf3e..d106dea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -138,8 +138,8 @@
         assertEquals(500f, draggedBubble.getTranslationX(), 1f);
         assertEquals(500f, draggedBubble.getTranslationY(), 1f);
 
-        // Snap it back and make sure it made it back correctly.
-        mExpandedController.prepareForDismissalWithVelocity(draggedBubble, 0f, 0f);
+        // Snap bubble back and make sure it returned correctly.
+        mExpandedController.prepareForDismissalWithVelocity(draggedBubble);
         mLayout.removeView(draggedBubble);
         waitForLayoutMessageQueue();
         waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);