Switch Dialer to use new third_party bubble library

This CL switches Dialer to use the new common bubble libary. It also moves the
integration tests into the bubble libary.

Bug: 64797730
Test: BubbleIntegrationTest
PiperOrigin-RevId: 167439680
Change-Id: Ie2e9367cb6a6561efb8abd425b6a12f8c1e78138
diff --git a/Android.mk b/Android.mk
index db0aed4..2c511e1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,14 +15,6 @@
 # The base directory for Dialer sources.
 BASE_DIR := java/com/android
 
-# Primary dialer module sources.
-SRC_DIRS := \
-	$(BASE_DIR)/contacts/common \
-	$(BASE_DIR)/dialer \
-	$(BASE_DIR)/dialershared \
-	$(BASE_DIR)/incallui \
-	$(BASE_DIR)/voicemail
-
 # Exclude files incompatible with AOSP.
 EXCLUDE_FILES := \
 	$(BASE_DIR)/incallui/calllocation/impl/AuthException.java \
@@ -76,8 +68,8 @@
 LOCAL_FULL_LIBS_MANIFEST_FILES := \
 	$(addprefix $(LOCAL_PATH)/, $(DIALER_MANIFEST_FILES))
 
-LOCAL_SRC_FILES := $(call all-java-files-under, $(SRC_DIRS))
-LOCAL_SRC_FILES += $(call all-proto-files-under, $(SRC_DIRS))
+LOCAL_SRC_FILES := $(call all-java-files-under, $(BASE_DIR))
+LOCAL_SRC_FILES += $(call all-proto-files-under, $(BASE_DIR))
 LOCAL_SRC_FILES := $(filter-out $(EXCLUDE_FILES),$(LOCAL_SRC_FILES))
 
 LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)
@@ -93,6 +85,7 @@
 # We specify each package explicitly to glob resource files.
 # find . -type f -name "AndroidManifest.xml" | uniq | sort | cut -c 8- | rev | cut -c 21- | rev | sed 's/\//./g' | sed 's/$/ \\/'
 LOCAL_AAPT_FLAGS := \
+	com.android.bubble \
 	com.android.contacts.common \
 	com.android.dialer.about \
 	com.android.dialer.app \
@@ -131,7 +124,6 @@
 	com.android.dialer.searchfragment.list \
 	com.android.dialer.searchfragment.nearbyplaces \
 	com.android.dialer.searchfragment.remote \
-	com.android.dialershared.bubble \
 	com.android.dialer.shortcuts \
 	com.android.dialer.simulator.impl \
 	com.android.dialer.speeddial \
@@ -233,7 +225,7 @@
 
 
 # Proguard includes
-LOCAL_PROGUARD_FLAG_FILES := $(call all-named-files-under,proguard.*flags,$(SRC_DIRS))
+LOCAL_PROGUARD_FLAG_FILES := $(call all-named-files-under,proguard.*flags,$(BASE_DIR))
 LOCAL_PROGUARD_ENABLED := custom
 
 LOCAL_PROGUARD_ENABLED += optimization
@@ -255,7 +247,6 @@
 
 # Cleanup local state
 BASE_DIR :=
-SRC_DIRS :=
 EXCLUDE_FILES :=
 RES_DIRS :=
 DIALER_MANIFEST_FILES :=
diff --git a/java/com/android/dialershared/bubble/AndroidManifest.xml b/java/com/android/bubble/AndroidManifest.xml
similarity index 94%
rename from java/com/android/dialershared/bubble/AndroidManifest.xml
rename to java/com/android/bubble/AndroidManifest.xml
index 1a94aaf..80efe5c 100644
--- a/java/com/android/dialershared/bubble/AndroidManifest.xml
+++ b/java/com/android/bubble/AndroidManifest.xml
@@ -15,7 +15,7 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.dialershared.bubble">
+    package="com.android.bubble">
 
   <uses-sdk android:minSdkVersion="21"/>
   <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
diff --git a/java/com/android/dialershared/bubble/Bubble.java b/java/com/android/bubble/Bubble.java
similarity index 97%
rename from java/com/android/dialershared/bubble/Bubble.java
rename to java/com/android/bubble/Bubble.java
index d245522..d83e284 100644
--- a/java/com/android/dialershared/bubble/Bubble.java
+++ b/java/com/android/bubble/Bubble.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.dialershared.bubble;
+package com.android.bubble;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
@@ -61,7 +61,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 import android.widget.ViewAnimator;
-import com.android.dialershared.bubble.BubbleInfo.Action;
+import com.android.bubble.BubbleInfo.Action;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
@@ -87,8 +87,7 @@
   private final Context context;
   private final WindowManager windowManager;
 
-  private final Handler handler = new Handler();
-
+  private final Handler handler;
   private LayoutParams windowParams;
 
   // Initialized in factory method
@@ -107,6 +106,21 @@
   private Integer overrideGravity;
   private ViewPropertyAnimator exitAnimator;
 
+  private final Runnable collapseRunnable =
+      new Runnable() {
+        @Override
+        public void run() {
+          textShowing = false;
+          if (hideAfterText) {
+            // Always reset here since text shouldn't keep showing.
+            hideAndReset();
+          } else {
+            doResize(
+                () -> viewHolder.getPrimaryButton().setDisplayedChild(ViewHolder.CHILD_INDEX_ICON));
+          }
+        }
+      };
+
   private BubbleExpansionStateListener bubbleExpansionStateListener;
 
   @Retention(RetentionPolicy.SOURCE)
@@ -163,13 +177,13 @@
   /** Creates instances of Bubble. The default implementation just calls the constructor. */
   @VisibleForTesting
   public interface BubbleFactory {
-    Bubble createBubble(@NonNull Context context);
+    Bubble createBubble(@NonNull Context context, @NonNull Handler handler);
   }
 
   private static BubbleFactory bubbleFactory = Bubble::new;
 
   public static Bubble createBubble(@NonNull Context context, @NonNull BubbleInfo info) {
-    Bubble bubble = bubbleFactory.createBubble(context);
+    Bubble bubble = bubbleFactory.createBubble(context, new Handler());
     bubble.setBubbleInfo(info);
     return bubble;
   }
@@ -185,14 +199,55 @@
   }
 
   @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-  Bubble(@NonNull Context context) {
+  Bubble(@NonNull Context context, @NonNull Handler handler) {
     context = new ContextThemeWrapper(context, R.style.Theme_AppCompat);
     this.context = context;
+    this.handler = handler;
     windowManager = context.getSystemService(WindowManager.class);
 
     viewHolder = new ViewHolder(context);
   }
 
+  /** Expands the main bubble menu. */
+  public void expand() {
+    if (expanded || textShowing || currentInfo.getActions().isEmpty()) {
+      try {
+        currentInfo.getPrimaryIntent().send();
+      } catch (CanceledException e) {
+        throw new RuntimeException(e);
+      }
+      return;
+    }
+
+    if (bubbleExpansionStateListener != null) {
+      bubbleExpansionStateListener.onBubbleExpansionStateChanged(ExpansionState.START_EXPANDING);
+    }
+    doResize(
+        () -> {
+          onLeftRightSwitch(isDrawingFromRight());
+          viewHolder.setDrawerVisibility(View.VISIBLE);
+        });
+    View expandedView = viewHolder.getExpandedView();
+    expandedView
+        .getViewTreeObserver()
+        .addOnPreDrawListener(
+            new OnPreDrawListener() {
+              @Override
+              public boolean onPreDraw() {
+                expandedView.getViewTreeObserver().removeOnPreDrawListener(this);
+                expandedView.setTranslationX(
+                    isDrawingFromRight() ? expandedView.getWidth() : -expandedView.getWidth());
+                expandedView
+                    .animate()
+                    .setInterpolator(new LinearOutSlowInInterpolator())
+                    .translationX(0);
+                return false;
+              }
+            });
+    setFocused(true);
+    expanded = true;
+  }
+
   /**
    * Make the bubble visible. Will show a short entrance animation as it enters. If the bubble is
    * already showing this method does nothing.
@@ -371,19 +426,8 @@
                     });
           });
     }
-    handler.removeCallbacks(null);
-    handler.postDelayed(
-        () -> {
-          textShowing = false;
-          if (hideAfterText) {
-            // Always reset here since text shouldn't keep showing.
-            hideAndReset();
-          } else {
-            doResize(
-                () -> viewHolder.getPrimaryButton().setDisplayedChild(ViewHolder.CHILD_INDEX_ICON));
-          }
-        },
-        SHOW_TEXT_DURATION_MILLIS);
+    handler.removeCallbacks(collapseRunnable);
+    handler.postDelayed(collapseRunnable, SHOW_TEXT_DURATION_MILLIS);
   }
 
   public void setBubbleExpansionStateListener(
@@ -415,42 +459,7 @@
   }
 
   void primaryButtonClick() {
-    if (expanded || textShowing || currentInfo.getActions().isEmpty()) {
-      try {
-        currentInfo.getPrimaryIntent().send();
-      } catch (CanceledException e) {
-        throw new RuntimeException(e);
-      }
-      return;
-    }
-
-    if (bubbleExpansionStateListener != null) {
-      bubbleExpansionStateListener.onBubbleExpansionStateChanged(ExpansionState.START_EXPANDING);
-    }
-    doResize(
-        () -> {
-          onLeftRightSwitch(isDrawingFromRight());
-          viewHolder.setDrawerVisibility(View.VISIBLE);
-        });
-    View expandedView = viewHolder.getExpandedView();
-    expandedView
-        .getViewTreeObserver()
-        .addOnPreDrawListener(
-            new OnPreDrawListener() {
-              @Override
-              public boolean onPreDraw() {
-                expandedView.getViewTreeObserver().removeOnPreDrawListener(this);
-                expandedView.setTranslationX(
-                    isDrawingFromRight() ? expandedView.getWidth() : -expandedView.getWidth());
-                expandedView
-                    .animate()
-                    .setInterpolator(new LinearOutSlowInInterpolator())
-                    .translationX(0);
-                return false;
-              }
-            });
-    setFocused(true);
-    expanded = true;
+    expand();
   }
 
   void onLeftRightSwitch(boolean onRight) {
diff --git a/java/com/android/dialershared/bubble/BubbleInfo.java b/java/com/android/bubble/BubbleInfo.java
similarity index 98%
rename from java/com/android/dialershared/bubble/BubbleInfo.java
rename to java/com/android/bubble/BubbleInfo.java
index eb9abd0..b4f81b3 100644
--- a/java/com/android/dialershared/bubble/BubbleInfo.java
+++ b/java/com/android/bubble/BubbleInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.dialershared.bubble;
+package com.android.bubble;
 
 import android.app.PendingIntent;
 import android.graphics.drawable.Icon;
diff --git a/java/com/android/dialershared/bubble/ChangeOnScreenBounds.java b/java/com/android/bubble/ChangeOnScreenBounds.java
similarity index 99%
rename from java/com/android/dialershared/bubble/ChangeOnScreenBounds.java
rename to java/com/android/bubble/ChangeOnScreenBounds.java
index 8cd61af..0a7adf6 100644
--- a/java/com/android/dialershared/bubble/ChangeOnScreenBounds.java
+++ b/java/com/android/bubble/ChangeOnScreenBounds.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.dialershared.bubble;
+package com.android.bubble;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
diff --git a/java/com/android/dialershared/bubble/CheckableImageButton.java b/java/com/android/bubble/CheckableImageButton.java
similarity index 98%
rename from java/com/android/dialershared/bubble/CheckableImageButton.java
rename to java/com/android/bubble/CheckableImageButton.java
index 7a5a432..dd9acce 100644
--- a/java/com/android/dialershared/bubble/CheckableImageButton.java
+++ b/java/com/android/bubble/CheckableImageButton.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.dialershared.bubble;
+package com.android.bubble;
 
 import android.content.Context;
 import android.support.v4.view.AccessibilityDelegateCompat;
diff --git a/java/com/android/dialershared/bubble/MoveHandler.java b/java/com/android/bubble/MoveHandler.java
similarity index 99%
rename from java/com/android/dialershared/bubble/MoveHandler.java
rename to java/com/android/bubble/MoveHandler.java
index 33507ef..06efbd4 100644
--- a/java/com/android/dialershared/bubble/MoveHandler.java
+++ b/java/com/android/bubble/MoveHandler.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.dialershared.bubble;
+package com.android.bubble;
 
 import android.content.Context;
 import android.graphics.Point;
diff --git a/java/com/android/dialershared/bubble/WindowRoot.java b/java/com/android/bubble/WindowRoot.java
similarity index 98%
rename from java/com/android/dialershared/bubble/WindowRoot.java
rename to java/com/android/bubble/WindowRoot.java
index 81d6b48..b9024c4 100644
--- a/java/com/android/dialershared/bubble/WindowRoot.java
+++ b/java/com/android/bubble/WindowRoot.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.dialershared.bubble;
+package com.android.bubble;
 
 import android.content.Context;
 import android.content.res.Configuration;
diff --git a/java/com/android/dialershared/bubble/res/color/bubble_checkable_mask.xml b/java/com/android/bubble/res/color/bubble_checkable_mask.xml
similarity index 100%
rename from java/com/android/dialershared/bubble/res/color/bubble_checkable_mask.xml
rename to java/com/android/bubble/res/color/bubble_checkable_mask.xml
diff --git a/java/com/android/dialershared/bubble/res/color/bubble_icon_tint_states.xml b/java/com/android/bubble/res/color/bubble_icon_tint_states.xml
similarity index 100%
rename from java/com/android/dialershared/bubble/res/color/bubble_icon_tint_states.xml
rename to java/com/android/bubble/res/color/bubble_icon_tint_states.xml
diff --git a/java/com/android/dialershared/bubble/res/drawable/bubble_background_pill_ltr.xml b/java/com/android/bubble/res/drawable/bubble_background_pill_ltr.xml
similarity index 100%
rename from java/com/android/dialershared/bubble/res/drawable/bubble_background_pill_ltr.xml
rename to java/com/android/bubble/res/drawable/bubble_background_pill_ltr.xml
diff --git a/java/com/android/dialershared/bubble/res/drawable/bubble_background_pill_rtl.xml b/java/com/android/bubble/res/drawable/bubble_background_pill_rtl.xml
similarity index 100%
rename from java/com/android/dialershared/bubble/res/drawable/bubble_background_pill_rtl.xml
rename to java/com/android/bubble/res/drawable/bubble_background_pill_rtl.xml
diff --git a/java/com/android/dialershared/bubble/res/drawable/bubble_ripple_checkable_circle.xml b/java/com/android/bubble/res/drawable/bubble_ripple_checkable_circle.xml
similarity index 100%
rename from java/com/android/dialershared/bubble/res/drawable/bubble_ripple_checkable_circle.xml
rename to java/com/android/bubble/res/drawable/bubble_ripple_checkable_circle.xml
diff --git a/java/com/android/dialershared/bubble/res/drawable/bubble_ripple_circle.xml b/java/com/android/bubble/res/drawable/bubble_ripple_circle.xml
similarity index 100%
rename from java/com/android/dialershared/bubble/res/drawable/bubble_ripple_circle.xml
rename to java/com/android/bubble/res/drawable/bubble_ripple_circle.xml
diff --git a/java/com/android/dialershared/bubble/res/layout/bubble_base.xml b/java/com/android/bubble/res/layout/bubble_base.xml
similarity index 96%
rename from java/com/android/dialershared/bubble/res/layout/bubble_base.xml
rename to java/com/android/bubble/res/layout/bubble_base.xml
index 76970f0..3b5735c 100644
--- a/java/com/android/dialershared/bubble/res/layout/bubble_base.xml
+++ b/java/com/android/bubble/res/layout/bubble_base.xml
@@ -54,7 +54,7 @@
         android:visibility="gone"
         tools:backgroundTint="#FF0000FF"
         tools:visibility="visible">
-      <com.android.dialershared.bubble.CheckableImageButton
+      <com.android.bubble.CheckableImageButton
           android:id="@+id/bubble_icon_first"
           android:layout_width="@dimen/bubble_size"
           android:layout_height="@dimen/bubble_size"
@@ -64,7 +64,7 @@
           android:tintMode="src_in"
           tools:background="@drawable/bubble_ripple_checkable_circle"
           tools:src="@android:drawable/ic_lock_idle_lock"/>
-      <com.android.dialershared.bubble.CheckableImageButton
+      <com.android.bubble.CheckableImageButton
           android:id="@+id/bubble_icon_second"
           android:layout_width="@dimen/bubble_size"
           android:layout_height="@dimen/bubble_size"
@@ -74,7 +74,7 @@
           android:tintMode="src_in"
           tools:background="@drawable/bubble_ripple_checkable_circle"
           tools:src="@android:drawable/ic_input_add"/>
-      <com.android.dialershared.bubble.CheckableImageButton
+      <com.android.bubble.CheckableImageButton
           android:id="@+id/bubble_icon_third"
           android:layout_width="@dimen/bubble_size"
           android:layout_height="@dimen/bubble_size"
diff --git a/java/com/android/dialershared/bubble/res/values/colors.xml b/java/com/android/bubble/res/values/colors.xml
similarity index 100%
rename from java/com/android/dialershared/bubble/res/values/colors.xml
rename to java/com/android/bubble/res/values/colors.xml
diff --git a/java/com/android/dialershared/bubble/res/values/values.xml b/java/com/android/bubble/res/values/values.xml
similarity index 100%
rename from java/com/android/dialershared/bubble/res/values/values.xml
rename to java/com/android/bubble/res/values/values.xml
diff --git a/java/com/android/dialershared/bubble/g3doc/INTEGRATION.md b/java/com/android/dialershared/bubble/g3doc/INTEGRATION.md
deleted file mode 100644
index a13a605..0000000
--- a/java/com/android/dialershared/bubble/g3doc/INTEGRATION.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# Floating Bubble Integration
-
-go/bubble-integration
-
-Author: keyboardr@
-
-Last Updated: 2017-06-06
-
-Floating bubbles provide a lightweight means of providing interactive UI while
-the user is away from the app. This document details the steps necessary to
-integrate these bubbles into your app.
-
-[TOC]
-
-![Floating bubble](images/bubble_collapsed.png){height=400}
-
-## Ensure Bubbles can be shown
-
-Add the `android.permission.SYSTEM_ALERT_WINDOW` permission to your manifest.
-Before you show the bubble, call `Bubble.canShowBubbles(Context)` to see if the
-user has granted you permission. If not, you can start an Activity from
-`Bubble.getRequestPermissionIntent(Context)` to navigate the user to the system
-settings to enable drawing over other apps. This is more than just a simple
-runtime permission; the user must explicitly allow you to draw over other apps
-via this system setting. System apps may have this allowed by default, but be
-sure to test.
-
-## Create your initial `BubbleInfo`
-
-Use `BubbleInfo.builder()` to populate a `BubbleInfo` with your color, main
-icon, main Intent (which should navigate back to your app), starting Y position,
-and a list of `Actions` to put in the drawer. Each `Action` will define its
-icon, user-displayable name (used for content description), Intent to perform
-when clicked, whether it is enabled (optional, default true), and whether it is
-checked (optional, default false).
-
-![Floating bubble expanded](images/bubble_expanded.png){height=400}
-
-## Create, show, and hide the Bubble
-
-Create the bubble using `Bubble.createBubble(Context, BubbleInfo)`. The `show()`
-method is safe to call at any time. If the Bubble is already showing, it is a
-no-op. `hide()` may also be called at any time and will collapse the drawer
-before hiding if already open. While `show()` will show immediately, `hide()`
-may need to wait for other operations or animations before the bubble is hidden.
-It is unlikely you will need to keep track of this, however. The bubble will be
-hidden at its next opportunity, and `hide()` will not block.
-
-![Floating bubble with state](images/bubble_state.png){height=400}
-
-## Update the Bubble's state
-
-Call `Bubble.setBubbleInfo(BubbleInfo)` to update all displayed state.
-`BubbleInfo`s are immutable, so to make a new one using an existing
-`BubbleInfo`, use `BubbleInfo.from(BubbleInfo)` to get a `Builder` with
-prepopulated info. If only the `Action` state has changed, it is more efficient
-to just call `Bubble.updateActions(List<Action>)`
-
-![Floating bubble with text](images/bubble_text.png){height=400}
-
-## Show text
-
-To temporarily replace the icon with a textual message, call
-`Bubble.showText(CharSequence)`. The text will be displayed for several seconds
-before transitioning back to the primary icon. The drawer will be closed if open
-and cannot be reopened while the text is displayed. Any calls to `hide()` will
-be deferred until after the text is done being displayed, so if you wish to show
-an ending message of some sort you may call `hide()` immediately after
-`showText(CharSequence)`.
diff --git a/java/com/android/dialershared/bubble/g3doc/images/bubble_collapsed.png b/java/com/android/dialershared/bubble/g3doc/images/bubble_collapsed.png
deleted file mode 100644
index 7ecc067..0000000
--- a/java/com/android/dialershared/bubble/g3doc/images/bubble_collapsed.png
+++ /dev/null
Binary files differ
diff --git a/java/com/android/dialershared/bubble/g3doc/images/bubble_expanded.png b/java/com/android/dialershared/bubble/g3doc/images/bubble_expanded.png
deleted file mode 100644
index cd477f3..0000000
--- a/java/com/android/dialershared/bubble/g3doc/images/bubble_expanded.png
+++ /dev/null
Binary files differ
diff --git a/java/com/android/dialershared/bubble/g3doc/images/bubble_state.png b/java/com/android/dialershared/bubble/g3doc/images/bubble_state.png
deleted file mode 100644
index 21ca8a8..0000000
--- a/java/com/android/dialershared/bubble/g3doc/images/bubble_state.png
+++ /dev/null
Binary files differ
diff --git a/java/com/android/dialershared/bubble/g3doc/images/bubble_text.png b/java/com/android/dialershared/bubble/g3doc/images/bubble_text.png
deleted file mode 100644
index 9c476dc..0000000
--- a/java/com/android/dialershared/bubble/g3doc/images/bubble_text.png
+++ /dev/null
Binary files differ
diff --git a/java/com/android/incallui/ReturnToCallController.java b/java/com/android/incallui/ReturnToCallController.java
index e54102c..fd48b37 100644
--- a/java/com/android/incallui/ReturnToCallController.java
+++ b/java/com/android/incallui/ReturnToCallController.java
@@ -23,16 +23,16 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
 import android.telecom.CallAudioState;
+import com.android.bubble.Bubble;
+import com.android.bubble.Bubble.BubbleExpansionStateListener;
+import com.android.bubble.Bubble.ExpansionState;
+import com.android.bubble.BubbleInfo;
+import com.android.bubble.BubbleInfo.Action;
 import com.android.dialer.common.LogUtil;
 import com.android.dialer.configprovider.ConfigProviderBindings;
 import com.android.dialer.logging.DialerImpression;
 import com.android.dialer.logging.Logger;
 import com.android.dialer.telecom.TelecomUtil;
-import com.android.dialershared.bubble.Bubble;
-import com.android.dialershared.bubble.Bubble.BubbleExpansionStateListener;
-import com.android.dialershared.bubble.Bubble.ExpansionState;
-import com.android.dialershared.bubble.BubbleInfo;
-import com.android.dialershared.bubble.BubbleInfo.Action;
 import com.android.incallui.InCallPresenter.InCallUiListener;
 import com.android.incallui.audiomode.AudioModeProvider;
 import com.android.incallui.audiomode.AudioModeProvider.AudioModeListener;