diff options
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. |