summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/speeddial/loader
diff options
context:
space:
mode:
authorcalderwoodra <calderwoodra@google.com>2018-04-25 17:21:03 -0700
committerCopybara-Service <copybara-piper@google.com>2018-04-25 17:23:09 -0700
commitaa9d670a4f076e52418cd5e404435c524713278e (patch)
tree35906c59b5daccce7f7dacd2ca8a01aaa3dcec5c /java/com/android/dialer/speeddial/loader
parenta0c49f63111f672d91e812370baa0249b69929cd (diff)
Persist contacts pinned positions in speed dial.
Bug: 78491298 Test: WIP PiperOrigin-RevId: 194323952 Change-Id: I6883ce1506684c93cb5538ebbc0e14aecc300a00
Diffstat (limited to 'java/com/android/dialer/speeddial/loader')
-rw-r--r--java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java11
-rw-r--r--java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java (renamed from java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java)91
-rw-r--r--java/com/android/dialer/speeddial/loader/UiItemLoaderComponent.java2
3 files changed, 94 insertions, 10 deletions
diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java
index 9bda3fb31..a2bdfb89a 100644
--- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java
+++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java
@@ -25,6 +25,7 @@ import com.android.dialer.common.Assert;
import com.android.dialer.speeddial.database.SpeedDialEntry;
import com.android.dialer.speeddial.database.SpeedDialEntry.Channel;
import com.google.auto.value.AutoValue;
+import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
@@ -83,7 +84,9 @@ public abstract class SpeedDialUiItem {
}
public static Builder builder() {
- return new AutoValue_SpeedDialUiItem.Builder().setChannels(ImmutableList.of());
+ return new AutoValue_SpeedDialUiItem.Builder()
+ .setChannels(ImmutableList.of())
+ .setPinnedPosition(Optional.absent());
}
/**
@@ -139,6 +142,7 @@ public abstract class SpeedDialUiItem {
public SpeedDialEntry buildSpeedDialEntry() {
return SpeedDialEntry.builder()
.setId(speedDialEntryId())
+ .setPinnedPosition(pinnedPosition())
.setLookupKey(lookupKey())
.setContactId(contactId())
.setDefaultChannel(defaultChannel())
@@ -212,6 +216,9 @@ public abstract class SpeedDialUiItem {
@Nullable
public abstract Long speedDialEntryId();
+ /** @see SpeedDialEntry#pinnedPosition() */
+ public abstract Optional<Integer> pinnedPosition();
+
/** @see android.provider.ContactsContract.Contacts#DISPLAY_NAME */
public abstract String name();
@@ -255,6 +262,8 @@ public abstract class SpeedDialUiItem {
/** Set to null if {@link #isStarred()} is false. */
public abstract Builder setSpeedDialEntryId(@Nullable Long id);
+ public abstract Builder setPinnedPosition(Optional<Integer> pinnedPosition);
+
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/SpeedDialUiItemMutator.java
index 921468773..5dae2efab 100644
--- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
+++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java
@@ -17,11 +17,14 @@
package com.android.dialer.speeddial.loader;
import android.annotation.TargetApi;
+import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.content.Context;
+import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build.VERSION_CODES;
+import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
@@ -43,6 +46,7 @@ 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.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ListenableFuture;
@@ -76,7 +80,7 @@ import javax.inject.Singleton;
@SuppressWarnings("AndroidApiChecker")
@TargetApi(VERSION_CODES.N)
@Singleton
-public final class SpeedDialUiItemLoader {
+public final class SpeedDialUiItemMutator {
private static final int MAX_DUO_SUGGESTIONS = 3;
@@ -87,7 +91,7 @@ public final class SpeedDialUiItemLoader {
private final ContactsPreferences contactsPreferences;
@Inject
- public SpeedDialUiItemLoader(
+ public SpeedDialUiItemMutator(
@ApplicationContext Context appContext,
@BackgroundExecutor ListeningExecutorService backgroundExecutor) {
this.appContext = appContext;
@@ -127,7 +131,7 @@ public final class SpeedDialUiItemLoader {
null,
null)) {
if (cursor == null) {
- LogUtil.e("SpeedDialUiItemLoader.insertNewContactEntry", "Cursor was null");
+ LogUtil.e("SpeedDialUiItemMutator.insertNewContactEntry", "Cursor was null");
return loadSpeedDialUiItemsInternal();
}
Assert.checkArgument(cursor.moveToFirst(), "Cursor should never be empty");
@@ -285,7 +289,7 @@ public final class SpeedDialUiItemLoader {
null,
null)) {
if (cursor == null) {
- LogUtil.e("SpeedDialUiItemLoader.updateContactIdsAndLookupKeys", "null cursor");
+ LogUtil.e("SpeedDialUiItemMutator.updateContactIdsAndLookupKeys", "null cursor");
return new ArrayList<>();
}
if (cursor.getCount() == 0) {
@@ -339,9 +343,11 @@ 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.
+ // Update the id and pinned position to match it's corresponding SpeedDialEntry.
SpeedDialUiItem.Builder entrySpeedDialItem =
- item.toBuilder().setSpeedDialEntryId(entry.id());
+ item.toBuilder()
+ .setSpeedDialEntryId(entry.id())
+ .setPinnedPosition(entry.pinnedPosition());
// Preserve the default channel if it didn't change/still exists
Channel defaultChannel = entry.defaultChannel();
@@ -405,7 +411,7 @@ public final class SpeedDialUiItemLoader {
.getContentResolver()
.query(strequentUri, new String[] {Phone.CONTACT_ID}, null, null, null)) {
if (cursor == null) {
- LogUtil.e("SpeedDialUiItemLoader.getStrequentContacts", "null cursor");
+ LogUtil.e("SpeedDialUiItemMutator.getStrequentContacts", "null cursor");
return new ArrayList<>();
}
if (cursor.getCount() == 0) {
@@ -430,7 +436,7 @@ public final class SpeedDialUiItemLoader {
null)) {
List<SpeedDialUiItem> contacts = new ArrayList<>();
if (cursor == null) {
- LogUtil.e("SpeedDialUiItemLoader.getStrequentContacts", "null cursor");
+ LogUtil.e("SpeedDialUiItemMutator.getStrequentContacts", "null cursor");
return new ArrayList<>();
}
if (cursor.getCount() == 0) {
@@ -444,6 +450,75 @@ public final class SpeedDialUiItemLoader {
}
/**
+ * Persists the position of the {@link SpeedDialUiItem items} as the pinned position according to
+ * the order they were passed in.
+ */
+ @WorkerThread
+ public void updatePinnedPosition(List<SpeedDialUiItem> speedDialUiItems) {
+ Assert.isWorkerThread();
+ if (speedDialUiItems == null || speedDialUiItems.isEmpty()) {
+ return;
+ }
+
+ // Update the positions in the SpeedDialEntry database
+ ImmutableList.Builder<SpeedDialEntry> entriesToUpdate = ImmutableList.builder();
+ for (int i = 0; i < speedDialUiItems.size(); i++) {
+ SpeedDialUiItem item = speedDialUiItems.get(i);
+ if (item.isStarred()) {
+ entriesToUpdate.add(
+ item.buildSpeedDialEntry().toBuilder().setPinnedPosition(Optional.of(i)).build());
+ }
+ }
+ getSpeedDialEntryDao().update(entriesToUpdate.build());
+
+ // Update the positions in CP2
+ // Build a list of SpeedDialUiItems where each contact is only represented once but the order
+ // is maintained. For example, assume you have a list of contacts with contact ids:
+ // > { 1, 1, 2, 1, 2, 3 }
+ // This list will be reduced to:
+ // > { 1, 2, 3 }
+ // and their positions in the resulting list will be written to the CP2 Contacts.PINNED column.
+ List<SpeedDialUiItem> cp2SpeedDialUiItems = new ArrayList<>();
+ Set<Long> contactIds = new ArraySet<>();
+ for (SpeedDialUiItem item : speedDialUiItems) {
+ if (contactIds.add(item.contactId())) {
+ cp2SpeedDialUiItems.add(item);
+ }
+ }
+
+ // Code copied from PhoneFavoritesTileAdapter#handleDrop
+ ArrayList<ContentProviderOperation> operations = new ArrayList<>();
+ for (int i = 0; i < cp2SpeedDialUiItems.size(); i++) {
+ SpeedDialUiItem item = cp2SpeedDialUiItems.get(i);
+ // Pinned positions in the database start from 1 instead of being zero-indexed like
+ // arrays, so offset by 1.
+ int databasePinnedPosition = i + 1;
+ if (item.pinnedPosition().isPresent()
+ && item.pinnedPosition().get() == databasePinnedPosition) {
+ continue;
+ }
+
+ Uri uri = Uri.withAppendedPath(Contacts.CONTENT_URI, String.valueOf(item.contactId()));
+ ContentValues values = new ContentValues();
+ values.put(Contacts.PINNED, databasePinnedPosition);
+ operations.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
+ }
+ if (operations.isEmpty()) {
+ // Nothing to update
+ return;
+ }
+ try {
+ appContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
+ // TODO(calderwoodra): log
+ } catch (RemoteException | OperationApplicationException e) {
+ LogUtil.e(
+ "SpeedDialUiItemMutator.updatePinnedPosition",
+ "Exception thrown when pinning contacts",
+ e);
+ }
+ }
+
+ /**
* Returns a new list with duo reachable channels inserted. Duo channels won't replace ViLTE
* channels.
*/
diff --git a/java/com/android/dialer/speeddial/loader/UiItemLoaderComponent.java b/java/com/android/dialer/speeddial/loader/UiItemLoaderComponent.java
index 7d01b4380..852908409 100644
--- a/java/com/android/dialer/speeddial/loader/UiItemLoaderComponent.java
+++ b/java/com/android/dialer/speeddial/loader/UiItemLoaderComponent.java
@@ -24,7 +24,7 @@ import dagger.Subcomponent;
@Subcomponent
public abstract class UiItemLoaderComponent {
- public abstract SpeedDialUiItemLoader speedDialUiItemLoader();
+ public abstract SpeedDialUiItemMutator speedDialUiItemMutator();
public static UiItemLoaderComponent get(Context context) {
return ((UiItemLoaderComponent.HasComponent)