Add avatar and small icon in bubble primary button.

Bug: 67605985
Test: NewBubbleIntegrationTest, NewReturnToCallControllerTest
PiperOrigin-RevId: 174089572
Change-Id: Icaeb41482cffe522e09ee1ec068b5d47f476b146
diff --git a/java/com/android/newbubble/NewBubble.java b/java/com/android/newbubble/NewBubble.java
index d9b9ae2..226326f 100644
--- a/java/com/android/newbubble/NewBubble.java
+++ b/java/com/android/newbubble/NewBubble.java
@@ -57,6 +57,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 import android.widget.ViewAnimator;
+import com.android.dialer.util.DrawableConverter;
 import com.android.newbubble.NewBubbleInfo.Action;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -113,7 +114,10 @@
             hideAndReset();
           } else {
             doResize(
-                () -> viewHolder.getPrimaryButton().setDisplayedChild(ViewHolder.CHILD_INDEX_ICON));
+                () ->
+                    viewHolder
+                        .getPrimaryButton()
+                        .setDisplayedChild(ViewHolder.CHILD_INDEX_AVATAR_AND_ICON));
           }
         }
       };
@@ -351,6 +355,32 @@
     updateButtonStates();
   }
 
+  /**
+   * Update the avatar from photo.
+   *
+   * @param avatar the new photo avatar in the bubble's primary button
+   */
+  public void updatePhotoAvatar(@NonNull Drawable avatar) {
+    // Make it round
+    int bubbleSize = context.getResources().getDimensionPixelSize(R.dimen.bubble_size);
+    Drawable roundAvatar =
+        DrawableConverter.getRoundedDrawable(context, avatar, bubbleSize, bubbleSize);
+
+    updateAvatar(roundAvatar);
+  }
+
+  /**
+   * Update the avatar.
+   *
+   * @param avatar the new avatar in the bubble's primary button
+   */
+  public void updateAvatar(@NonNull Drawable avatar) {
+    if (!avatar.equals(currentInfo.getAvatar())) {
+      currentInfo = NewBubbleInfo.from(currentInfo).setAvatar(avatar).build();
+      viewHolder.getPrimaryAvatar().setImageDrawable(currentInfo.getAvatar());
+    }
+  }
+
   /** Returns the currently displayed NewBubbleInfo */
   public NewBubbleInfo getBubbleInfo() {
     return currentInfo;
@@ -525,6 +555,7 @@
   }
 
   private void update() {
+    // Whole primary button background
     RippleDrawable backgroundRipple =
         (RippleDrawable)
             context.getResources().getDrawable(R.drawable.bubble_ripple_circle, context.getTheme());
@@ -532,12 +563,23 @@
         ColorUtils.compositeColors(
             context.getColor(R.color.bubble_primary_background_darken),
             currentInfo.getPrimaryColor());
-    backgroundRipple.getDrawable(0).setTint(primaryTint);
+    backgroundRipple.getDrawable(0).mutate().setTint(primaryTint);
     viewHolder.getPrimaryButton().setBackground(backgroundRipple);
 
+    // Small icon
+    RippleDrawable smallIconBackgroundRipple =
+        (RippleDrawable)
+            context
+                .getResources()
+                .getDrawable(R.drawable.bubble_ripple_circle_small, context.getTheme());
+    smallIconBackgroundRipple
+        .getDrawable(0)
+        .setTint(context.getColor(R.color.bubble_button_text_color_blue));
+    viewHolder.getPrimaryIcon().setBackground(smallIconBackgroundRipple);
     viewHolder.getPrimaryIcon().setImageIcon(currentInfo.getPrimaryIcon());
-    updatePrimaryIconAnimation();
+    viewHolder.getPrimaryAvatar().setImageDrawable(currentInfo.getAvatar());
 
+    updatePrimaryIconAnimation();
     updateButtonStates();
   }
 
@@ -715,13 +757,14 @@
   @VisibleForTesting
   class ViewHolder {
 
-    public static final int CHILD_INDEX_ICON = 0;
+    public static final int CHILD_INDEX_AVATAR_AND_ICON = 0;
     public static final int CHILD_INDEX_TEXT = 1;
 
     private final NewMoveHandler moveHandler;
     private final NewWindowRoot root;
     private final ViewAnimator primaryButton;
     private final ImageView primaryIcon;
+    private final ImageView primaryAvatar;
     private final TextView primaryText;
 
     private final NewCheckableButton fullScreenButton;
@@ -737,6 +780,7 @@
       View contentView = inflater.inflate(R.layout.new_bubble_base, root, true);
       expandedView = contentView.findViewById(R.id.bubble_expanded_layout);
       primaryButton = contentView.findViewById(R.id.bubble_button_primary);
+      primaryAvatar = contentView.findViewById(R.id.bubble_icon_avatar);
       primaryIcon = contentView.findViewById(R.id.bubble_icon_primary);
       primaryText = contentView.findViewById(R.id.bubble_text);
 
@@ -793,6 +837,10 @@
       return primaryIcon;
     }
 
+    public ImageView getPrimaryAvatar() {
+      return primaryAvatar;
+    }
+
     public TextView getPrimaryText() {
       return primaryText;
     }
diff --git a/java/com/android/newbubble/NewBubbleInfo.java b/java/com/android/newbubble/NewBubbleInfo.java
index f615929..44232f3 100644
--- a/java/com/android/newbubble/NewBubbleInfo.java
+++ b/java/com/android/newbubble/NewBubbleInfo.java
@@ -35,6 +35,9 @@
 
   public abstract Icon getPrimaryIcon();
 
+  @Nullable
+  public abstract Drawable getAvatar();
+
   @Px
   public abstract int getStartingYPosition();
 
@@ -61,6 +64,8 @@
 
     public abstract Builder setPrimaryIcon(@NonNull Icon primaryIcon);
 
+    public abstract Builder setAvatar(@Nullable Drawable avatar);
+
     public abstract Builder setStartingYPosition(@Px int startingYPosition);
 
     public abstract Builder setActions(List<Action> actions);
diff --git a/java/com/android/newbubble/res/drawable/bubble_ripple_circle_small.xml b/java/com/android/newbubble/res/drawable/bubble_ripple_circle_small.xml
new file mode 100644
index 0000000..109d1ce
--- /dev/null
+++ b/java/com/android/newbubble/res/drawable/bubble_ripple_circle_small.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:colorControlHighlight">
+  <item>
+    <shape>
+      <corners android:radius="@dimen/bubble_small_icon_size"/>
+      <solid android:color="@android:color/white"/>
+    </shape>
+  </item>
+</ripple>
diff --git a/java/com/android/newbubble/res/layout/new_bubble_base.xml b/java/com/android/newbubble/res/layout/new_bubble_base.xml
index ef35d74..9174f3f 100644
--- a/java/com/android/newbubble/res/layout/new_bubble_base.xml
+++ b/java/com/android/newbubble/res/layout/new_bubble_base.xml
@@ -36,14 +36,28 @@
         android:background="@drawable/bubble_ripple_circle"
         android:measureAllChildren="false"
         tools:backgroundTint="#FF0000AA">
-      <ImageView
-          android:id="@+id/bubble_icon_primary"
-          android:layout_width="@dimen/bubble_size"
-          android:layout_height="@dimen/bubble_size"
-          android:padding="@dimen/bubble_icon_padding"
-          android:tint="@android:color/white"
-          android:tintMode="src_in"
-          tools:src="@android:drawable/ic_btn_speak_now"/>
+      <RelativeLayout
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content">
+        <ImageView
+            android:id="@+id/bubble_icon_avatar"
+            android:layout_width="@dimen/bubble_size"
+            android:layout_height="@dimen/bubble_size"
+            tools:src="@android:drawable/ic_btn_speak_now"/>
+        <ImageView
+            android:id="@+id/bubble_icon_primary"
+            android:layout_width="@dimen/bubble_small_icon_size"
+            android:layout_height="@dimen/bubble_small_icon_size"
+            android:layout_alignBottom="@id/bubble_icon_avatar"
+            android:layout_alignEnd="@id/bubble_icon_avatar"
+            android:padding="@dimen/bubble_small_icon_padding"
+            android:tint="@android:color/white"
+            android:tintMode="src_in"
+            android:background="@drawable/bubble_ripple_circle_small"
+            android:measureAllChildren="false"
+            tools:backgroundTint="#FF0000AA"
+            tools:src="@android:drawable/ic_btn_speak_now"/>
+      </RelativeLayout>
       <TextView
           android:id="@+id/bubble_text"
           android:layout_width="wrap_content"
diff --git a/java/com/android/newbubble/res/values/values.xml b/java/com/android/newbubble/res/values/values.xml
index 4bb90af..381b007 100644
--- a/java/com/android/newbubble/res/values/values.xml
+++ b/java/com/android/newbubble/res/values/values.xml
@@ -20,6 +20,7 @@
   <dimen name="bubble_icon_padding">16dp</dimen>
   <dimen name="bubble_move_elevation_change">4dp</dimen>
 
+  <dimen name="bubble_button_icon_padding">16dp</dimen>
   <dimen name="bubble_safe_margin_horizontal">-4dp</dimen>
   <dimen name="bubble_safe_margin_vertical">64dp</dimen>
   <dimen name="bubble_shadow_padding_size_vertical">16dp</dimen>
@@ -29,4 +30,6 @@
   <dimen name="bubble_expanded_width">160dp</dimen>
   <dimen name="bubble_radius">20dp</dimen>
   <dimen name="bubble_expanded_separator_height">4dp</dimen>
+  <dimen name="bubble_small_icon_size">24dp</dimen>
+  <dimen name="bubble_small_icon_padding">4dp</dimen>
 </resources>