Fix undismissed bubble text for two continuous call.

If a new call is placed before hiding the current bubble, bubble text will not be reset and the new bubble shows with the text. Fixing it by using different hide method for onUiShowing() and onDisconnect() (reset after disconnecting).

Test: ReturnToCallControllerTest, BubbleTest
PiperOrigin-RevId: 164048596
Change-Id: I7259df57da3aba51960bfb7bb1ea5f840c9501e0
diff --git a/java/com/android/dialershared/bubble/Bubble.java b/java/com/android/dialershared/bubble/Bubble.java
index 9ce356a..9606f5b 100644
--- a/java/com/android/dialershared/bubble/Bubble.java
+++ b/java/com/android/dialershared/bubble/Bubble.java
@@ -89,6 +89,8 @@
   private final Context context;
   private final WindowManager windowManager;
 
+  private final Handler handler = new Handler();
+
   private LayoutParams windowParams;
 
   // Initialized in factory method
@@ -102,8 +104,6 @@
   private boolean hideAfterText;
   private int collapseEndAction;
 
-  private final Handler handler = new Handler();
-
   @VisibleForTesting ViewHolder viewHolder;
   private ViewPropertyAnimator collapseAnimation;
   private Integer overrideGravity;
@@ -240,47 +240,22 @@
     updatePrimaryIconAnimation();
   }
 
-  /**
-   * Hide the button if visible. Will run a short exit animation before hiding. If the bubble is
-   * currently showing text, will hide after the text is done displaying. If the bubble is not
-   * visible this method does nothing.
-   */
+  /** Hide the bubble. */
   public void hide() {
-    if (visibility == Visibility.HIDDEN || visibility == Visibility.EXITING) {
+    if (hideAfterText) {
+      // hideAndReset() will be called after showing text, do nothing here.
       return;
     }
+    hideHelper(this::defaultAfterHidingAnimation);
+  }
 
-    if (textShowing) {
-      hideAfterText = true;
-      return;
-    }
-
-    if (collapseAnimation != null) {
-      collapseEndAction = CollapseEnd.HIDE;
-      return;
-    }
-
-    if (expanded) {
-      startCollapse(CollapseEnd.HIDE);
-      return;
-    }
-
-    visibility = Visibility.EXITING;
-    exitAnimator =
-        viewHolder
-            .getPrimaryButton()
-            .animate()
-            .setInterpolator(new AnticipateInterpolator())
-            .scaleX(0)
-            .scaleY(0)
-            .withEndAction(
-                () -> {
-                  exitAnimator = null;
-                  windowManager.removeView(viewHolder.getRoot());
-                  visibility = Visibility.HIDDEN;
-                  updatePrimaryIconAnimation();
-                });
-    exitAnimator.start();
+  /** Hide the bubble and reset {@viewHolder} to initial state */
+  public void hideAndReset() {
+    hideHelper(
+        () -> {
+          defaultAfterHidingAnimation();
+          reset();
+        });
   }
 
   /** Returns whether the bubble is currently visible */
@@ -386,7 +361,8 @@
         () -> {
           textShowing = false;
           if (hideAfterText) {
-            hide();
+            // Always reset here since text shouldn't keep showing.
+            hideAndReset();
           } else {
             doResize(
                 () -> viewHolder.getPrimaryButton().setDisplayedChild(ViewHolder.CHILD_INDEX_ICON));
@@ -489,6 +465,48 @@
     return viewHolder.getRoot();
   }
 
+  /**
+   * Hide the bubble if visible. Will run a short exit animation and before hiding, and {@code
+   * afterHiding} after hiding. If the bubble is currently showing text, will hide after the text is
+   * done displaying. If the bubble is not visible this method does nothing.
+   */
+  private void hideHelper(Runnable afterHiding) {
+    if (visibility == Visibility.HIDDEN || visibility == Visibility.EXITING) {
+      return;
+    }
+
+    if (textShowing) {
+      hideAfterText = true;
+      return;
+    }
+
+    if (collapseAnimation != null) {
+      collapseEndAction = CollapseEnd.HIDE;
+      return;
+    }
+
+    if (expanded) {
+      startCollapse(CollapseEnd.HIDE);
+      return;
+    }
+
+    visibility = Visibility.EXITING;
+    exitAnimator =
+        viewHolder
+            .getPrimaryButton()
+            .animate()
+            .setInterpolator(new AnticipateInterpolator())
+            .scaleX(0)
+            .scaleY(0)
+            .withEndAction(afterHiding);
+    exitAnimator.start();
+  }
+
+  private void reset() {
+    viewHolder = new ViewHolder(viewHolder.getRoot().getContext());
+    update();
+  }
+
   private void update() {
     RippleDrawable backgroundRipple =
         (RippleDrawable)
@@ -692,6 +710,14 @@
     windowManager.updateViewLayout(getRootView(), windowParams);
   }
 
+  private void defaultAfterHidingAnimation() {
+    exitAnimator = null;
+    windowManager.removeView(viewHolder.getRoot());
+    visibility = Visibility.HIDDEN;
+
+    updatePrimaryIconAnimation();
+  }
+
   @VisibleForTesting
   class ViewHolder {
 
diff --git a/java/com/android/incallui/ReturnToCallController.java b/java/com/android/incallui/ReturnToCallController.java
index 978b140..8e4b9cc 100644
--- a/java/com/android/incallui/ReturnToCallController.java
+++ b/java/com/android/incallui/ReturnToCallController.java
@@ -102,6 +102,14 @@
     }
   }
 
+  private void hideAndReset() {
+    if (bubble != null) {
+      bubble.hideAndReset();
+    } else {
+      LogUtil.i("ReturnToCallController.reset", "reset() called without calling show()");
+    }
+  }
+
   private void show() {
     if (bubble == null) {
       bubble = startNewBubble();
@@ -141,7 +149,7 @@
       bubble.showText(context.getText(R.string.incall_call_ended));
     }
     if (!hasAnotherCall) {
-      hide();
+      hideAndReset();
     }
   }