Include the timestamp in the data returned by the Spam interface.

Bug: 70989530
Test: Unit tests
PiperOrigin-RevId: 184703655
Change-Id: I043c05a2db9f05745952ee04a84912f7540a9a17
diff --git a/java/com/android/dialer/spam/Spam.java b/java/com/android/dialer/spam/Spam.java
index a79205b..5924d56 100644
--- a/java/com/android/dialer/spam/Spam.java
+++ b/java/com/android/dialer/spam/Spam.java
@@ -46,10 +46,9 @@
    * Checks if each of numbers in the given list is suspected of being a spam.
    *
    * @param dialerPhoneNumbers A set of {@link DialerPhoneNumber}.
-   * @return A {@link ListenableFuture} of a map that maps each number to its spam status
-   *     (true/false).
+   * @return A {@link ListenableFuture} of a map that maps each number to its {@link SpamStatus}.
    */
-  ListenableFuture<ImmutableMap<DialerPhoneNumber, Boolean>> batchCheckSpamStatus(
+  ListenableFuture<ImmutableMap<DialerPhoneNumber, SpamStatus>> batchCheckSpamStatus(
       ImmutableSet<DialerPhoneNumber> dialerPhoneNumbers);
 
   /**
diff --git a/java/com/android/dialer/spam/SpamStatus.java b/java/com/android/dialer/spam/SpamStatus.java
new file mode 100644
index 0000000..0b859d1
--- /dev/null
+++ b/java/com/android/dialer/spam/SpamStatus.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 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
+ */
+
+package com.android.dialer.spam;
+
+import com.google.common.base.Optional;
+
+/** An interface representing a number's spam status. */
+@SuppressWarnings("Guava")
+public interface SpamStatus {
+
+  /** Returns true if the number is spam. */
+  boolean isSpam();
+
+  /**
+   * Returns the timestamp (in milliseconds) indicating when the number's spam status entered the
+   * underlying data source.
+   *
+   * <p>{@code Optional.absent()} is returned if
+   *
+   * <ul>
+   *   <li>the number's spam status doesn't exist in the underlying data source, or
+   *   <li>the underlying data source can't provide a timestamp.
+   * </ul>
+   */
+  Optional<Long> getTimestampMillis();
+}
diff --git a/java/com/android/dialer/spam/SpamStub.java b/java/com/android/dialer/spam/SpamStub.java
index 91a56e8..b171d0d 100644
--- a/java/com/android/dialer/spam/SpamStub.java
+++ b/java/com/android/dialer/spam/SpamStub.java
@@ -21,6 +21,7 @@
 import com.android.dialer.logging.ContactLookupResult;
 import com.android.dialer.logging.ContactSource;
 import com.android.dialer.logging.ReportingLocation;
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.Futures;
@@ -69,14 +70,26 @@
   }
 
   @Override
-  public ListenableFuture<ImmutableMap<DialerPhoneNumber, Boolean>> batchCheckSpamStatus(
+  public ListenableFuture<ImmutableMap<DialerPhoneNumber, SpamStatus>> batchCheckSpamStatus(
       ImmutableSet<DialerPhoneNumber> dialerPhoneNumbers) {
     return backgroundExecutorService.submit(
         () -> {
-          ImmutableMap.Builder<DialerPhoneNumber, Boolean> resultBuilder =
+          ImmutableMap.Builder<DialerPhoneNumber, SpamStatus> resultBuilder =
               new ImmutableMap.Builder<>();
           for (DialerPhoneNumber dialerPhoneNumber : dialerPhoneNumbers) {
-            resultBuilder.put(dialerPhoneNumber, false);
+            resultBuilder.put(
+                dialerPhoneNumber,
+                new SpamStatus() {
+                  @Override
+                  public boolean isSpam() {
+                    return false;
+                  }
+
+                  @Override
+                  public Optional<Long> getTimestampMillis() {
+                    return Optional.absent();
+                  }
+                });
           }
           return resultBuilder.build();
         });