summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/calllog/database
diff options
context:
space:
mode:
authorlinyuh <linyuh@google.com>2018-06-15 13:31:28 -0700
committerCopybara-Service <copybara-piper@google.com>2018-06-18 13:20:17 -0700
commit8f1fbd77f64fdf376e70dd3e7de3c8eb5d9cfbf9 (patch)
treee212342f4a8b8a4e29c52c8df34225a1fb11a0b5 /java/com/android/dialer/calllog/database
parenteed866a9b6bf32cb81e62fc94b94cd3242895c76 (diff)
Improve Coalescer performance
Bug: 77813585 Test: CoalescerTest PiperOrigin-RevId: 200764878 Change-Id: I7e3d9c3b4eab1e5de12a108b82c04704550c8c5e
Diffstat (limited to 'java/com/android/dialer/calllog/database')
-rw-r--r--java/com/android/dialer/calllog/database/Coalescer.java429
-rw-r--r--java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java85
2 files changed, 233 insertions, 281 deletions
diff --git a/java/com/android/dialer/calllog/database/Coalescer.java b/java/com/android/dialer/calllog/database/Coalescer.java
index 903b7e26e..2ad9f9a97 100644
--- a/java/com/android/dialer/calllog/database/Coalescer.java
+++ b/java/com/android/dialer/calllog/database/Coalescer.java
@@ -15,11 +15,9 @@
*/
package com.android.dialer.calllog.database;
-import android.content.ContentValues;
import android.database.Cursor;
import android.provider.CallLog.Calls;
import android.support.annotation.NonNull;
-import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
import android.telecom.PhoneAccountHandle;
import android.text.TextUtils;
@@ -27,9 +25,6 @@ import com.android.dialer.CoalescedIds;
import com.android.dialer.DialerPhoneNumber;
import com.android.dialer.NumberAttributes;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
-import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
-import com.android.dialer.calllog.datasources.CallLogDataSource;
-import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.calllog.model.CoalescedRow;
import com.android.dialer.common.Assert;
import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor;
@@ -38,35 +33,24 @@ import com.android.dialer.metrics.FutureTimer;
import com.android.dialer.metrics.Metrics;
import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
import com.android.dialer.telecom.TelecomUtil;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.protobuf.InvalidProtocolBufferException;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Objects;
import javax.inject.Inject;
-/**
- * Coalesces rows in {@link AnnotatedCallLog} by combining adjacent rows.
- *
- * <p>Applies the logic that determines which adjacent rows should be coalesced, and then delegates
- * to each data source to determine how individual columns should be aggregated.
- */
+/** Combines adjacent rows in {@link AnnotatedCallLog}. */
public class Coalescer {
- private final DataSources dataSources;
private final FutureTimer futureTimer;
private final ListeningExecutorService backgroundExecutorService;
@Inject
Coalescer(
@BackgroundExecutor ListeningExecutorService backgroundExecutorService,
- DataSources dataSources,
FutureTimer futureTimer) {
this.backgroundExecutorService = backgroundExecutorService;
- this.dataSources = dataSources;
this.futureTimer = futureTimer;
}
@@ -108,256 +92,249 @@ public class Coalescer {
return ImmutableList.of();
}
- // Note: This method relies on rowsShouldBeCombined to determine which rows should be combined,
- // but delegates to data sources to actually aggregate column values.
-
- DialerPhoneNumberUtil dialerPhoneNumberUtil = new DialerPhoneNumberUtil();
-
ImmutableList.Builder<CoalescedRow> coalescedRowListBuilder = new ImmutableList.Builder<>();
- int coalescedRowId = 0;
+ RowCombiner rowCombiner = new RowCombiner(allAnnotatedCallLogRowsSortedByTimestampDesc);
+ rowCombiner.startNewGroup();
- // TODO(a bug): Avoid using ContentValues as it doesn't make sense here.
- List<ContentValues> currentRowGroup = new ArrayList<>();
+ long coalescedRowId = 0;
+ do {
+ boolean isRowMerged = rowCombiner.mergeRow(allAnnotatedCallLogRowsSortedByTimestampDesc);
- ContentValues firstRow = cursorRowToContentValues(allAnnotatedCallLogRowsSortedByTimestampDesc);
- currentRowGroup.add(firstRow);
+ if (isRowMerged) {
+ allAnnotatedCallLogRowsSortedByTimestampDesc.moveToNext();
+ }
- while (!currentRowGroup.isEmpty()) {
- // Group consecutive rows
- ContentValues firstRowInGroup = currentRowGroup.get(0);
- ContentValues currentRow = null;
- while (allAnnotatedCallLogRowsSortedByTimestampDesc.moveToNext()) {
- currentRow = cursorRowToContentValues(allAnnotatedCallLogRowsSortedByTimestampDesc);
+ if (!isRowMerged || allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast()) {
+ coalescedRowListBuilder.add(
+ rowCombiner.combine().toBuilder().setId(coalescedRowId++).build());
+ rowCombiner.startNewGroup();
+ }
+ } while (!allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast());
- if (!rowsShouldBeCombined(dialerPhoneNumberUtil, firstRowInGroup, currentRow)) {
- break;
- }
+ return coalescedRowListBuilder.build();
+ }
- currentRowGroup.add(currentRow);
- }
+ /** Combines rows from {@link AnnotatedCallLog} into a {@link CoalescedRow}. */
+ private static final class RowCombiner {
+ private final CoalescedRow.Builder coalescedRowBuilder = CoalescedRow.newBuilder();
+ private final CoalescedIds.Builder coalescedIdsBuilder = CoalescedIds.newBuilder();
+
+ // Indexes for columns in AnnotatedCallLog
+ private final int idColumn;
+ private final int timestampColumn;
+ private final int numberColumn;
+ private final int formattedNumberColumn;
+ private final int numberPresentationColumn;
+ private final int isReadColumn;
+ private final int isNewColumn;
+ private final int geocodedLocationColumn;
+ private final int phoneAccountComponentNameColumn;
+ private final int phoneAccountIdColumn;
+ private final int featuresColumn;
+ private final int numberAttributesColumn;
+ private final int isVoicemailCallColumn;
+ private final int voicemailCallTagColumn;
+ private final int callTypeColumn;
+
+ // DialerPhoneNumberUtil will be created lazily as its instantiation is expensive.
+ private DialerPhoneNumberUtil dialerPhoneNumberUtil = null;
+
+ RowCombiner(Cursor annotatedCallLogRow) {
+ idColumn = annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog._ID);
+ timestampColumn = annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.TIMESTAMP);
+ numberColumn = annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.NUMBER);
+ formattedNumberColumn =
+ annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.FORMATTED_NUMBER);
+ numberPresentationColumn =
+ annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.NUMBER_PRESENTATION);
+ isReadColumn = annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.IS_READ);
+ isNewColumn = annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.NEW);
+ geocodedLocationColumn =
+ annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.GEOCODED_LOCATION);
+ phoneAccountComponentNameColumn =
+ annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME);
+ phoneAccountIdColumn =
+ annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.PHONE_ACCOUNT_ID);
+ featuresColumn = annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.FEATURES);
+ numberAttributesColumn =
+ annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.NUMBER_ATTRIBUTES);
+ isVoicemailCallColumn =
+ annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.IS_VOICEMAIL_CALL);
+ voicemailCallTagColumn =
+ annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.VOICEMAIL_CALL_TAG);
+ callTypeColumn = annotatedCallLogRow.getColumnIndexOrThrow(AnnotatedCallLog.CALL_TYPE);
+ }
- // Coalesce the group into a single row
- ContentValues coalescedRow = coalesceRowsForAllDataSources(currentRowGroup);
- coalescedRow.put(CoalescedAnnotatedCallLog._ID, coalescedRowId++);
- coalescedRow.put(
- CoalescedAnnotatedCallLog.COALESCED_IDS, getCoalescedIds(currentRowGroup).toByteArray());
- coalescedRowListBuilder.add(toCoalescedRowProto(coalescedRow));
+ /**
+ * Prepares {@link RowCombiner} for building a new group of rows by clearing information on all
+ * previously merged rows.
+ */
+ void startNewGroup() {
+ coalescedRowBuilder.clear();
+ coalescedIdsBuilder.clear();
+ }
- // Clear the current group after the rows are coalesced.
- currentRowGroup.clear();
+ /**
+ * Merge the given {@link AnnotatedCallLog} row into the current group.
+ *
+ * @return true if the given row is merged.
+ */
+ boolean mergeRow(Cursor annotatedCallLogRow) {
+ Assert.checkArgument(annotatedCallLogRow.getInt(callTypeColumn) != Calls.VOICEMAIL_TYPE);
- // Add the first of the remaining rows to the current group.
- if (!allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast()) {
- currentRowGroup.add(currentRow);
+ if (!canMergeRow(annotatedCallLogRow)) {
+ return false;
}
- }
- return coalescedRowListBuilder.build();
- }
+ // Set fields that don't use the most recent value.
+ //
+ // Currently there is only one such field: "features".
+ // If any call in a group includes a feature (like Wifi/HD), consider the group to have
+ // the feature.
+ coalescedRowBuilder.setFeatures(
+ coalescedRowBuilder.getFeatures() | annotatedCallLogRow.getInt(featuresColumn));
+
+ // Set fields that use the most recent value.
+ // Rows passed to Coalescer are already sorted in descending order of timestamp. If the
+ // coalesced ID list is not empty, it means RowCombiner has merged the most recent row in a
+ // group and there is no need to continue as we only set fields that use the most recent value
+ // from this point forward.
+ if (!coalescedIdsBuilder.getCoalescedIdList().isEmpty()) {
+ coalescedIdsBuilder.addCoalescedId(annotatedCallLogRow.getInt(idColumn));
+ return true;
+ }
- private static ContentValues cursorRowToContentValues(Cursor cursor) {
- ContentValues values = new ContentValues();
- String[] columns = cursor.getColumnNames();
- int length = columns.length;
- for (int i = 0; i < length; i++) {
- if (cursor.getType(i) == Cursor.FIELD_TYPE_BLOB) {
- values.put(columns[i], cursor.getBlob(i));
- } else {
- values.put(columns[i], cursor.getString(i));
+ coalescedRowBuilder
+ .setTimestamp(annotatedCallLogRow.getLong(timestampColumn))
+ .setNumberPresentation(annotatedCallLogRow.getInt(numberPresentationColumn))
+ .setIsRead(annotatedCallLogRow.getInt(isReadColumn) == 1)
+ .setIsNew(annotatedCallLogRow.getInt(isNewColumn) == 1)
+ .setIsVoicemailCall(annotatedCallLogRow.getInt(isVoicemailCallColumn) == 1)
+ .setCallType(annotatedCallLogRow.getInt(callTypeColumn));
+
+ // Two different DialerPhoneNumbers could be combined if they are different but considered
+ // to be a match by libphonenumber; in this case we arbitrarily select the most recent one.
+ try {
+ coalescedRowBuilder.setNumber(
+ DialerPhoneNumber.parseFrom(annotatedCallLogRow.getBlob(numberColumn)));
+ } catch (InvalidProtocolBufferException e) {
+ throw Assert.createAssertionFailException("Unable to parse DialerPhoneNumber bytes", e);
}
- }
- return values;
- }
- /**
- * @param row1 a row from {@link AnnotatedCallLog}
- * @param row2 a row from {@link AnnotatedCallLog}
- */
- private static boolean rowsShouldBeCombined(
- DialerPhoneNumberUtil dialerPhoneNumberUtil, ContentValues row1, ContentValues row2) {
- // Don't combine rows which don't use the same phone account.
- PhoneAccountHandle phoneAccount1 =
- TelecomUtil.composePhoneAccountHandle(
- row1.getAsString(AnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME),
- row1.getAsString(AnnotatedCallLog.PHONE_ACCOUNT_ID));
- PhoneAccountHandle phoneAccount2 =
- TelecomUtil.composePhoneAccountHandle(
- row2.getAsString(AnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME),
- row2.getAsString(AnnotatedCallLog.PHONE_ACCOUNT_ID));
- if (!Objects.equals(phoneAccount1, phoneAccount2)) {
- return false;
- }
+ String formattedNumber = annotatedCallLogRow.getString(formattedNumberColumn);
+ if (!TextUtils.isEmpty(formattedNumber)) {
+ coalescedRowBuilder.setFormattedNumber(formattedNumber);
+ }
- if (!row1.getAsInteger(AnnotatedCallLog.NUMBER_PRESENTATION)
- .equals(row2.getAsInteger(AnnotatedCallLog.NUMBER_PRESENTATION))) {
- return false;
- }
+ String geocodedLocation = annotatedCallLogRow.getString(geocodedLocationColumn);
+ if (!TextUtils.isEmpty(geocodedLocation)) {
+ coalescedRowBuilder.setGeocodedLocation(geocodedLocation);
+ }
- if (!meetsCallFeatureCriteria(row1, row2)) {
- return false;
- }
+ String phoneAccountComponentName =
+ annotatedCallLogRow.getString(phoneAccountComponentNameColumn);
+ if (!TextUtils.isEmpty(phoneAccountComponentName)) {
+ coalescedRowBuilder.setPhoneAccountComponentName(phoneAccountComponentName);
+ }
- DialerPhoneNumber number1;
- DialerPhoneNumber number2;
- try {
- byte[] number1Bytes = row1.getAsByteArray(AnnotatedCallLog.NUMBER);
- byte[] number2Bytes = row2.getAsByteArray(AnnotatedCallLog.NUMBER);
+ String phoneAccountId = annotatedCallLogRow.getString(phoneAccountIdColumn);
+ if (!TextUtils.isEmpty(phoneAccountId)) {
+ coalescedRowBuilder.setPhoneAccountId(phoneAccountId);
+ }
- if (number1Bytes == null || number2Bytes == null) {
- // Empty numbers should not be combined.
- return false;
+ try {
+ coalescedRowBuilder.setNumberAttributes(
+ NumberAttributes.parseFrom(annotatedCallLogRow.getBlob(numberAttributesColumn)));
+ } catch (InvalidProtocolBufferException e) {
+ throw Assert.createAssertionFailException("Unable to parse NumberAttributes bytes", e);
}
- number1 = DialerPhoneNumber.parseFrom(number1Bytes);
- number2 = DialerPhoneNumber.parseFrom(number2Bytes);
- } catch (InvalidProtocolBufferException e) {
- throw Assert.createAssertionFailException("error parsing DialerPhoneNumber proto", e);
- }
- return dialerPhoneNumberUtil.isMatch(number1, number2);
- }
+ String voicemailCallTag = annotatedCallLogRow.getString(voicemailCallTagColumn);
+ if (!TextUtils.isEmpty(voicemailCallTag)) {
+ coalescedRowBuilder.setVoicemailCallTag(voicemailCallTag);
+ }
- /**
- * Returns true if column {@link AnnotatedCallLog#FEATURES} of the two given rows indicate that
- * they can be coalesced.
- */
- private static boolean meetsCallFeatureCriteria(ContentValues row1, ContentValues row2) {
- int row1Features = row1.getAsInteger(AnnotatedCallLog.FEATURES);
- int row2Features = row2.getAsInteger(AnnotatedCallLog.FEATURES);
-
- // A row with FEATURES_ASSISTED_DIALING should not be combined with one without it.
- if ((row1Features & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING)
- != (row2Features & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING)) {
- return false;
+ coalescedIdsBuilder.addCoalescedId(annotatedCallLogRow.getInt(idColumn));
+ return true;
}
- // A video call should not be combined with one that is not a video call.
- if ((row1Features & Calls.FEATURES_VIDEO) != (row2Features & Calls.FEATURES_VIDEO)) {
- return false;
+ /** Builds a {@link CoalescedRow} based on all rows merged into the current group. */
+ CoalescedRow combine() {
+ return coalescedRowBuilder.setCoalescedIds(coalescedIdsBuilder.build()).build();
}
- // A RTT call should not be combined with one that is not a RTT call.
- if ((row1Features & Calls.FEATURES_RTT) != (row2Features & Calls.FEATURES_RTT)) {
- return false;
+ /**
+ * Returns true if the given {@link AnnotatedCallLog} row can be merged into the current group.
+ */
+ private boolean canMergeRow(Cursor annotatedCallLogRow) {
+ return coalescedIdsBuilder.getCoalescedIdList().isEmpty()
+ || (samePhoneAccount(annotatedCallLogRow)
+ && sameNumberPresentation(annotatedCallLogRow)
+ && meetsCallFeatureCriteria(annotatedCallLogRow)
+ && meetsDialerPhoneNumberCriteria(annotatedCallLogRow));
}
- return true;
- }
-
- /**
- * Delegates to data sources to aggregate individual columns to create a new coalesced row.
- *
- * @param individualRows {@link AnnotatedCallLog} rows sorted by timestamp descending
- * @return a {@link CoalescedAnnotatedCallLog} row
- */
- private ContentValues coalesceRowsForAllDataSources(List<ContentValues> individualRows) {
- ContentValues coalescedValues = new ContentValues();
- for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) {
- coalescedValues.putAll(dataSource.coalesce(individualRows));
+ private boolean samePhoneAccount(Cursor annotatedCallLogRow) {
+ PhoneAccountHandle groupPhoneAccountHandle =
+ TelecomUtil.composePhoneAccountHandle(
+ coalescedRowBuilder.getPhoneAccountComponentName(),
+ coalescedRowBuilder.getPhoneAccountId());
+ PhoneAccountHandle rowPhoneAccountHandle =
+ TelecomUtil.composePhoneAccountHandle(
+ annotatedCallLogRow.getString(phoneAccountComponentNameColumn),
+ annotatedCallLogRow.getString(phoneAccountIdColumn));
+
+ return Objects.equals(groupPhoneAccountHandle, rowPhoneAccountHandle);
}
- return coalescedValues;
- }
- /**
- * Build a {@link CoalescedIds} proto that contains IDs of the rows in {@link AnnotatedCallLog}
- * that are coalesced into one row in {@link CoalescedAnnotatedCallLog}.
- *
- * @param individualRows {@link AnnotatedCallLog} rows sorted by timestamp descending
- * @return A {@link CoalescedIds} proto containing IDs of {@code individualRows}.
- */
- private CoalescedIds getCoalescedIds(List<ContentValues> individualRows) {
- CoalescedIds.Builder coalescedIds = CoalescedIds.newBuilder();
-
- for (ContentValues row : individualRows) {
- coalescedIds.addCoalescedId(Preconditions.checkNotNull(row.getAsLong(AnnotatedCallLog._ID)));
+ private boolean sameNumberPresentation(Cursor annotatedCallLogRow) {
+ return coalescedRowBuilder.getNumberPresentation()
+ == annotatedCallLogRow.getInt(numberPresentationColumn);
}
- return coalescedIds.build();
- }
+ private boolean meetsCallFeatureCriteria(Cursor annotatedCallLogRow) {
+ int groupFeatures = coalescedRowBuilder.getFeatures();
+ int rowFeatures = annotatedCallLogRow.getInt(featuresColumn);
- /**
- * Creates a new {@link CoalescedRow} proto based on the provided {@link ContentValues}.
- *
- * <p>The provided {@link ContentValues} should be one for {@link CoalescedAnnotatedCallLog}.
- */
- @VisibleForTesting
- static CoalescedRow toCoalescedRowProto(ContentValues coalescedContentValues) {
- DialerPhoneNumber number;
- try {
- number =
- DialerPhoneNumber.parseFrom(
- coalescedContentValues.getAsByteArray(CoalescedAnnotatedCallLog.NUMBER));
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalStateException("Couldn't parse DialerPhoneNumber bytes");
- }
+ // A row with FEATURES_ASSISTED_DIALING should not be combined with one without it.
+ if ((groupFeatures & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING)
+ != (rowFeatures & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING)) {
+ return false;
+ }
- CoalescedIds coalescedIds;
- try {
- coalescedIds =
- CoalescedIds.parseFrom(
- coalescedContentValues.getAsByteArray(CoalescedAnnotatedCallLog.COALESCED_IDS));
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalStateException("Couldn't parse CoalescedIds bytes");
- }
+ // A video call should not be combined with one that is not a video call.
+ if ((groupFeatures & Calls.FEATURES_VIDEO) != (rowFeatures & Calls.FEATURES_VIDEO)) {
+ return false;
+ }
- NumberAttributes numberAttributes;
- try {
- numberAttributes =
- NumberAttributes.parseFrom(
- coalescedContentValues.getAsByteArray(CoalescedAnnotatedCallLog.NUMBER_ATTRIBUTES));
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalStateException("Couldn't parse NumberAttributes bytes");
- }
+ // A RTT call should not be combined with one that is not a RTT call.
+ if ((groupFeatures & Calls.FEATURES_RTT) != (rowFeatures & Calls.FEATURES_RTT)) {
+ return false;
+ }
- CoalescedRow.Builder coalescedRowBuilder =
- CoalescedRow.newBuilder()
- .setId(coalescedContentValues.getAsLong(CoalescedAnnotatedCallLog._ID))
- .setTimestamp(coalescedContentValues.getAsLong(CoalescedAnnotatedCallLog.TIMESTAMP))
- .setNumber(number)
- .setNumberPresentation(
- coalescedContentValues.getAsInteger(CoalescedAnnotatedCallLog.NUMBER_PRESENTATION))
- .setIsRead(coalescedContentValues.getAsInteger(CoalescedAnnotatedCallLog.IS_READ) == 1)
- .setIsNew(coalescedContentValues.getAsInteger(CoalescedAnnotatedCallLog.NEW) == 1)
- .setFeatures(coalescedContentValues.getAsInteger(CoalescedAnnotatedCallLog.FEATURES))
- .setCallType(coalescedContentValues.getAsInteger(CoalescedAnnotatedCallLog.CALL_TYPE))
- .setNumberAttributes(numberAttributes)
- .setIsVoicemailCall(
- coalescedContentValues.getAsInteger(CoalescedAnnotatedCallLog.IS_VOICEMAIL_CALL)
- == 1)
- .setCoalescedIds(coalescedIds);
-
- String formattedNumber =
- coalescedContentValues.getAsString(CoalescedAnnotatedCallLog.FORMATTED_NUMBER);
- if (!TextUtils.isEmpty(formattedNumber)) {
- coalescedRowBuilder.setFormattedNumber(formattedNumber);
+ return true;
}
- String geocodedLocation =
- coalescedContentValues.getAsString(CoalescedAnnotatedCallLog.GEOCODED_LOCATION);
- if (!TextUtils.isEmpty(geocodedLocation)) {
- coalescedRowBuilder.setGeocodedLocation(geocodedLocation);
- }
+ private boolean meetsDialerPhoneNumberCriteria(Cursor annotatedCallLogRow) {
+ DialerPhoneNumber groupPhoneNumber = coalescedRowBuilder.getNumber();
- String phoneAccountComponentName =
- coalescedContentValues.getAsString(CoalescedAnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME);
- if (!TextUtils.isEmpty(phoneAccountComponentName)) {
- coalescedRowBuilder.setPhoneAccountComponentName(
- coalescedContentValues.getAsString(
- CoalescedAnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME));
- }
+ DialerPhoneNumber rowPhoneNumber;
+ try {
+ byte[] rowPhoneNumberBytes = annotatedCallLogRow.getBlob(numberColumn);
+ if (rowPhoneNumberBytes == null) {
+ return false; // Empty numbers should not be combined.
+ }
+ rowPhoneNumber = DialerPhoneNumber.parseFrom(rowPhoneNumberBytes);
+ } catch (InvalidProtocolBufferException e) {
+ throw Assert.createAssertionFailException("Unable to parse DialerPhoneNumber bytes", e);
+ }
- String phoneAccountId =
- coalescedContentValues.getAsString(CoalescedAnnotatedCallLog.PHONE_ACCOUNT_ID);
- if (!TextUtils.isEmpty(phoneAccountId)) {
- coalescedRowBuilder.setPhoneAccountId(phoneAccountId);
- }
+ if (dialerPhoneNumberUtil == null) {
+ dialerPhoneNumberUtil = new DialerPhoneNumberUtil();
+ }
- String voicemailCallTag =
- coalescedContentValues.getAsString(CoalescedAnnotatedCallLog.VOICEMAIL_CALL_TAG);
- if (!TextUtils.isEmpty(voicemailCallTag)) {
- coalescedRowBuilder.setVoicemailCallTag(voicemailCallTag);
+ return dialerPhoneNumberUtil.isMatch(groupPhoneNumber, rowPhoneNumber);
}
-
- return coalescedRowBuilder.build();
}
}
diff --git a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
index 5aa62c2d1..1fdf38ac7 100644
--- a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
+++ b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
@@ -28,15 +28,29 @@ public class AnnotatedCallLogContract {
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
- /** Columns shared by {@link AnnotatedCallLog} and {@link CoalescedAnnotatedCallLog}. */
- interface CommonColumns extends BaseColumns {
+ /** AnnotatedCallLog table. */
+ public static final class AnnotatedCallLog implements BaseColumns {
+
+ public static final String TABLE = "AnnotatedCallLog";
+ public static final String DISTINCT_PHONE_NUMBERS = "DistinctPhoneNumbers";
+
+ /** The content URI for this table. */
+ public static final Uri CONTENT_URI =
+ Uri.withAppendedPath(AnnotatedCallLogContract.CONTENT_URI, TABLE);
+
+ /** Content URI for selecting the distinct phone numbers from the AnnotatedCallLog. */
+ public static final Uri DISTINCT_NUMBERS_CONTENT_URI =
+ Uri.withAppendedPath(AnnotatedCallLogContract.CONTENT_URI, DISTINCT_PHONE_NUMBERS);
+
+ /** The MIME type of a {@link android.content.ContentProvider#getType(Uri)} single entry. */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/annotated_call_log";
/**
* Timestamp of the entry, in milliseconds.
*
* <p>Type: INTEGER (long)
*/
- String TIMESTAMP = "timestamp";
+ public static final String TIMESTAMP = "timestamp";
/**
* The phone number called or number the call came from, encoded as a {@link
@@ -45,7 +59,7 @@ public class AnnotatedCallLogContract {
*
* <p>Type: BLOB
*/
- String NUMBER = "number";
+ public static final String NUMBER = "number";
/**
* The number formatted as it should be displayed to the user. Note that it may not always be
@@ -53,56 +67,56 @@ public class AnnotatedCallLogContract {
*
* <p>Type: TEXT
*/
- String FORMATTED_NUMBER = "formatted_number";
+ public static final String FORMATTED_NUMBER = "formatted_number";
/**
* See {@link android.provider.CallLog.Calls#NUMBER_PRESENTATION}.
*
* <p>Type: INTEGER (int)
*/
- String NUMBER_PRESENTATION = "presentation";
+ public static final String NUMBER_PRESENTATION = "presentation";
/**
* See {@link android.provider.CallLog.Calls#IS_READ}.
*
* <p>TYPE: INTEGER (boolean)
*/
- String IS_READ = "is_read";
+ public static final String IS_READ = "is_read";
/**
* See {@link android.provider.CallLog.Calls#NEW}.
*
* <p>Type: INTEGER (boolean)
*/
- String NEW = "new";
+ public static final String NEW = "new";
/**
* See {@link android.provider.CallLog.Calls#GEOCODED_LOCATION}.
*
* <p>TYPE: TEXT
*/
- String GEOCODED_LOCATION = "geocoded_location";
+ public static final String GEOCODED_LOCATION = "geocoded_location";
/**
* See {@link android.provider.CallLog.Calls#PHONE_ACCOUNT_COMPONENT_NAME}.
*
* <p>TYPE: TEXT
*/
- String PHONE_ACCOUNT_COMPONENT_NAME = "phone_account_component_name";
+ public static final String PHONE_ACCOUNT_COMPONENT_NAME = "phone_account_component_name";
/**
* See {@link android.provider.CallLog.Calls#PHONE_ACCOUNT_ID}.
*
* <p>TYPE: TEXT
*/
- String PHONE_ACCOUNT_ID = "phone_account_id";
+ public static final String PHONE_ACCOUNT_ID = "phone_account_id";
/**
* See {@link android.provider.CallLog.Calls#FEATURES}.
*
* <p>TYPE: INTEGER (int)
*/
- String FEATURES = "features";
+ public static final String FEATURES = "features";
/**
* Additional attributes about the number.
@@ -111,7 +125,7 @@ public class AnnotatedCallLogContract {
*
* @see com.android.dialer.NumberAttributes
*/
- String NUMBER_ATTRIBUTES = "number_attributes";
+ public static final String NUMBER_ATTRIBUTES = "number_attributes";
/**
* Whether the call is to the voicemail inbox.
@@ -121,7 +135,7 @@ public class AnnotatedCallLogContract {
* @see android.telecom.TelecomManager#isVoiceMailNumber(android.telecom.PhoneAccountHandle,
* String)
*/
- String IS_VOICEMAIL_CALL = "is_voicemail_call";
+ public static final String IS_VOICEMAIL_CALL = "is_voicemail_call";
/**
* The "name" of the voicemail inbox. This is provided by the SIM to show as the caller ID
@@ -130,36 +144,14 @@ public class AnnotatedCallLogContract {
*
* @see android.telephony.TelephonyManager#getVoiceMailAlphaTag()
*/
- String VOICEMAIL_CALL_TAG = "voicemail_call_tag";
+ public static final String VOICEMAIL_CALL_TAG = "voicemail_call_tag";
/**
* Copied from {@link android.provider.CallLog.Calls#TYPE}.
*
* <p>Type: INTEGER (int)
*/
- String CALL_TYPE = "call_type";
- }
-
- /**
- * AnnotatedCallLog table.
- *
- * <p>This contains all of the non-coalesced call log entries.
- */
- public static final class AnnotatedCallLog implements CommonColumns {
-
- public static final String TABLE = "AnnotatedCallLog";
- public static final String DISTINCT_PHONE_NUMBERS = "DistinctPhoneNumbers";
-
- /** The content URI for this table. */
- public static final Uri CONTENT_URI =
- Uri.withAppendedPath(AnnotatedCallLogContract.CONTENT_URI, TABLE);
-
- /** Content URI for selecting the distinct phone numbers from the AnnotatedCallLog. */
- public static final Uri DISTINCT_NUMBERS_CONTENT_URI =
- Uri.withAppendedPath(AnnotatedCallLogContract.CONTENT_URI, DISTINCT_PHONE_NUMBERS);
-
- /** The MIME type of a {@link android.content.ContentProvider#getType(Uri)} single entry. */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/annotated_call_log";
+ public static final String CALL_TYPE = "call_type";
/**
* See {@link android.provider.CallLog.Calls#DATA_USAGE}.
@@ -209,21 +201,4 @@ public class AnnotatedCallLogContract {
*/
public static final String CALL_MAPPING_ID = "call_mapping_id";
}
-
- /**
- * Coalesced view of the AnnotatedCallLog table.
- *
- * <p>This is an in-memory view of the {@link AnnotatedCallLog} with some adjacent entries
- * collapsed.
- */
- public static final class CoalescedAnnotatedCallLog implements CommonColumns {
-
- /**
- * IDs of rows in {@link AnnotatedCallLog} that are coalesced into one row in {@link
- * CoalescedAnnotatedCallLog}, encoded as a {@link com.android.dialer.CoalescedIds} proto.
- *
- * <p>Type: BLOB
- */
- public static final String COALESCED_IDS = "coalesced_ids";
- }
}