summaryrefslogtreecommitdiff
path: root/java/com
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2017-11-03 02:07:32 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-11-03 02:07:32 +0000
commit6eec20f5c5a56177f050b1490e2ba198748c0fd4 (patch)
treeab82401c5c33c58ecf534fc73962405f8af94122 /java/com
parent9ebcbef57c9c694f2ab1c357b6b6356d0aa0d143 (diff)
parenta5a08d8890b08ac1fde8ccaf333fe33c69333ae5 (diff)
Merge "Add avatar and small icon in bubble primary button."
Diffstat (limited to 'java/com')
-rw-r--r--java/com/android/incallui/InCallServiceImpl.java3
-rw-r--r--java/com/android/incallui/NewReturnToCallController.java99
-rw-r--r--java/com/android/newbubble/NewBubble.java56
-rw-r--r--java/com/android/newbubble/NewBubbleInfo.java5
-rw-r--r--java/com/android/newbubble/res/drawable/bubble_ripple_circle_small.xml26
-rw-r--r--java/com/android/newbubble/res/layout/new_bubble_base.xml30
-rw-r--r--java/com/android/newbubble/res/values/values.xml3
7 files changed, 208 insertions, 14 deletions
diff --git a/java/com/android/incallui/InCallServiceImpl.java b/java/com/android/incallui/InCallServiceImpl.java
index 402e0021f..539dba8dd 100644
--- a/java/com/android/incallui/InCallServiceImpl.java
+++ b/java/com/android/incallui/InCallServiceImpl.java
@@ -99,7 +99,8 @@ public class InCallServiceImpl extends InCallService {
returnToCallController = new ReturnToCallController(this);
}
if (NewReturnToCallController.isEnabled(this)) {
- newReturnToCallController = new NewReturnToCallController(this);
+ newReturnToCallController =
+ new NewReturnToCallController(this, ContactInfoCache.getInstance(context));
}
IBinder iBinder = super.onBind(intent);
diff --git a/java/com/android/incallui/NewReturnToCallController.java b/java/com/android/incallui/NewReturnToCallController.java
index cd69ea1be..fa7a45de0 100644
--- a/java/com/android/incallui/NewReturnToCallController.java
+++ b/java/com/android/incallui/NewReturnToCallController.java
@@ -19,15 +19,21 @@ package com.android.incallui;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.telecom.CallAudioState;
+import android.text.TextUtils;
+import com.android.contacts.common.util.ContactDisplayUtils;
import com.android.dialer.common.LogUtil;
import com.android.dialer.configprovider.ConfigProviderBindings;
+import com.android.dialer.lettertile.LetterTileDrawable;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.telecom.TelecomUtil;
+import com.android.incallui.ContactInfoCache.ContactCacheEntry;
+import com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
import com.android.incallui.InCallPresenter.InCallUiListener;
import com.android.incallui.audiomode.AudioModeProvider;
import com.android.incallui.audiomode.AudioModeProvider.AudioModeListener;
@@ -41,6 +47,7 @@ import com.android.newbubble.NewBubble.BubbleExpansionStateListener;
import com.android.newbubble.NewBubble.ExpansionState;
import com.android.newbubble.NewBubbleInfo;
import com.android.newbubble.NewBubbleInfo.Action;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -65,12 +72,15 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au
private final PendingIntent endCall;
private final PendingIntent fullScreen;
+ private final ContactInfoCache contactInfoCache;
+
public static boolean isEnabled(Context context) {
return ConfigProviderBindings.get(context).getBoolean("enable_return_to_call_bubble_v2", false);
}
- public NewReturnToCallController(Context context) {
+ public NewReturnToCallController(Context context, ContactInfoCache contactInfoCache) {
this.context = context;
+ this.contactInfoCache = contactInfoCache;
toggleSpeaker = createActionIntent(ReturnToCallActionReceiver.ACTION_TOGGLE_SPEAKER);
showSpeakerSelect =
@@ -130,6 +140,7 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au
} else {
bubble.show();
}
+ startContactInfoSearch();
}
@VisibleForTesting
@@ -213,6 +224,8 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au
// parent call is still there.
if (!CallList.getInstance().hasNonParentActiveOrBackgroundCall()) {
hideAndReset();
+ } else {
+ startContactInfoSearch();
}
}
@@ -233,6 +246,22 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au
}
}
+ private void startContactInfoSearch() {
+ DialerCall dialerCall = CallList.getInstance().getActiveOrBackgroundCall();
+ if (dialerCall != null) {
+ contactInfoCache.findInfo(
+ dialerCall, false /* isIncoming */, new ReturnToCallContactInfoCacheCallback(this));
+ }
+ }
+
+ private void onPhotoAvatarReceived(@NonNull Drawable photo) {
+ bubble.updatePhotoAvatar(photo);
+ }
+
+ private void onLetterTileAvatarReceived(@NonNull Drawable photo) {
+ bubble.updateAvatar(photo);
+ }
+
private NewBubbleInfo generateBubbleInfo() {
return NewBubbleInfo.builder()
.setPrimaryColor(context.getResources().getColor(R.color.dialer_theme_color, null))
@@ -280,4 +309,72 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au
toggleSpeaker.setAction(action);
return PendingIntent.getBroadcast(context, 0, toggleSpeaker, 0);
}
+
+ @NonNull
+ private LetterTileDrawable createLettleTileDrawable(
+ DialerCall dialerCall, ContactCacheEntry entry) {
+ String preferredName =
+ ContactDisplayUtils.getPreferredDisplayName(
+ entry.namePrimary,
+ entry.nameAlternative,
+ ContactsPreferencesFactory.newContactsPreferences(context));
+ if (TextUtils.isEmpty(preferredName)) {
+ preferredName = entry.number;
+ }
+
+ LetterTileDrawable letterTile = new LetterTileDrawable(context.getResources());
+ letterTile.setCanonicalDialerLetterTileDetails(
+ dialerCall.updateNameIfRestricted(preferredName),
+ entry.lookupKey,
+ LetterTileDrawable.SHAPE_CIRCLE,
+ LetterTileDrawable.getContactTypeFromPrimitives(
+ dialerCall.isVoiceMailNumber(),
+ dialerCall.isSpam(),
+ entry.isBusiness,
+ dialerCall.getNumberPresentation(),
+ dialerCall.isConferenceCall()));
+ return letterTile;
+ }
+
+ private static class ReturnToCallContactInfoCacheCallback implements ContactInfoCacheCallback {
+
+ private final WeakReference<NewReturnToCallController> newReturnToCallControllerWeakReference;
+
+ private ReturnToCallContactInfoCacheCallback(
+ NewReturnToCallController newReturnToCallController) {
+ newReturnToCallControllerWeakReference = new WeakReference<>(newReturnToCallController);
+ }
+
+ @Override
+ public void onContactInfoComplete(String callId, ContactCacheEntry entry) {
+ NewReturnToCallController newReturnToCallController =
+ newReturnToCallControllerWeakReference.get();
+ if (newReturnToCallController == null) {
+ return;
+ }
+ if (entry.photo != null) {
+ newReturnToCallController.onPhotoAvatarReceived(entry.photo);
+ } else {
+ DialerCall dialerCall = CallList.getInstance().getCallById(callId);
+ newReturnToCallController.onLetterTileAvatarReceived(
+ newReturnToCallController.createLettleTileDrawable(dialerCall, entry));
+ }
+ }
+
+ @Override
+ public void onImageLoadComplete(String callId, ContactCacheEntry entry) {
+ NewReturnToCallController newReturnToCallController =
+ newReturnToCallControllerWeakReference.get();
+ if (newReturnToCallController == null) {
+ return;
+ }
+ if (entry.photo != null) {
+ newReturnToCallController.onPhotoAvatarReceived(entry.photo);
+ } else {
+ DialerCall dialerCall = CallList.getInstance().getCallById(callId);
+ newReturnToCallController.onLetterTileAvatarReceived(
+ newReturnToCallController.createLettleTileDrawable(dialerCall, entry));
+ }
+ }
+ }
}
diff --git a/java/com/android/newbubble/NewBubble.java b/java/com/android/newbubble/NewBubble.java
index d9b9ae2ad..226326f3c 100644
--- a/java/com/android/newbubble/NewBubble.java
+++ b/java/com/android/newbubble/NewBubble.java
@@ -57,6 +57,7 @@ import android.view.animation.OvershootInterpolator;
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 @@ public class NewBubble {
hideAndReset();
} else {
doResize(
- () -> viewHolder.getPrimaryButton().setDisplayedChild(ViewHolder.CHILD_INDEX_ICON));
+ () ->
+ viewHolder
+ .getPrimaryButton()
+ .setDisplayedChild(ViewHolder.CHILD_INDEX_AVATAR_AND_ICON));
}
}
};
@@ -351,6 +355,32 @@ public class NewBubble {
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 @@ public class NewBubble {
}
private void update() {
+ // Whole primary button background
RippleDrawable backgroundRipple =
(RippleDrawable)
context.getResources().getDrawable(R.drawable.bubble_ripple_circle, context.getTheme());
@@ -532,12 +563,23 @@ public class NewBubble {
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 @@ public class NewBubble {
@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 @@ public class NewBubble {
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 @@ public class NewBubble {
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 f615929e3..44232f39b 100644
--- a/java/com/android/newbubble/NewBubbleInfo.java
+++ b/java/com/android/newbubble/NewBubbleInfo.java
@@ -35,6 +35,9 @@ public abstract class NewBubbleInfo {
public abstract Icon getPrimaryIcon();
+ @Nullable
+ public abstract Drawable getAvatar();
+
@Px
public abstract int getStartingYPosition();
@@ -61,6 +64,8 @@ public abstract class NewBubbleInfo {
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 000000000..109d1cec1
--- /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 ef35d7426..9174f3fdb 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 4bb90aff0..381b0079e 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>