Implement remember this choice in SpeedDialEntry database.

In order to connect SpeedDialUiItems to the correct SpeedDialEntry in the
database, we need to pipe the entry ID throgh to the UI item. So this
change includes the logic to pipe the id as well.

Bug: 36841782,77760800
Test: DisambigDialogTest
PiperOrigin-RevId: 193550938
Change-Id: I6ec64d0aec7f85d36555707a54953bfdff938bb5
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