Loading java/com/android/dialer/speeddial/DisambigDialog.java +59 −5 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -62,6 +79,7 @@ public class DisambigDialog extends DialogFragment { // 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(); } Loading Loading @@ -132,7 +150,10 @@ public class DisambigDialog extends DialogFragment { } 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( Loading @@ -151,9 +172,42 @@ public class DisambigDialog extends DialogFragment { } 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)); } } java/com/android/dialer/speeddial/FavoritesViewHolder.java +2 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import com.android.dialer.speeddial.database.SpeedDialEntry.Channel; 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 Loading Loading @@ -97,7 +96,7 @@ public class FavoritesViewHolder extends RecyclerView.ViewHolder if (speedDialUiItem.defaultChannel() != null) { listener.onClick(speedDialUiItem.defaultChannel()); } else { listener.onAmbiguousContactClicked(speedDialUiItem.channels()); listener.onAmbiguousContactClicked(speedDialUiItem); } } Loading @@ -117,7 +116,7 @@ public class FavoritesViewHolder extends RecyclerView.ViewHolder 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); Loading java/com/android/dialer/speeddial/SpeedDialFragment.java +2 −3 Original line number Diff line number Diff line Loading @@ -48,7 +48,6 @@ import com.android.dialer.speeddial.draghelper.SpeedDialLayoutManager; 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: Loading Loading @@ -185,8 +184,8 @@ public class SpeedDialFragment extends Fragment { 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 Loading java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java +12 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,15 @@ public abstract class SpeedDialUiItem { 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(); Loading Loading @@ -158,6 +167,9 @@ public abstract class SpeedDialUiItem { @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); Loading java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java +33 −1 Original line number Diff line number Diff line Loading @@ -303,11 +303,24 @@ public final class SpeedDialUiItemLoader { 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"); } } Loading @@ -321,6 +334,25 @@ public final class SpeedDialUiItemLoader { } } /** * 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(); Loading Loading
java/com/android/dialer/speeddial/DisambigDialog.java +59 −5 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -62,6 +79,7 @@ public class DisambigDialog extends DialogFragment { // 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(); } Loading Loading @@ -132,7 +150,10 @@ public class DisambigDialog extends DialogFragment { } 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( Loading @@ -151,9 +172,42 @@ public class DisambigDialog extends DialogFragment { } 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)); } }
java/com/android/dialer/speeddial/FavoritesViewHolder.java +2 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import com.android.dialer.speeddial.database.SpeedDialEntry.Channel; 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 Loading Loading @@ -97,7 +96,7 @@ public class FavoritesViewHolder extends RecyclerView.ViewHolder if (speedDialUiItem.defaultChannel() != null) { listener.onClick(speedDialUiItem.defaultChannel()); } else { listener.onAmbiguousContactClicked(speedDialUiItem.channels()); listener.onAmbiguousContactClicked(speedDialUiItem); } } Loading @@ -117,7 +116,7 @@ public class FavoritesViewHolder extends RecyclerView.ViewHolder 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); Loading
java/com/android/dialer/speeddial/SpeedDialFragment.java +2 −3 Original line number Diff line number Diff line Loading @@ -48,7 +48,6 @@ import com.android.dialer.speeddial.draghelper.SpeedDialLayoutManager; 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: Loading Loading @@ -185,8 +184,8 @@ public class SpeedDialFragment extends Fragment { 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 Loading
java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java +12 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,15 @@ public abstract class SpeedDialUiItem { 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(); Loading Loading @@ -158,6 +167,9 @@ public abstract class SpeedDialUiItem { @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); Loading
java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java +33 −1 Original line number Diff line number Diff line Loading @@ -303,11 +303,24 @@ public final class SpeedDialUiItemLoader { 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"); } } Loading @@ -321,6 +334,25 @@ public final class SpeedDialUiItemLoader { } } /** * 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(); Loading