Merge "In the coalesced call log, replace column NUMBER_CALLS with a new column COALESCED_IDS."
diff --git a/java/com/android/dialer/calllog/database/Coalescer.java b/java/com/android/dialer/calllog/database/Coalescer.java
index a8a8f2f..71052b9 100644
--- a/java/com/android/dialer/calllog/database/Coalescer.java
+++ b/java/com/android/dialer/calllog/database/Coalescer.java
@@ -21,6 +21,7 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.WorkerThread;
 import android.telecom.PhoneAccountHandle;
+import com.android.dialer.CoalescedIds;
 import com.android.dialer.DialerPhoneNumber;
 import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
 import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
@@ -29,6 +30,7 @@
 import com.android.dialer.calllogutils.PhoneAccountUtils;
 import com.android.dialer.common.Assert;
 import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
+import com.google.common.base.Preconditions;
 import com.google.i18n.phonenumbers.PhoneNumberUtil;
 import com.google.protobuf.InvalidProtocolBufferException;
 import java.util.ArrayList;
@@ -40,11 +42,10 @@
 /**
  * Coalesces call log rows by combining some adjacent rows.
  *
- * <p>Applies the business which logic which determines which adjacent rows should be coalasced, and
- * then delegates to each data source to determine how individual columns should be aggregated.
+ * <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.
  */
 public class Coalescer {
-
   private final DataSources dataSources;
 
   @Inject
@@ -96,7 +97,9 @@
 
         if (!rowsShouldBeCombined(dialerPhoneNumberUtil, previousRow, currentRow)) {
           ContentValues coalescedRow = coalesceRowsForAllDataSources(currentRowGroup);
-          coalescedRow.put(CoalescedAnnotatedCallLog.NUMBER_CALLS, currentRowGroup.size());
+          coalescedRow.put(
+              CoalescedAnnotatedCallLog.COALESCED_IDS,
+              getCoalescedIds(currentRowGroup).toByteArray());
           addContentValuesToMatrixCursor(
               coalescedRow, allCoalescedRowsMatrixCursor, coalescedRowId++);
           currentRowGroup.clear();
@@ -106,7 +109,8 @@
 
       // Deal with leftover rows.
       ContentValues coalescedRow = coalesceRowsForAllDataSources(currentRowGroup);
-      coalescedRow.put(CoalescedAnnotatedCallLog.NUMBER_CALLS, currentRowGroup.size());
+      coalescedRow.put(
+          CoalescedAnnotatedCallLog.COALESCED_IDS, getCoalescedIds(currentRowGroup).toByteArray());
       addContentValuesToMatrixCursor(coalescedRow, allCoalescedRowsMatrixCursor, coalescedRowId);
     }
     return allCoalescedRowsMatrixCursor;
@@ -185,6 +189,23 @@
   }
 
   /**
+   * 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)));
+    }
+
+    return coalescedIds.build();
+  }
+
+  /**
    * @param contentValues a {@link CoalescedAnnotatedCallLog} row
    * @param matrixCursor represents {@link CoalescedAnnotatedCallLog}
    */
diff --git a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
index 9efe214..c9c053c 100644
--- a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
+++ b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
@@ -274,17 +274,18 @@
         "vnd.android.cursor.item/coalesced_annotated_call_log";
 
     /**
-     * Number of AnnotatedCallLog rows represented by this CoalescedAnnotatedCallLog row.
+     * 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: INTEGER
+     * <p>Type: BLOB
      */
-    public static final String NUMBER_CALLS = "number_calls";
+    public static final String COALESCED_IDS = "coalesced_ids";
 
     /**
      * Columns that are only in the {@link CoalescedAnnotatedCallLog} but not the {@link
      * AnnotatedCallLog}.
      */
-    private static final String[] COLUMNS_ONLY_IN_COALESCED_CALL_LOG = new String[] {NUMBER_CALLS};
+    private static final String[] COLUMNS_ONLY_IN_COALESCED_CALL_LOG = new String[] {COALESCED_IDS};
 
     /** All columns in the {@link CoalescedAnnotatedCallLog}. */
     public static final String[] ALL_COLUMNS =
diff --git a/java/com/android/dialer/calllog/model/CoalescedRow.java b/java/com/android/dialer/calllog/model/CoalescedRow.java
index 0914674..5cc0568 100644
--- a/java/com/android/dialer/calllog/model/CoalescedRow.java
+++ b/java/com/android/dialer/calllog/model/CoalescedRow.java
@@ -17,8 +17,8 @@
 package com.android.dialer.calllog.model;
 
 import android.support.annotation.ColorInt;
-import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import com.android.dialer.CoalescedIds;
 import com.android.dialer.DialerPhoneNumber;
 import com.google.auto.value.AutoValue;
 
@@ -38,15 +38,14 @@
         .setFeatures(0)
         .setIsBusiness(false)
         .setIsVoicemail(false)
-        .setNumberCalls(0)
-        .setCallType(0);
+        .setCallType(0)
+        .setCoalescedIds(CoalescedIds.getDefaultInstance());
   }
 
   public abstract int id();
 
   public abstract long timestamp();
 
-  @NonNull
   public abstract DialerPhoneNumber number();
 
   @Nullable
@@ -93,7 +92,7 @@
 
   public abstract int callType();
 
-  public abstract int numberCalls();
+  public abstract CoalescedIds coalescedIds();
 
   /** Builder for {@link CoalescedRow}. */
   @AutoValue.Builder
@@ -103,7 +102,7 @@
 
     public abstract Builder setTimestamp(long timestamp);
 
-    public abstract Builder setNumber(@NonNull DialerPhoneNumber number);
+    public abstract Builder setNumber(DialerPhoneNumber number);
 
     public abstract Builder setName(@Nullable String name);
 
@@ -140,7 +139,7 @@
 
     public abstract Builder setCallType(int callType);
 
-    public abstract Builder setNumberCalls(int numberCalls);
+    public abstract Builder setCoalescedIds(CoalescedIds coalescedIds);
 
     public abstract CoalescedRow build();
   }
diff --git a/java/com/android/dialer/calllog/model/coalesced_ids.proto b/java/com/android/dialer/calllog/model/coalesced_ids.proto
new file mode 100644
index 0000000..059f957
--- /dev/null
+++ b/java/com/android/dialer/calllog/model/coalesced_ids.proto
@@ -0,0 +1,30 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+
+syntax = "proto2";
+
+option java_package = "com.android.dialer";
+option java_multiple_files = true;
+option optimize_for = LITE_RUNTIME;
+
+
+package com.android.dialer;
+
+// A proto containing a list of IDs of the rows in AnnotatedCallLog that are
+// coalesced into a row in CoalescedAnnotatedCallLog.
+// For example, if rows in the AnnotatedCallLog with IDs 123, 124, 125 are
+// coalesced into one row, the list in the proto will be [123, 124, 125].
+message CoalescedIds {
+  repeated int64 coalesced_id = 1;
+}
\ No newline at end of file
diff --git a/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java
index 9f63543..8aefb1a 100644
--- a/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java
+++ b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.support.v4.content.CursorLoader;
+import com.android.dialer.CoalescedIds;
 import com.android.dialer.DialerPhoneNumber;
 import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
 import com.android.dialer.calllog.model.CoalescedRow;
@@ -48,7 +49,7 @@
   private static final int IS_BUSINESS = 17;
   private static final int IS_VOICEMAIL = 18;
   private static final int CALL_TYPE = 19;
-  private static final int NUMBER_CALLS = 20;
+  private static final int COALESCED_IDS = 20;
 
   CoalescedAnnotatedCallLogCursorLoader(Context context) {
     // CoalescedAnnotatedCallLog requires that PROJECTION be ALL_COLUMNS and the following params be
@@ -71,6 +72,13 @@
       throw new IllegalStateException("Couldn't parse DialerPhoneNumber bytes");
     }
 
+    CoalescedIds coalescedIds;
+    try {
+      coalescedIds = CoalescedIds.parseFrom(cursor.getBlob(COALESCED_IDS));
+    } catch (InvalidProtocolBufferException e) {
+      throw new IllegalStateException("Couldn't parse CoalescedIds bytes");
+    }
+
     return CoalescedRow.builder()
         .setId(cursor.getInt(ID))
         .setTimestamp(cursor.getLong(TIMESTAMP))
@@ -92,7 +100,7 @@
         .setIsBusiness(cursor.getInt(IS_BUSINESS) == 1)
         .setIsVoicemail(cursor.getInt(IS_VOICEMAIL) == 1)
         .setCallType(cursor.getInt(CALL_TYPE))
-        .setNumberCalls(cursor.getInt(NUMBER_CALLS))
+        .setCoalescedIds(coalescedIds)
         .build();
   }
 
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
index 16147f6..629a9a2 100644
--- a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
+++ b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
@@ -89,8 +89,9 @@
 
   private void setNumberCalls(CoalescedRow row) {
     // TODO(zachh): Number of calls shouldn't be text, but a circle with a number inside.
-    if (row.numberCalls() > 1) {
-      primaryTextView.append(String.format(Locale.getDefault(), " (%d)", row.numberCalls()));
+    int numberCalls = row.coalescedIds().getCoalescedIdCount();
+    if (numberCalls > 1) {
+      primaryTextView.append(String.format(Locale.getDefault(), " (%d)", numberCalls));
     }
   }