summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java5
-rw-r--r--java/com/android/dialer/calllog/ui/NewCallLogAdapter.java4
-rw-r--r--java/com/android/dialer/calllog/ui/NewCallLogFragment.java10
-rw-r--r--java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java30
-rw-r--r--java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java17
-rw-r--r--java/com/android/dialer/phonelookup/cp2/Cp2LocalPhoneLookup.java7
6 files changed, 43 insertions, 30 deletions
diff --git a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
index 1d4a35a6c..a0874f0cd 100644
--- a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
@@ -280,7 +280,10 @@ public final class PhoneLookupDataSource
PhoneLookupHistory.contentUriForNumber(normalizedNumber))
.build());
}
- appContext.getContentResolver().applyBatch(PhoneLookupHistoryContract.AUTHORITY, operations);
+ Assert.isNotNull(
+ appContext
+ .getContentResolver()
+ .applyBatch(PhoneLookupHistoryContract.AUTHORITY, operations));
return null;
}
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java b/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java
index 24324b073..5618c4d16 100644
--- a/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java
+++ b/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java
@@ -70,6 +70,10 @@ final class NewCallLogAdapter extends RecyclerView.Adapter<ViewHolder> {
notifyDataSetChanged();
}
+ void clearCache() {
+ this.realtimeRowProcessor.clearCache();
+ }
+
private void setHeaderPositions() {
// Calculate header adapter positions by reading cursor.
long currentTimeMillis = clock.currentTimeMillis();
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
index 6db7c5d6c..10f75ef07 100644
--- a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
+++ b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
@@ -93,6 +93,16 @@ public final class NewCallLogFragment extends Fragment
// TODO(zachh): Consider doing this when fragment becomes visible.
refreshAnnotatedCallLog(true /* checkDirty */);
+
+ // There are some types of data that we show in the call log that are not represented in the
+ // AnnotatedCallLog. For example, CP2 information for invalid numbers can sometimes only be
+ // fetched at display time. Because of this, we need to clear the adapter's cache and update it
+ // whenever the user arrives at the call log (rather than relying on changes to the CursorLoader
+ // alone).
+ if (recyclerView.getAdapter() != null) {
+ ((NewCallLogAdapter) recyclerView.getAdapter()).clearCache();
+ recyclerView.getAdapter().notifyDataSetChanged();
+ }
}
@Override
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
index 2938d083b..a0daae141 100644
--- a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
+++ b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
@@ -38,7 +38,6 @@ import com.android.dialer.compat.telephony.TelephonyManagerCompat;
import com.android.dialer.contactphoto.ContactPhotoManager;
import com.android.dialer.oem.MotorolaUtils;
import com.android.dialer.time.Clock;
-import com.google.common.base.Optional;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import java.util.Locale;
@@ -86,17 +85,17 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
// Even if there is additional real time processing necessary, we still want to immediately show
// what information we have, rather than an empty card. For example, if CP2 information needs to
// be queried on the fly, we can still show the phone number until the contact name loads.
- handleRow(row);
+ displayRow(row);
// Note: This leaks the view holder via the callback (which is an inner class), but this is OK
// because we only create ~10 of them (and they'll be collected assuming all jobs finish).
Futures.addCallback(
realtimeRowProcessor.applyRealtimeProcessing(row),
- new RealtimeRowFutureCallback(row.id()),
+ new RealtimeRowFutureCallback(row),
uiExecutorService);
}
- private void handleRow(CoalescedRow row) {
+ private void displayRow(CoalescedRow row) {
// TODO(zachh): Handle RTL properly.
primaryTextView.setText(CallLogEntryText.buildPrimaryText(context, row));
secondaryTextView.setText(CallLogEntryText.buildSecondaryTextForEntries(context, clock, row));
@@ -189,23 +188,24 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
menuButton.setOnClickListener(NewCallLogMenu.createOnClickListener(context, row));
}
- private class RealtimeRowFutureCallback implements FutureCallback<Optional<CoalescedRow>> {
- private final int id;
+ private class RealtimeRowFutureCallback implements FutureCallback<CoalescedRow> {
+ private final CoalescedRow originalRow;
- RealtimeRowFutureCallback(int id) {
- this.id = id;
+ RealtimeRowFutureCallback(CoalescedRow originalRow) {
+ this.originalRow = originalRow;
}
- /**
- * @param updatedRow the updated row if an update is required, or absent if no updates are
- * required
- */
@Override
- public void onSuccess(Optional<CoalescedRow> updatedRow) {
+ public void onSuccess(CoalescedRow updatedRow) {
// If the user scrolled then this ViewHolder may not correspond to the completed task and
// there's nothing to do.
- if (updatedRow.isPresent() && id == currentRowId) {
- handleRow(updatedRow.get());
+ if (originalRow.id() != currentRowId) {
+ return;
+ }
+ // Only update the UI if the updated row differs from the original row (which has already
+ // been displayed).
+ if (!updatedRow.equals(originalRow)) {
+ displayRow(updatedRow);
}
}
diff --git a/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java b/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java
index 6e214edc4..57ad9657c 100644
--- a/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java
+++ b/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java
@@ -29,7 +29,6 @@ import com.android.dialer.phonelookup.PhoneLookupInfo;
import com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info;
import com.android.dialer.phonelookup.consolidator.PhoneLookupInfoConsolidator;
import com.android.dialer.phonelookup.cp2.Cp2LocalPhoneLookup;
-import com.google.common.base.Optional;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
@@ -67,21 +66,18 @@ public final class RealtimeRowProcessor {
/**
* Converts a {@link CoalescedRow} to a future which is the result of performing additional work
- * on the row. Returns {@link Optional#absent()} if no modifications were necessary.
+ * on the row. May simply return the original row if no modifications were necessary.
*/
@MainThread
- ListenableFuture<Optional<CoalescedRow>> applyRealtimeProcessing(final CoalescedRow row) {
+ ListenableFuture<CoalescedRow> applyRealtimeProcessing(final CoalescedRow row) {
// Cp2LocalPhoneLookup can not always efficiently process all rows.
if (!row.numberAttributes().getIsCp2InfoIncomplete()) {
- return Futures.immediateFuture(Optional.absent());
+ return Futures.immediateFuture(row);
}
Cp2Info cachedCp2Info = cache.get(row.number());
if (cachedCp2Info != null) {
- if (cachedCp2Info.equals(Cp2Info.getDefaultInstance())) {
- return Futures.immediateFuture(Optional.absent());
- }
- return Futures.immediateFuture(Optional.of(applyCp2LocalInfoToRow(cachedCp2Info, row)));
+ return Futures.immediateFuture(applyCp2LocalInfoToRow(cachedCp2Info, row));
}
ListenableFuture<Cp2Info> cp2InfoFuture = cp2LocalPhoneLookup.lookupByNumber(row.number());
@@ -89,10 +85,7 @@ public final class RealtimeRowProcessor {
cp2InfoFuture,
cp2Info -> {
cache.put(row.number(), cp2Info);
- if (!cp2Info.equals(Cp2Info.getDefaultInstance())) {
- return Optional.of(applyCp2LocalInfoToRow(cp2Info, row));
- }
- return Optional.absent();
+ return applyCp2LocalInfoToRow(cp2Info, row);
},
uiExecutor /* ensures the cache is updated on a single thread */);
}
diff --git a/java/com/android/dialer/phonelookup/cp2/Cp2LocalPhoneLookup.java b/java/com/android/dialer/phonelookup/cp2/Cp2LocalPhoneLookup.java
index c6e7f5aa3..995950d0e 100644
--- a/java/com/android/dialer/phonelookup/cp2/Cp2LocalPhoneLookup.java
+++ b/java/com/android/dialer/phonelookup/cp2/Cp2LocalPhoneLookup.java
@@ -140,7 +140,7 @@ public final class Cp2LocalPhoneLookup implements PhoneLookup<Cp2Info> {
try (Cursor cursor =
queryPhoneLookup(Cp2Projections.getProjectionForPhoneLookupTable(), rawNumber)) {
if (cursor == null) {
- LogUtil.w("Cp2LocalPhoneLookup.lookup", "null cursor");
+ LogUtil.w("Cp2LocalPhoneLookup.lookupByNumber", "null cursor");
return Cp2Info.getDefaultInstance();
}
while (cursor.moveToNext()) {
@@ -511,7 +511,10 @@ public final class Cp2LocalPhoneLookup implements PhoneLookup<Cp2Info> {
} else if (deletedPhoneNumbers.contains(dialerPhoneNumber)) {
infoBuilder.clear();
} else if (unprocessableNumbers.contains(dialerPhoneNumber)) {
- infoBuilder.clear().setIsIncomplete(true);
+ // Don't clear the existing info when the number is unprocessable. It's
+ // likely that the existing info is up-to-date so keep it in place so that
+ // the UI doesn't pop when the query is completed at display time.
+ infoBuilder.setIsIncomplete(true);
}
// If the DialerPhoneNumber didn't change, add the unchanged existing info.