Added duo channels to favorite contacts and duo suggestions.

Bug: 36841782,77724710,77760800
Test: SpeedDialUiItemLoaderTest
PiperOrigin-RevId: 193432314
Change-Id: If9e0aa05b1aeb266960281ac13218091882ff4c3
diff --git a/java/com/android/dialer/logging/dialer_impression.proto b/java/com/android/dialer/logging/dialer_impression.proto
index a0e36f3..cc65bf9 100644
--- a/java/com/android/dialer/logging/dialer_impression.proto
+++ b/java/com/android/dialer/logging/dialer_impression.proto
@@ -12,7 +12,7 @@
   // Event enums to be used for Impression Logging in Dialer.
   // It's perfectly acceptable for this enum to be large
   // Values should be from 1000 to 100000.
-  // Next Tag: 1376
+  // Next Tag: 1379
   enum Type {
     UNKNOWN_AOSP_EVENT_TYPE = 1000;
 
@@ -741,5 +741,10 @@
     TOKEN_FETCHER_CLEAR_EXCEPTION = 1374;
 
     PEOPLE_API_LOOKUP_FAILED = 1375;
+
+    // New Speed Dial impressions
+    LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT = 1376;
+    LIGHTBRINGER_VIDEO_REQUESTED_FOR_SUGGESTED_CONTACT = 1377;
+    LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT_DISAMBIG = 1378;
   }
 }
diff --git a/java/com/android/dialer/speeddial/DisambigDialog.java b/java/com/android/dialer/speeddial/DisambigDialog.java
index 2a82002..6f7403a 100644
--- a/java/com/android/dialer/speeddial/DisambigDialog.java
+++ b/java/com/android/dialer/speeddial/DisambigDialog.java
@@ -17,6 +17,7 @@
 package com.android.dialer.speeddial;
 
 import android.app.Dialog;
+import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.VisibleForTesting;
 import android.support.v4.app.DialogFragment;
@@ -30,6 +31,10 @@
 import android.widget.TextView;
 import com.android.dialer.callintent.CallInitiationType;
 import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.constants.ActivityRequestCodes;
+import com.android.dialer.duo.DuoComponent;
+import com.android.dialer.logging.DialerImpression;
+import com.android.dialer.logging.Logger;
 import com.android.dialer.precall.PreCall;
 import com.android.dialer.speeddial.database.SpeedDialEntry.Channel;
 import java.util.List;
@@ -128,7 +133,16 @@
 
   private void onVideoOptionClicked(Channel channel) {
     // TODO(calderwoodra): save this option if remember is checked
-    // TODO(calderwoodra): place a duo call if possible
+    if (channel.technology() == Channel.DUO) {
+      Logger.get(getContext())
+          .logImpression(
+              DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT_DISAMBIG);
+      Intent intent =
+          DuoComponent.get(getContext()).getDuo().getIntent(getContext(), channel.number());
+      getActivity().startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO);
+      return;
+    }
+
     PreCall.start(
         getContext(),
         new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL)
diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java
index b58d4ab..004588e 100644
--- a/java/com/android/dialer/speeddial/SpeedDialFragment.java
+++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java
@@ -31,6 +31,10 @@
 import com.android.dialer.common.LogUtil;
 import com.android.dialer.common.concurrent.DialerExecutorComponent;
 import com.android.dialer.common.concurrent.SupportUiListener;
+import com.android.dialer.constants.ActivityRequestCodes;
+import com.android.dialer.duo.DuoComponent;
+import com.android.dialer.logging.DialerImpression;
+import com.android.dialer.logging.Logger;
 import com.android.dialer.precall.PreCall;
 import com.android.dialer.speeddial.ContextMenu.ContextMenuItemListener;
 import com.android.dialer.speeddial.FavoritesViewHolder.FavoriteContactsListener;
@@ -123,7 +127,10 @@
         getContext(),
         UiItemLoaderComponent.get(getContext()).speedDialUiItemLoader().loadSpeedDialUiItems(),
         speedDialUiItems -> {
-          adapter.setSpeedDialUiItems(speedDialUiItems);
+          adapter.setSpeedDialUiItems(
+              UiItemLoaderComponent.get(getContext())
+                  .speedDialUiItemLoader()
+                  .insertDuoChannels(getContext(), speedDialUiItems));
           adapter.notifyDataSetChanged();
         },
         throwable -> {
@@ -148,7 +155,15 @@
 
     @Override
     public void onClick(Channel channel) {
-      // TODO(calderwoodra): add logic for duo video calls
+      if (channel.technology() == Channel.DUO) {
+        Logger.get(getContext())
+            .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT);
+        Intent intent =
+            DuoComponent.get(getContext()).getDuo().getIntent(getContext(), channel.number());
+        getActivity().startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO);
+        return;
+      }
+
       PreCall.start(
           getContext(),
           new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL)
@@ -181,14 +196,25 @@
   private final class SpeedDialSuggestedListener implements SuggestedContactsListener {
 
     @Override
-    public void onOverFlowMenuClicked(String number) {
+    public void onOverFlowMenuClicked(SpeedDialUiItem speedDialUiItem) {
       // TODO(calderwoodra) show overflow menu for suggested contacts
     }
 
     @Override
-    public void onRowClicked(String number) {
+    public void onRowClicked(Channel channel) {
+      if (channel.technology() == Channel.DUO) {
+        Logger.get(getContext())
+            .logImpression(
+                DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_SUGGESTED_CONTACT);
+        Intent intent =
+            DuoComponent.get(getContext()).getDuo().getIntent(getContext(), channel.number());
+        getActivity().startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO);
+        return;
+      }
       PreCall.start(
-          getContext(), new CallIntentBuilder(number, CallInitiationType.Type.SPEED_DIAL));
+          getContext(),
+          new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL)
+              .setIsVideoCall(channel.isVideoTechnology()));
     }
   }
 
diff --git a/java/com/android/dialer/speeddial/SuggestionViewHolder.java b/java/com/android/dialer/speeddial/SuggestionViewHolder.java
index 9e4c81d..546ffbd 100644
--- a/java/com/android/dialer/speeddial/SuggestionViewHolder.java
+++ b/java/com/android/dialer/speeddial/SuggestionViewHolder.java
@@ -29,6 +29,7 @@
 import com.android.dialer.glidephotomanager.PhotoInfo;
 import com.android.dialer.location.GeoUtil;
 import com.android.dialer.phonenumberutil.PhoneNumberHelper;
+import com.android.dialer.speeddial.database.SpeedDialEntry.Channel;
 import com.android.dialer.speeddial.loader.SpeedDialUiItem;
 
 /** ViewHolder for displaying suggested contacts in {@link SpeedDialFragment}. */
@@ -40,7 +41,7 @@
   private final TextView nameOrNumberView;
   private final TextView numberView;
 
-  private String number;
+  private SpeedDialUiItem speedDialUiItem;
 
   SuggestionViewHolder(View view, SuggestedContactsListener listener) {
     super(view);
@@ -54,7 +55,8 @@
 
   public void bind(Context context, SpeedDialUiItem speedDialUiItem) {
     Assert.isNotNull(speedDialUiItem.defaultChannel());
-    number =
+    this.speedDialUiItem = speedDialUiItem;
+    String number =
         PhoneNumberHelper.formatNumber(
             context,
             speedDialUiItem.defaultChannel().number(),
@@ -77,6 +79,7 @@
                 .setPhotoId(speedDialUiItem.photoId())
                 .setPhotoUri(speedDialUiItem.photoUri())
                 .setName(speedDialUiItem.name())
+                .setIsVideo(speedDialUiItem.defaultChannel().isVideoTechnology())
                 .setLookupUri(
                     Contacts.getLookupUri(speedDialUiItem.contactId(), speedDialUiItem.lookupKey())
                         .toString())
@@ -86,18 +89,18 @@
   @Override
   public void onClick(View v) {
     if (v.getId() == R.id.overflow) {
-      listener.onOverFlowMenuClicked(number);
+      listener.onOverFlowMenuClicked(speedDialUiItem);
     } else {
-      listener.onRowClicked(number);
+      listener.onRowClicked(speedDialUiItem.defaultChannel());
     }
   }
 
   /** Listener/Callback for {@link SuggestionViewHolder} parents. */
   public interface SuggestedContactsListener {
 
-    void onOverFlowMenuClicked(String number);
+    void onOverFlowMenuClicked(SpeedDialUiItem speedDialUiItem);
 
     /** Called when a suggested contact is clicked. */
-    void onRowClicked(String number);
+    void onRowClicked(Channel channel);
   }
 }
diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
index 3149480..9a027de 100644
--- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
+++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
@@ -24,6 +24,7 @@
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.Contacts;
+import android.support.annotation.MainThread;
 import android.support.annotation.WorkerThread;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -33,8 +34,11 @@
 import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
 import com.android.dialer.common.concurrent.DialerFutureSerializer;
 import com.android.dialer.common.database.Selection;
+import com.android.dialer.duo.Duo;
+import com.android.dialer.duo.DuoComponent;
 import com.android.dialer.inject.ApplicationContext;
 import com.android.dialer.speeddial.database.SpeedDialEntry;
+import com.android.dialer.speeddial.database.SpeedDialEntry.Channel;
 import com.android.dialer.speeddial.database.SpeedDialEntryDao;
 import com.android.dialer.speeddial.database.SpeedDialEntryDatabaseHelper;
 import com.google.common.collect.ImmutableList;
@@ -72,6 +76,8 @@
 @Singleton
 public final class SpeedDialUiItemLoader {
 
+  private static final int MAX_DUO_SUGGESTIONS = 3;
+
   private final Context appContext;
   private final ListeningExecutorService backgroundExecutor;
   // Used to ensure that only one refresh flow runs at a time.
@@ -320,4 +326,70 @@
       return contacts;
     }
   }
+
+  /**
+   * Returns a new list with duo reachable channels inserted. Duo channels won't replace ViLTE
+   * channels.
+   */
+  @MainThread
+  public ImmutableList<SpeedDialUiItem> insertDuoChannels(
+      Context context, ImmutableList<SpeedDialUiItem> speedDialUiItems) {
+    Assert.isMainThread();
+
+    Duo duo = DuoComponent.get(context).getDuo();
+    int maxDuoSuggestions = MAX_DUO_SUGGESTIONS;
+
+    ImmutableList.Builder<SpeedDialUiItem> newSpeedDialItemList = ImmutableList.builder();
+    // for each existing item
+    for (SpeedDialUiItem item : speedDialUiItems) {
+      // If the item is a suggestion
+      if (!item.isStarred()) {
+        // And duo reachable, insert a duo suggestion
+        if (maxDuoSuggestions > 0 && duo.isReachable(context, item.defaultChannel().number())) {
+          maxDuoSuggestions--;
+          Channel defaultChannel =
+              item.defaultChannel().toBuilder().setTechnology(Channel.DUO).build();
+          newSpeedDialItemList.add(item.toBuilder().setDefaultChannel(defaultChannel).build());
+        }
+        // Insert the voice suggestion too
+        newSpeedDialItemList.add(item);
+      } else if (item.defaultChannel() == null) {
+        // If the contact is starred and doesn't have a default channel, insert duo channels
+        newSpeedDialItemList.add(insertDuoChannelsToStarredContact(context, item));
+      } // if starred and has a default channel, leave it as is, the user knows what they want.
+    }
+    return newSpeedDialItemList.build();
+  }
+
+  @MainThread
+  private SpeedDialUiItem insertDuoChannelsToStarredContact(Context context, SpeedDialUiItem item) {
+    Assert.isMainThread();
+    Assert.checkArgument(item.isStarred());
+
+    // build a new list of channels
+    ImmutableList.Builder<Channel> newChannelsList = ImmutableList.builder();
+    Channel previousChannel = item.channels().get(0);
+    newChannelsList.add(previousChannel);
+
+    for (int i = 1; i < item.channels().size(); i++) {
+      Channel currentChannel = item.channels().get(i);
+      // If the previous and current channel are voice channels, that means the previous number
+      // didn't have a video channel.
+      // If the previous number is duo reachable, insert a duo channel.
+      if (!previousChannel.isVideoTechnology()
+          && !currentChannel.isVideoTechnology()
+          && DuoComponent.get(context).getDuo().isReachable(context, previousChannel.number())) {
+        newChannelsList.add(previousChannel.toBuilder().setTechnology(Channel.DUO).build());
+      }
+      newChannelsList.add(currentChannel);
+      previousChannel = currentChannel;
+    }
+
+    // Check the last channel
+    if (!previousChannel.isVideoTechnology()
+        && DuoComponent.get(context).getDuo().isReachable(context, previousChannel.number())) {
+      newChannelsList.add(previousChannel.toBuilder().setTechnology(Channel.DUO).build());
+    }
+    return item.toBuilder().setChannels(newChannelsList.build()).build();
+  }
 }