Merge "Implement remember this choice in SpeedDialEntry database."
diff --git a/java/com/android/dialer/speeddial/DisambigDialog.java b/java/com/android/dialer/speeddial/DisambigDialog.java
index 6f7403a..0d29a9c 100644
--- a/java/com/android/dialer/speeddial/DisambigDialog.java
+++ b/java/com/android/dialer/speeddial/DisambigDialog.java
@@ -17,42 +17,59 @@
 package com.android.dialer.speeddial;
 
 import android.app.Dialog;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.VisibleForTesting;
+import android.support.annotation.WorkerThread;
 import android.support.v4.app.DialogFragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v7.app.AlertDialog;
 import android.util.ArraySet;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.widget.CheckBox;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import com.android.dialer.callintent.CallInitiationType;
 import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DefaultFutureCallback;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
 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;
 import com.android.dialer.speeddial.database.SpeedDialEntry.Channel;
+import com.android.dialer.speeddial.database.SpeedDialEntryDatabaseHelper;
+import com.android.dialer.speeddial.loader.SpeedDialUiItem;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.List;
 import java.util.Set;
 
 /** Disambiguation dialog for favorite contacts in {@link SpeedDialFragment}. */
 public class DisambigDialog extends DialogFragment {
 
+  @VisibleForTesting public static final String FRAGMENT_TAG = "disambig_dialog";
   private final Set<String> phoneNumbers = new ArraySet<>();
 
+  private SpeedDialUiItem speedDialUiItem;
   @VisibleForTesting public List<Channel> channels;
   @VisibleForTesting public LinearLayout container;
+  private CheckBox rememberThisChoice;
 
   /** Show a disambiguation dialog for a starred contact without a favorite communication avenue. */
-  public static DisambigDialog show(List<Channel> channels, FragmentManager manager) {
+  public static DisambigDialog show(SpeedDialUiItem speedDialUiItem, FragmentManager manager) {
     DisambigDialog dialog = new DisambigDialog();
-    dialog.channels = channels;
-    dialog.show(manager, null);
+    dialog.speedDialUiItem = speedDialUiItem;
+    dialog.channels = speedDialUiItem.channels();
+    dialog.show(manager, FRAGMENT_TAG);
     return dialog;
   }
 
@@ -62,6 +79,7 @@
     // TODO(calderwoodra): set max height of the scrollview. Might need to override onMeasure.
     View view = inflater.inflate(R.layout.disambig_dialog_layout, null, false);
     container = view.findViewById(R.id.communication_avenue_container);
+    rememberThisChoice = view.findViewById(R.id.remember_this_choice_checkbox);
     insertOptions(container.findViewById(R.id.communication_avenue_container), channels);
     return new AlertDialog.Builder(getActivity()).setView(view).create();
   }
@@ -132,7 +150,10 @@
   }
 
   private void onVideoOptionClicked(Channel channel) {
-    // TODO(calderwoodra): save this option if remember is checked
+    if (rememberThisChoice.isChecked()) {
+      setDefaultChannel(getContext().getApplicationContext(), speedDialUiItem, channel);
+    }
+
     if (channel.technology() == Channel.DUO) {
       Logger.get(getContext())
           .logImpression(
@@ -151,9 +172,42 @@
   }
 
   private void onVoiceOptionClicked(Channel channel) {
-    // TODO(calderwoodra): save this option if remember is checked
+    if (rememberThisChoice.isChecked()) {
+      setDefaultChannel(getContext().getApplicationContext(), speedDialUiItem, channel);
+    }
+
     PreCall.start(
         getContext(), new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL));
     dismiss();
   }
+
+  private static void setDefaultChannel(Context appContext, SpeedDialUiItem item, Channel channel) {
+    LogUtil.enterBlock("DisambigDialog.setDefaultChannel");
+    ListenableFuture<Void> future =
+        DialerExecutorComponent.get(appContext)
+            .backgroundExecutor()
+            .submit(
+                () -> {
+                  updateDatabaseEntry(appContext, item, channel);
+                  return null;
+                });
+    Futures.addCallback(
+        future,
+        new DefaultFutureCallback<>(),
+        DialerExecutorComponent.get(appContext).backgroundExecutor());
+  }
+
+  @WorkerThread
+  private static void updateDatabaseEntry(
+      Context appContext, SpeedDialUiItem item, Channel channel) {
+    Assert.isWorkerThread();
+    SpeedDialEntry entry =
+        SpeedDialEntry.builder()
+            .setId(item.speedDialEntryId())
+            .setContactId(item.contactId())
+            .setLookupKey(item.lookupKey())
+            .setDefaultChannel(channel)
+            .build();
+    new SpeedDialEntryDatabaseHelper(appContext).update(ImmutableList.of(entry));
+  }
 }
diff --git a/java/com/android/dialer/speeddial/FavoritesViewHolder.java b/java/com/android/dialer/speeddial/FavoritesViewHolder.java
index 56d9f36..474516e 100644
--- a/java/com/android/dialer/speeddial/FavoritesViewHolder.java
+++ b/java/com/android/dialer/speeddial/FavoritesViewHolder.java
@@ -34,7 +34,6 @@
 import com.android.dialer.speeddial.draghelper.SpeedDialFavoritesViewHolderOnTouchListener;
 import com.android.dialer.speeddial.draghelper.SpeedDialFavoritesViewHolderOnTouchListener.OnTouchFinishCallback;
 import com.android.dialer.speeddial.loader.SpeedDialUiItem;
-import java.util.List;
 
 /** ViewHolder for starred/favorite contacts in {@link SpeedDialFragment}. */
 public class FavoritesViewHolder extends RecyclerView.ViewHolder
@@ -97,7 +96,7 @@
     if (speedDialUiItem.defaultChannel() != null) {
       listener.onClick(speedDialUiItem.defaultChannel());
     } else {
-      listener.onAmbiguousContactClicked(speedDialUiItem.channels());
+      listener.onAmbiguousContactClicked(speedDialUiItem);
     }
   }
 
@@ -117,7 +116,7 @@
   public interface FavoriteContactsListener {
 
     /** Called when the user clicks on a favorite contact that doesn't have a default number. */
-    void onAmbiguousContactClicked(List<Channel> channels);
+    void onAmbiguousContactClicked(SpeedDialUiItem speedDialUiItem);
 
     /** Called when the user clicks on a favorite contact. */
     void onClick(Channel channel);
diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java
index 52d7b7f..c45ec58 100644
--- a/java/com/android/dialer/speeddial/SpeedDialFragment.java
+++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java
@@ -48,7 +48,6 @@
 import com.android.dialer.speeddial.loader.SpeedDialUiItem;
 import com.android.dialer.speeddial.loader.UiItemLoaderComponent;
 import com.google.common.collect.ImmutableList;
-import java.util.List;
 
 /**
  * Fragment for displaying:
@@ -185,8 +184,8 @@
   private final class SpeedDialFavoritesListener implements FavoriteContactsListener {
 
     @Override
-    public void onAmbiguousContactClicked(List<Channel> channels) {
-      DisambigDialog.show(channels, getChildFragmentManager());
+    public void onAmbiguousContactClicked(SpeedDialUiItem speedDialUiItem) {
+      DisambigDialog.show(speedDialUiItem, getChildFragmentManager());
     }
 
     @Override
diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java
index 28c2274..65aa297 100644
--- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java
+++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java
@@ -118,6 +118,15 @@
     return builder.build();
   }
 
+  /**
+   * The id of the corresponding SpeedDialEntry. Null if the UI item does not have an entry, for
+   * example suggested contacts (isStarred() will also be false)
+   *
+   * @see SpeedDialEntry#id()
+   */
+  @Nullable
+  public abstract Long speedDialEntryId();
+
   /** @see android.provider.ContactsContract.Contacts#DISPLAY_NAME */
   public abstract String name();
 
@@ -158,6 +167,9 @@
   @AutoValue.Builder
   public abstract static class Builder {
 
+    /** Set to null if {@link #isStarred()} is false. */
+    public abstract Builder setSpeedDialEntryId(@Nullable Long id);
+
     public abstract Builder setName(String name);
 
     public abstract Builder setContactId(long contactId);
diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
index 9ea84ec..955793d 100644
--- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
+++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
@@ -303,11 +303,24 @@
         SpeedDialUiItem item = SpeedDialUiItem.fromCursor(cursor);
         for (SpeedDialEntry entry : entries) {
           if (entry.contactId() == item.contactId()) {
+            // Update the id to match it's corresponding SpeedDialEntry.
+            SpeedDialUiItem.Builder entrySpeedDialItem =
+                item.toBuilder().setSpeedDialEntryId(entry.id());
+
+            // Preserve the default channel if it didn't change/still exists
+            Channel defaultChannel = entry.defaultChannel();
+            if (defaultChannel != null) {
+              if (item.channels().contains(defaultChannel)
+                  || isValidDuoDefaultChannel(item.channels(), defaultChannel)) {
+                entrySpeedDialItem.setDefaultChannel(defaultChannel);
+              }
+            }
+
             // It's impossible for two contacts to exist with the same contact id, so if this entry
             // was previously matched to a SpeedDialUiItem and is being matched again, something
             // went horribly wrong.
             Assert.checkArgument(
-                map.put(entry, item) == null,
+                map.put(entry, entrySpeedDialItem.build()) == null,
                 "Each SpeedDialEntry only has one correct SpeedDialUiItem");
           }
         }
@@ -321,6 +334,25 @@
     }
   }
 
+  /**
+   * Since we can't check duo reachabliity on background threads, we have to assume the contact is
+   * still duo reachable. So we just check it is and return true if the Duo number is still
+   * associated with the contact.
+   */
+  private static boolean isValidDuoDefaultChannel(
+      ImmutableList<Channel> channels, Channel defaultChannel) {
+    if (defaultChannel.technology() != Channel.DUO) {
+      return false;
+    }
+
+    for (Channel channel : channels) {
+      if (channel.number().equals(defaultChannel.number())) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   @WorkerThread
   private List<SpeedDialUiItem> getStrequentContacts() {
     Assert.isWorkerThread();
diff --git a/java/com/android/dialer/speeddial/res/layout/disambig_dialog_layout.xml b/java/com/android/dialer/speeddial/res/layout/disambig_dialog_layout.xml
index 3562058..ba7b805 100644
--- a/java/com/android/dialer/speeddial/res/layout/disambig_dialog_layout.xml
+++ b/java/com/android/dialer/speeddial/res/layout/disambig_dialog_layout.xml
@@ -61,6 +61,7 @@
         android:id="@+id/remember_this_choice_checkbox"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:minHeight="48dp"
         android:text="@string/speed_dial_remember_this_choice"/>
   </FrameLayout>
 </LinearLayout>
\ No newline at end of file