Add bottom sheet options for blocked and/or spam numbers in the new call log.

Bug: 70989605
Test: ModulesTest
PiperOrigin-RevId: 185392711
Change-Id: I709a1e307925f1c99d2740ed52dc2b7784bca986
diff --git a/assets/quantum/res/drawable/quantum_ic_report_off_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_report_off_vd_theme_24.xml
new file mode 100644
index 0000000..8af3a72
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_report_off_vd_theme_24.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ 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
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M11,7h2v2.92l6.91,6.91 1.09,-1.1L21,8.27L15.73,3L8.27,3L7.18,4.1 11,7.92zM22.27,21.73l-20,-20.01L1,2.99l3.64,3.64L3,8.27v7.46L8.27,21h7.46l1.64,-1.63L21,23l1.27,-1.27zM12,17.3c-0.72,0 -1.3,-0.58 -1.3,-1.3s0.58,-1.3 1.3,-1.3 1.3,0.58 1.3,1.3 -0.58,1.3 -1.3,1.3z"/>
+</vector>
diff --git a/java/com/android/dialer/calllog/ui/menu/Modules.java b/java/com/android/dialer/calllog/ui/menu/Modules.java
index d591558..c85a9fd 100644
--- a/java/com/android/dialer/calllog/ui/menu/Modules.java
+++ b/java/com/android/dialer/calllog/ui/menu/Modules.java
@@ -52,15 +52,8 @@
 
     if (canPlaceCalls) {
       addModuleForVideoOrAudioCall(context, modules, row, normalizedNumber);
-
-      SharedModules.maybeAddModuleForAddingToContacts(
-          context,
-          modules,
-          row.number(),
-          row.numberAttributes().getName(),
-          row.numberAttributes().getLookupUri());
-
-      SharedModules.maybeAddModuleForSendingTextMessage(context, modules, normalizedNumber);
+      SharedModules.maybeAddModuleForSendingTextMessage(
+          context, modules, normalizedNumber, row.numberAttributes().getIsBlocked());
     }
 
     if (!modules.isEmpty()) {
@@ -68,10 +61,23 @@
     }
 
 
-    // TODO(zachh): Module for blocking/unblocking spam.
     // TODO(zachh): Module for CallComposer.
 
     if (canPlaceCalls) {
+      SharedModules.maybeAddModuleForAddingToContacts(
+          context,
+          modules,
+          row.number(),
+          row.numberAttributes().getName(),
+          row.numberAttributes().getLookupUri(),
+          row.numberAttributes().getIsBlocked(),
+          row.numberAttributes().getIsSpam());
+      SharedModules.addModulesHandlingBlockedOrSpamNumber(
+          context,
+          modules,
+          normalizedNumber,
+          row.numberAttributes().getIsBlocked(),
+          row.numberAttributes().getIsSpam());
       SharedModules.maybeAddModuleForCopyingNumber(context, modules, normalizedNumber);
     }
 
@@ -89,10 +95,23 @@
       List<ContactActionModule> modules,
       CoalescedRow row,
       String normalizedNumber) {
+    // If a number is blocked, skip this menu item.
+    if (row.numberAttributes().getIsBlocked()) {
+      return;
+    }
+
     PhoneAccountHandle phoneAccountHandle =
         TelecomUtil.composePhoneAccountHandle(
             row.phoneAccountComponentName(), row.phoneAccountId());
 
+    // For a spam number, only audio calls are allowed.
+    if (row.numberAttributes().getIsSpam()) {
+      modules.add(
+          IntentModule.newCallModule(
+              context, normalizedNumber, phoneAccountHandle, CallInitiationType.Type.CALL_LOG));
+      return;
+    }
+
     if ((row.features() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) {
       // Add an audio call item for video calls. Clicking the top entry on the bottom sheet will
       // trigger a video call.
diff --git a/java/com/android/dialer/contactactions/IntentModule.java b/java/com/android/dialer/contactactions/IntentModule.java
index aa7fd25..9a345c6 100644
--- a/java/com/android/dialer/contactactions/IntentModule.java
+++ b/java/com/android/dialer/contactactions/IntentModule.java
@@ -72,7 +72,7 @@
             context,
             new CallIntentBuilder(number, initiationType)
                 .setPhoneAccountHandle(phoneAccountHandle)),
-        R.string.call,
+        R.string.voice_call,
         R.drawable.quantum_ic_call_white_24);
   }
 
diff --git a/java/com/android/dialer/contactactions/SharedModules.java b/java/com/android/dialer/contactactions/SharedModules.java
index 7e72863..6d97fcb 100644
--- a/java/com/android/dialer/contactactions/SharedModules.java
+++ b/java/com/android/dialer/contactactions/SharedModules.java
@@ -20,14 +20,15 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.provider.ContactsContract;
-import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
+import android.widget.Toast;
 import com.android.dialer.DialerPhoneNumber;
 import com.android.dialer.clipboard.ClipboardUtils;
 import com.android.dialer.util.IntentUtil;
 import com.android.dialer.util.UriUtils;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * Modules for the bottom sheet that are shared between NewVoicemailFragment and NewCallLogFragment
@@ -37,10 +38,15 @@
   public static void maybeAddModuleForAddingToContacts(
       Context context,
       List<ContactActionModule> modules,
-      @NonNull DialerPhoneNumber number,
-      @Nullable String name,
-      @Nullable String lookupUri) {
-    // TODO(zachh): Only show this for non-spam/blocked numbers.
+      DialerPhoneNumber number,
+      String name,
+      String lookupUri,
+      boolean isBlocked,
+      boolean isSpam) {
+    // Skip showing the menu item for a spam/blocked number.
+    if (isBlocked || isSpam) {
+      return;
+    }
 
     // Skip showing the menu item for existing contacts.
     if (isExistingContact(lookupUri)) {
@@ -83,22 +89,148 @@
   }
 
   public static void maybeAddModuleForSendingTextMessage(
-      Context context, List<ContactActionModule> modules, String originalNumber) {
+      Context context,
+      List<ContactActionModule> modules,
+      String normalizedNumber,
+      boolean isBlocked) {
+    // Don't show the option to send a text message if the number is blocked.
+    if (isBlocked) {
+      return;
+    }
+
     // TODO(zachh): There are some conditions where this module should not be shown; consider
-    // voicemail, business numbers, blocked numbers, spam numbers, etc.
-    if (!TextUtils.isEmpty(originalNumber)) {
+    // voicemail, business numbers, etc.
+
+    if (!TextUtils.isEmpty(normalizedNumber)) {
       modules.add(
           new IntentModule(
               context,
-              IntentUtil.getSendSmsIntent(originalNumber),
+              IntentUtil.getSendSmsIntent(normalizedNumber),
               R.string.send_a_message,
               R.drawable.quantum_ic_message_vd_theme_24));
     }
   }
 
+  public static void addModulesHandlingBlockedOrSpamNumber(
+      Context context,
+      List<ContactActionModule> modules,
+      String normalizedNumber,
+      boolean isBlocked,
+      boolean isSpam) {
+    // For a spam number, add two options:
+    // (1) "Not spam" and "Block", or
+    // (2) "Not spam" and "Unblock".
+    if (isSpam) {
+      addModuleForMarkingNumberAsNonSpam(context, modules, normalizedNumber);
+      addModuleForBlockingOrUnblockingNumber(context, modules, normalizedNumber, isBlocked);
+      return;
+    }
+
+    // For a blocked non-spam number, add "Unblock" option.
+    if (isBlocked) {
+      addModuleForBlockingOrUnblockingNumber(context, modules, normalizedNumber, isBlocked);
+      return;
+    }
+
+    // For a number that is neither a spam number nor blocked, add "Block/Report spam" option.
+    addModuleForBlockingNumberAndOptionallyReportingSpam(context, modules, normalizedNumber);
+  }
+
+  private static void addModuleForMarkingNumberAsNonSpam(
+      Context context, List<ContactActionModule> modules, String normalizedNumber) {
+    modules.add(
+        new ContactActionModule() {
+          @Override
+          public int getStringId() {
+            return R.string.not_spam;
+          }
+
+          @Override
+          public int getDrawableId() {
+            return R.drawable.quantum_ic_report_off_vd_theme_24;
+          }
+
+          @Override
+          public boolean onClick() {
+            // TODO(a bug): implement this method.
+            Toast.makeText(
+                    context,
+                    String.format(Locale.ENGLISH, "TODO: Report %s as non-spam", normalizedNumber),
+                    Toast.LENGTH_SHORT)
+                .show();
+            return true; // Close the bottom sheet.
+          }
+        });
+  }
+
+  private static void addModuleForBlockingOrUnblockingNumber(
+      Context context,
+      List<ContactActionModule> modules,
+      String normalizedNumber,
+      boolean isBlocked) {
+    modules.add(
+        new ContactActionModule() {
+          @Override
+          public int getStringId() {
+            return isBlocked ? R.string.unblock_number : R.string.block_number;
+          }
+
+          @Override
+          public int getDrawableId() {
+            return isBlocked
+                ? R.drawable.ic_unblock // TODO(a bug): use a vector icon
+                : R.drawable.quantum_ic_block_vd_theme_24;
+          }
+
+          @Override
+          public boolean onClick() {
+            // TODO(a bug): implement this method.
+            Toast.makeText(
+                    context,
+                    String.format(
+                        Locale.ENGLISH,
+                        "TODO: " + (isBlocked ? "Unblock " : "Block ") + " number %s.",
+                        normalizedNumber),
+                    Toast.LENGTH_SHORT)
+                .show();
+            return true; // Close the bottom sheet.
+          }
+        });
+  }
+
+  private static void addModuleForBlockingNumberAndOptionallyReportingSpam(
+      Context context, List<ContactActionModule> modules, String normalizedNumber) {
+    modules.add(
+        new ContactActionModule() {
+          @Override
+          public int getStringId() {
+            return R.string.block_and_optionally_report_spam;
+          }
+
+          @Override
+          public int getDrawableId() {
+            return R.drawable.quantum_ic_block_vd_theme_24;
+          }
+
+          @Override
+          public boolean onClick() {
+            // TODO(a bug): implement this method.
+            Toast.makeText(
+                    context,
+                    String.format(
+                        Locale.ENGLISH,
+                        "TODO: Block and optionally report as spam %s.",
+                        normalizedNumber),
+                    Toast.LENGTH_SHORT)
+                .show();
+            return true; // Close the bottom sheet.
+          }
+        });
+  }
+
   public static void maybeAddModuleForCopyingNumber(
-      Context context, List<ContactActionModule> modules, String originalNumber) {
-    if (TextUtils.isEmpty(originalNumber)) {
+      Context context, List<ContactActionModule> modules, String normalizedNumber) {
+    if (TextUtils.isEmpty(normalizedNumber)) {
       return;
     }
     modules.add(
@@ -115,7 +247,7 @@
 
           @Override
           public boolean onClick() {
-            ClipboardUtils.copyText(context, null, originalNumber, true);
+            ClipboardUtils.copyText(context, null, normalizedNumber, true);
             return false;
           }
         });
diff --git a/java/com/android/dialer/contactactions/res/drawable-xxxhdpi/ic_unblock.png b/java/com/android/dialer/contactactions/res/drawable-xxxhdpi/ic_unblock.png
new file mode 100644
index 0000000..01551e2
--- /dev/null
+++ b/java/com/android/dialer/contactactions/res/drawable-xxxhdpi/ic_unblock.png
Binary files differ
diff --git a/java/com/android/dialer/contactactions/res/values/strings.xml b/java/com/android/dialer/contactactions/res/values/strings.xml
index 0e953a5..4d598a9 100644
--- a/java/com/android/dialer/contactactions/res/values/strings.xml
+++ b/java/com/android/dialer/contactactions/res/values/strings.xml
@@ -16,13 +16,31 @@
   -->
 
 <resources>
+  <!-- Option shown in call log/voicemail menu to make a voice call [CHAR LIMIT=30] -->
+  <string name="voice_call">Voice call</string>
+
+  <!-- Option shown in a call log/voicemail menu to make a video call [CHAR LIMIT=30] -->
+  <string name="video_call">Video call</string>
+
   <!-- Option shown in call log menu/voicemail to add the phone number from an entry to an existing contact
        (also provides option to create a new contact from the number). [CHAR LIMIT=30] -->
-  <string name="add_to_contacts">Add to contacts</string>
+  <string name="add_to_contacts">Add contact</string>
 
   <!-- Options shown in call log/voicemail menu to send a SMS to the number represented by the call log/voicemailentry.
      [CHAR LIMIT=30] -->
-  <string name="send_a_message">Send a message</string>
+  <string name="send_a_message">Message</string>
+
+  <!-- Options shown in call log/voicemail menu to mark a number as non-spam. [CHAR LIMIT=30] -->
+  <string name="not_spam">Not spam</string>
+
+  <!-- Options shown in a call log/voicemail menu to block a number. [CHAR LIMIT=30] -->
+  <string name="block_number">Block</string>
+
+  <!-- Options shown in a call log/voicemail menu to unblock a number. [CHAR LIMIT=30] -->
+  <string name="unblock_number">Unblock</string>
+
+  <!-- Options shown in a call log/voicemail menu to block a number and/or report it as spam. [CHAR LIMIT=30] -->
+  <string name="block_and_optionally_report_spam">Block/Report spam</string>
 
   <!-- Option displayed in call log/voicemail menu to copy phone number. [CHAR LIMIT=30] -->
   <string name="copy_number">Copy number</string>
diff --git a/java/com/android/dialer/theme/res/values/strings.xml b/java/com/android/dialer/theme/res/values/strings.xml
index 74cabad..a14693f 100644
--- a/java/com/android/dialer/theme/res/values/strings.xml
+++ b/java/com/android/dialer/theme/res/values/strings.xml
@@ -30,9 +30,6 @@
        used in the Launcher icon. -->
   <string name="launcherActivityLabel">Phone</string>
 
-  <!-- text on a button, Video call, as in to place a video call. -->
-  <string name="video_call">Video call</string>
-
   <!-- Label shown on the 'positive' button for the dialog. Indicates that the call will proceed -->
   <string name="call">Call</string>
 </resources>
diff --git a/java/com/android/dialer/voicemail/listui/menu/Modules.java b/java/com/android/dialer/voicemail/listui/menu/Modules.java
index 665031a..7254ad6 100644
--- a/java/com/android/dialer/voicemail/listui/menu/Modules.java
+++ b/java/com/android/dialer/voicemail/listui/menu/Modules.java
@@ -41,16 +41,25 @@
         modules,
         voicemailEntry.number(),
         voicemailEntry.numberAttributes().getName(),
-        voicemailEntry.numberAttributes().getLookupUri());
+        voicemailEntry.numberAttributes().getLookupUri(),
+        voicemailEntry.numberAttributes().getIsBlocked(),
+        voicemailEntry.numberAttributes().getIsSpam());
 
     String normalizedNumber = voicemailEntry.number().getNormalizedNumber();
-    SharedModules.maybeAddModuleForSendingTextMessage(context, modules, normalizedNumber);
+    SharedModules.maybeAddModuleForSendingTextMessage(
+        context, modules, normalizedNumber, voicemailEntry.numberAttributes().getIsBlocked());
 
     if (!modules.isEmpty()) {
       modules.add(new DividerModule());
     }
 
-    // TODO(zachh): Module for blocking/unblocking spam.
+    SharedModules.addModulesHandlingBlockedOrSpamNumber(
+        context,
+        modules,
+        normalizedNumber,
+        voicemailEntry.numberAttributes().getIsBlocked(),
+        voicemailEntry.numberAttributes().getIsSpam());
+
     // TODO(zachh): Module for CallComposer.
     SharedModules.maybeAddModuleForCopyingNumber(context, modules, normalizedNumber);