summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/historyitemactions
diff options
context:
space:
mode:
authorlinyuh <linyuh@google.com>2018-05-03 12:42:04 -0700
committerCopybara-Service <copybara-piper@google.com>2018-05-04 15:57:07 -0700
commit253b4407c125acbb7add26592ba782144c4d0366 (patch)
treedcf7f25e939d8beb80464cdddcf6ec87b604b982 /java/com/android/dialer/historyitemactions
parent49f90b332c6e716196276dab0f3d7e21b56b696e (diff)
Simplify how we build bottom sheet options (a.k.a. modules).
Test: HistoryItemActionModulesBuilderTest, ModulesTest PiperOrigin-RevId: 195294876 Change-Id: Iac44f965a585975389da7dee758a94a8ad8311d3
Diffstat (limited to 'java/com/android/dialer/historyitemactions')
-rw-r--r--java/com/android/dialer/historyitemactions/BlockReportSpamModules.java120
-rw-r--r--java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java400
-rw-r--r--java/com/android/dialer/historyitemactions/IntentModule.java9
-rw-r--r--java/com/android/dialer/historyitemactions/SharedModules.java247
-rw-r--r--java/com/android/dialer/historyitemactions/history_item_action_module_info.proto69
5 files changed, 598 insertions, 247 deletions
diff --git a/java/com/android/dialer/historyitemactions/BlockReportSpamModules.java b/java/com/android/dialer/historyitemactions/BlockReportSpamModules.java
new file mode 100644
index 000000000..396c03376
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/BlockReportSpamModules.java
@@ -0,0 +1,120 @@
+/*
+ * 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.historyitemactions;
+
+import android.content.Context;
+import com.android.dialer.blockreportspam.BlockReportSpamDialogInfo;
+import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogNotifier;
+
+/** Modules for blocking/unblocking a number and/or reporting it as spam/not spam. */
+final class BlockReportSpamModules {
+
+ private BlockReportSpamModules() {}
+
+ static HistoryItemActionModule moduleForMarkingNumberAsNotSpam(
+ Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) {
+
+ return new HistoryItemActionModule() {
+ @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() {
+ ShowBlockReportSpamDialogNotifier.notifyShowDialogToReportNotSpam(
+ context, blockReportSpamDialogInfo);
+ return true; // Close the bottom sheet.
+ }
+ };
+ }
+
+ static HistoryItemActionModule moduleForBlockingNumber(
+ Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) {
+
+ return new HistoryItemActionModule() {
+ @Override
+ public int getStringId() {
+ return R.string.block_number;
+ }
+
+ @Override
+ public int getDrawableId() {
+ return R.drawable.quantum_ic_block_vd_theme_24;
+ }
+
+ @Override
+ public boolean onClick() {
+ ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumber(
+ context, blockReportSpamDialogInfo);
+ return true; // Close the bottom sheet.
+ }
+ };
+ }
+
+ static HistoryItemActionModule moduleForUnblockingNumber(
+ Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) {
+
+ return new HistoryItemActionModule() {
+ @Override
+ public int getStringId() {
+ return R.string.unblock_number;
+ }
+
+ @Override
+ public int getDrawableId() {
+ return R.drawable.quantum_ic_unblock_vd_theme_24;
+ }
+
+ @Override
+ public boolean onClick() {
+ ShowBlockReportSpamDialogNotifier.notifyShowDialogToUnblockNumber(
+ context, blockReportSpamDialogInfo);
+
+ return true; // Close the bottom sheet.
+ }
+ };
+ }
+
+ static HistoryItemActionModule moduleForBlockingNumberAndOptionallyReportingSpam(
+ Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) {
+
+ return new HistoryItemActionModule() {
+ @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() {
+ ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumberAndOptionallyReportSpam(
+ context, blockReportSpamDialogInfo);
+ return true; // Close the bottom sheet.
+ }
+ };
+ }
+}
diff --git a/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java b/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java
new file mode 100644
index 000000000..ca6d3f3e4
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java
@@ -0,0 +1,400 @@
+/*
+ * 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.historyitemactions;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.CallLog.Calls;
+import android.provider.ContactsContract;
+import android.text.TextUtils;
+import com.android.dialer.blockreportspam.BlockReportSpamDialogInfo;
+import com.android.dialer.callintent.CallInitiationType;
+import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.clipboard.ClipboardUtils;
+import com.android.dialer.common.Assert;
+import com.android.dialer.duo.Duo;
+import com.android.dialer.duo.DuoComponent;
+import com.android.dialer.logging.ReportingLocation;
+import com.android.dialer.util.CallUtil;
+import com.android.dialer.util.UriUtils;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Builds a list of {@link HistoryItemActionModule HistoryItemActionModules}.
+ *
+ * <p>Example usage:
+ *
+ * <pre><code>
+ * // Create a HistoryItemActionModuleInfo proto with the information you have.
+ * // You can simply skip a field if there is no information for it.
+ * HistoryItemActionModuleInfo moduleInfo =
+ * HistoryItemActionModuleInfo.newBuilder()
+ * .setNormalizedNumber("+16502530000")
+ * .setCountryIso("US")
+ * .setName("Google")
+ * .build();
+ *
+ * // Initialize the builder using the module info above.
+ * // Note that some modules require an activity context to work so it is preferred to pass one
+ * // instead of an application context to the builder.
+ * HistoryItemActionModulesBuilder modulesBuilder =
+ * new HistoryItemActionModulesBuilder(activityContext, moduleInfo);
+ *
+ * // Add all modules you want in the order you like.
+ * // If a module shouldn't be added according to the module info, it won't be.
+ * // For example, if the module info is not for a video call and doesn't indicate the presence
+ * // of video calling capabilities, calling addModuleForVideoCall() is a no-op.
+ * modulesBuilder
+ * .addModuleForVoiceCall()
+ * .addModuleForVideoCall()
+ * .addModuleForSendingTextMessage()
+ * .addModuleForDivider()
+ * .addModuleForAddingToContacts()
+ * .addModuleForBlockedOrSpamNumber()
+ * .addModuleForCopyingNumber();
+ *
+ * List<HistoryItemActionModule> modules = modulesBuilder.build();
+ * </code></pre>
+ */
+public final class HistoryItemActionModulesBuilder {
+
+ private final Context context;
+ private final HistoryItemActionModuleInfo moduleInfo;
+ private final List<HistoryItemActionModule> modules;
+
+ public HistoryItemActionModulesBuilder(Context context, HistoryItemActionModuleInfo moduleInfo) {
+ Assert.checkArgument(
+ moduleInfo.getHost() != HistoryItemActionModuleInfo.Host.UNKNOWN,
+ "A host must be specified.");
+
+ this.context = context;
+ this.moduleInfo = moduleInfo;
+ this.modules = new ArrayList<>();
+ }
+
+ public List<HistoryItemActionModule> build() {
+ return new ArrayList<>(modules);
+ }
+
+ /**
+ * Adds a module for placing a voice call.
+ *
+ * <p>The method is a no-op if the number is blocked.
+ */
+ public HistoryItemActionModulesBuilder addModuleForVoiceCall() {
+ if (moduleInfo.getIsBlocked()) {
+ return this;
+ }
+
+ // TODO(zachh): Support post-dial digits; consider using DialerPhoneNumber.
+ // Do not set PhoneAccountHandle so that regular PreCall logic will be used. The account used to
+ // place or receive the call should be ignored for voice calls.
+ CallIntentBuilder callIntentBuilder =
+ new CallIntentBuilder(moduleInfo.getNormalizedNumber(), getCallInitiationType())
+ .setAllowAssistedDial(moduleInfo.getCanSupportAssistedDialing());
+ modules.add(IntentModule.newCallModule(context, callIntentBuilder));
+ return this;
+ }
+
+ /**
+ * Adds a module for a carrier video call *or* a Duo video call.
+ *
+ * <p>If the number is blocked or marked as spam, this method is a no-op.
+ *
+ * <p>If the provided module info is for a Duo video call and Duo is available, add a Duo video
+ * call module.
+ *
+ * <p>If the provided module info is for a Duo video call but Duo is unavailable, add a carrier
+ * video call module.
+ *
+ * <p>If the provided module info is for a carrier video call, add a carrier video call module.
+ *
+ * <p>If the provided module info is for a voice call and the device has carrier video call
+ * capability, add a carrier video call module.
+ *
+ * <p>If the provided module info is for a voice call, the device doesn't have carrier video call
+ * capability, and Duo is available, add a Duo video call module.
+ */
+ public HistoryItemActionModulesBuilder addModuleForVideoCall() {
+ if (moduleInfo.getIsBlocked() || moduleInfo.getIsSpam()) {
+ return this;
+ }
+
+ // Do not set PhoneAccountHandle so that regular PreCall logic will be used. The account used to
+ // place or receive the call should be ignored for carrier video calls.
+ // TODO(a bug): figure out the correct video call behavior
+ HistoryItemActionModule carrierVideoCallModule =
+ IntentModule.newCallModule(
+ context,
+ new CallIntentBuilder(moduleInfo.getNormalizedNumber(), getCallInitiationType())
+ .setAllowAssistedDial(moduleInfo.getCanSupportAssistedDialing())
+ .setIsVideoCall(true));
+ HistoryItemActionModule duoVideoCallModule =
+ new DuoCallModule(context, moduleInfo.getNormalizedNumber());
+
+ // If the module info is for a video call, add an appropriate video call module.
+ if ((moduleInfo.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) {
+ modules.add(isDuoCall() && canPlaceDuoCall() ? duoVideoCallModule : carrierVideoCallModule);
+ return this;
+ }
+
+ // At this point, the module info is for an audio call. We will also add a video call module if
+ // the video capability is present.
+ //
+ // The carrier video call module takes precedence over the Duo module.
+ if (canPlaceCarrierVideoCall()) {
+ modules.add(carrierVideoCallModule);
+ } else if (canPlaceDuoCall()) {
+ modules.add(duoVideoCallModule);
+ }
+ return this;
+ }
+
+ /**
+ * Adds a module for sending text messages.
+ *
+ * <p>The method is a no-op if the number is blocked or empty.
+ */
+ public HistoryItemActionModulesBuilder addModuleForSendingTextMessage() {
+ // TODO(zachh): There are other conditions where this module should not be shown; consider
+ // voicemail, business numbers, etc.
+ if (moduleInfo.getIsBlocked() || TextUtils.isEmpty(moduleInfo.getNormalizedNumber())) {
+ return this;
+ }
+
+ modules.add(
+ IntentModule.newModuleForSendingTextMessage(context, moduleInfo.getNormalizedNumber()));
+ return this;
+ }
+
+ /**
+ * Adds a module for a divider.
+ *
+ * <p>The method is a no-op if the divider module will be the first module.
+ */
+ public HistoryItemActionModulesBuilder addModuleForDivider() {
+ if (modules.isEmpty()) {
+ return this;
+ }
+
+ modules.add(new DividerModule());
+ return this;
+ }
+
+ /**
+ * Adds a module for adding a number to Contacts.
+ *
+ * <p>The method is a no-op if
+ *
+ * <ul>
+ * <li>the number is blocked,
+ * <li>the number is marked as spam,
+ * <li>the number is empty, or
+ * <li>the number belongs to an existing contact.
+ * </ul>
+ */
+ public HistoryItemActionModulesBuilder addModuleForAddingToContacts() {
+ if (moduleInfo.getIsBlocked()
+ || moduleInfo.getIsSpam()
+ || isExistingContact()
+ || TextUtils.isEmpty(moduleInfo.getNormalizedNumber())) {
+ return this;
+ }
+
+ Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
+ intent.putExtra(ContactsContract.Intents.Insert.PHONE, moduleInfo.getNormalizedNumber());
+
+ if (!TextUtils.isEmpty(moduleInfo.getName())) {
+ intent.putExtra(ContactsContract.Intents.Insert.NAME, moduleInfo.getName());
+ }
+
+ modules.add(
+ new IntentModule(
+ context,
+ intent,
+ R.string.add_to_contacts,
+ R.drawable.quantum_ic_person_add_vd_theme_24));
+ return this;
+ }
+
+ /**
+ * Add modules for blocking/unblocking a number and/or marking it as spam/not spam.
+ *
+ * <p>If a number is marked as spam, add two modules:
+ *
+ * <ul>
+ * <li>"Not spam" and "Block", or
+ * <li>"Not spam" and "Unblock".
+ * </ul>
+ *
+ * <p>If a number is blocked but not marked as spam, add the "Unblock" module.
+ *
+ * <p>If a number is not blocked or marked as spam, add the "Block/Report spam" module.
+ */
+ public HistoryItemActionModulesBuilder addModuleForBlockedOrSpamNumber() {
+ BlockReportSpamDialogInfo blockReportSpamDialogInfo =
+ BlockReportSpamDialogInfo.newBuilder()
+ .setNormalizedNumber(moduleInfo.getNormalizedNumber())
+ .setCountryIso(moduleInfo.getCountryIso())
+ .setCallType(moduleInfo.getCallType())
+ .setReportingLocation(getReportingLocation())
+ .setContactSource(moduleInfo.getContactSource())
+ .build();
+
+ // For a spam number, add two modules:
+ // (1) "Not spam" and "Block", or
+ // (2) "Not spam" and "Unblock".
+ if (moduleInfo.getIsSpam()) {
+ modules.add(
+ BlockReportSpamModules.moduleForMarkingNumberAsNotSpam(
+ context, blockReportSpamDialogInfo));
+ modules.add(
+ moduleInfo.getIsBlocked()
+ ? BlockReportSpamModules.moduleForUnblockingNumber(context, blockReportSpamDialogInfo)
+ : BlockReportSpamModules.moduleForBlockingNumber(context, blockReportSpamDialogInfo));
+ return this;
+ }
+
+ // For a blocked non-spam number, add the "Unblock" module.
+ if (moduleInfo.getIsBlocked()) {
+ modules.add(
+ BlockReportSpamModules.moduleForUnblockingNumber(context, blockReportSpamDialogInfo));
+ return this;
+ }
+
+ // For a number that is neither a spam number nor blocked, add the "Block/Report spam" module.
+ modules.add(
+ BlockReportSpamModules.moduleForBlockingNumberAndOptionallyReportingSpam(
+ context, blockReportSpamDialogInfo));
+ return this;
+ }
+
+ /**
+ * Adds a module for copying a number.
+ *
+ * <p>The method is a no-op if the number is empty.
+ */
+ public HistoryItemActionModulesBuilder addModuleForCopyingNumber() {
+ if (TextUtils.isEmpty(moduleInfo.getNormalizedNumber())) {
+ return this;
+ }
+
+ modules.add(
+ new HistoryItemActionModule() {
+ @Override
+ public int getStringId() {
+ return R.string.copy_number;
+ }
+
+ @Override
+ public int getDrawableId() {
+ return R.drawable.quantum_ic_content_copy_vd_theme_24;
+ }
+
+ @Override
+ public boolean onClick() {
+ ClipboardUtils.copyText(
+ context,
+ /* label = */ null,
+ moduleInfo.getNormalizedNumber(),
+ /* showToast = */ true);
+ return false;
+ }
+ });
+ return this;
+ }
+
+ private boolean canPlaceCarrierVideoCall() {
+ int carrierVideoAvailability = CallUtil.getVideoCallingAvailability(context);
+ boolean isCarrierVideoCallingEnabled =
+ ((carrierVideoAvailability & CallUtil.VIDEO_CALLING_ENABLED)
+ == CallUtil.VIDEO_CALLING_ENABLED);
+ boolean canRelyOnCarrierVideoPresence =
+ ((carrierVideoAvailability & CallUtil.VIDEO_CALLING_PRESENCE)
+ == CallUtil.VIDEO_CALLING_PRESENCE);
+
+ return isCarrierVideoCallingEnabled
+ && canRelyOnCarrierVideoPresence
+ && moduleInfo.getCanSupportCarrierVideoCall();
+ }
+
+ private boolean isDuoCall() {
+ return DuoComponent.get(context)
+ .getDuo()
+ .isDuoAccount(moduleInfo.getPhoneAccountComponentName());
+ }
+
+ private boolean canPlaceDuoCall() {
+ Duo duo = DuoComponent.get(context).getDuo();
+
+ return duo.isInstalled(context)
+ && duo.isEnabled(context)
+ && duo.isActivated(context)
+ && duo.isReachable(context, moduleInfo.getNormalizedNumber());
+ }
+
+ /**
+ * Lookup URIs are currently fetched from the cached column of the system call log. This URI
+ * contains encoded information for non-contacts for the purposes of populating contact cards.
+ *
+ * <p>We infer whether a contact is existing or not by checking if the lookup URI is "encoded" or
+ * not.
+ *
+ * <p>TODO(zachh): We should revisit this once the contact URI is no longer being read from the
+ * cached column in the system database, in case we decide not to overload the column.
+ */
+ private boolean isExistingContact() {
+ return !TextUtils.isEmpty(moduleInfo.getLookupUri())
+ && !UriUtils.isEncodedContactUri(Uri.parse(moduleInfo.getLookupUri()));
+ }
+
+ /**
+ * Maps the value of {@link HistoryItemActionModuleInfo#getHost()} to {@link
+ * CallInitiationType.Type}, which is required by {@link CallIntentBuilder} to build a call
+ * intent.
+ */
+ private CallInitiationType.Type getCallInitiationType() {
+ switch (moduleInfo.getHost()) {
+ case CALL_LOG:
+ return CallInitiationType.Type.CALL_LOG;
+ case VOICEMAIL:
+ return CallInitiationType.Type.VOICEMAIL_LOG;
+ default:
+ throw Assert.createUnsupportedOperationFailException(
+ String.format("Unsupported host: %s", moduleInfo.getHost()));
+ }
+ }
+
+ /**
+ * Maps the value of {@link HistoryItemActionModuleInfo#getHost()} to {@link
+ * ReportingLocation.Type}, which is for logging where a spam number is reported.
+ */
+ private ReportingLocation.Type getReportingLocation() {
+ switch (moduleInfo.getHost()) {
+ case CALL_LOG:
+ return ReportingLocation.Type.CALL_LOG_HISTORY;
+ case VOICEMAIL:
+ return ReportingLocation.Type.VOICEMAIL_HISTORY;
+ default:
+ throw Assert.createUnsupportedOperationFailException(
+ String.format("Unsupported host: %s", moduleInfo.getHost()));
+ }
+ }
+}
diff --git a/java/com/android/dialer/historyitemactions/IntentModule.java b/java/com/android/dialer/historyitemactions/IntentModule.java
index f73d4c951..dc53064af 100644
--- a/java/com/android/dialer/historyitemactions/IntentModule.java
+++ b/java/com/android/dialer/historyitemactions/IntentModule.java
@@ -23,6 +23,7 @@ import android.support.annotation.StringRes;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.precall.PreCall;
import com.android.dialer.util.DialerUtils;
+import com.android.dialer.util.IntentUtil;
/**
* {@link HistoryItemActionModule} useful for making easy to build modules based on starting an
@@ -73,4 +74,12 @@ public class IntentModule implements HistoryItemActionModule {
return new IntentModule(context, PreCall.getIntent(context, callIntentBuilder), text, image);
}
+
+ public static IntentModule newModuleForSendingTextMessage(Context context, String number) {
+ return new IntentModule(
+ context,
+ IntentUtil.getSendSmsIntent(number),
+ R.string.send_a_message,
+ R.drawable.quantum_ic_message_vd_theme_24);
+ }
}
diff --git a/java/com/android/dialer/historyitemactions/SharedModules.java b/java/com/android/dialer/historyitemactions/SharedModules.java
deleted file mode 100644
index 8604bed1d..000000000
--- a/java/com/android/dialer/historyitemactions/SharedModules.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * 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
- */
-
-package com.android.dialer.historyitemactions;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-import com.android.dialer.DialerPhoneNumber;
-import com.android.dialer.blockreportspam.BlockReportSpamDialogInfo;
-import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogNotifier;
-import com.android.dialer.clipboard.ClipboardUtils;
-import com.android.dialer.util.IntentUtil;
-import com.android.dialer.util.UriUtils;
-import com.google.common.base.Optional;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Modules for the bottom sheet that are shared between NewVoicemailFragment and NewCallLogFragment
- */
-@SuppressWarnings("Guava")
-public class SharedModules {
-
- public static Optional<HistoryItemActionModule> createModuleForAddingToContacts(
- Context context,
- DialerPhoneNumber dialerPhoneNumber,
- String name,
- String lookupUri,
- boolean isBlocked,
- boolean isSpam) {
- // Skip showing the menu item for a spam/blocked number.
- if (isBlocked || isSpam) {
- return Optional.absent();
- }
-
- // Skip showing the menu item for existing contacts.
- if (isExistingContact(lookupUri)) {
- return Optional.absent();
- }
-
- // Skip showing the menu item if there is no number.
- String normalizedNumber = dialerPhoneNumber.getNormalizedNumber();
- if (TextUtils.isEmpty(normalizedNumber)) {
- return Optional.absent();
- }
-
- Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
- intent.putExtra(ContactsContract.Intents.Insert.PHONE, normalizedNumber);
-
- if (!TextUtils.isEmpty(name)) {
- intent.putExtra(ContactsContract.Intents.Insert.NAME, name);
- }
-
- return Optional.of(
- new IntentModule(
- context,
- intent,
- R.string.add_to_contacts,
- R.drawable.quantum_ic_person_add_vd_theme_24));
- }
-
- /**
- * Lookup URIs are currently fetched from the cached column of the system call log. This URI
- * contains encoded information for non-contacts for the purposes of populating contact cards.
- *
- * <p>We infer whether a contact is existing or not by checking if the lookup URI is "encoded" or
- * not.
- *
- * <p>TODO(zachh): We should revisit this once the contact URI is no longer being read from the
- * cached column in the system database, in case we decide not to overload the column.
- */
- private static boolean isExistingContact(@Nullable String lookupUri) {
- return !TextUtils.isEmpty(lookupUri) && !UriUtils.isEncodedContactUri(Uri.parse(lookupUri));
- }
-
- public static Optional<HistoryItemActionModule> createModuleForSendingTextMessage(
- Context context, String normalizedNumber, boolean isBlocked) {
- // Don't show the option to send a text message if the number is blocked.
- if (isBlocked) {
- return Optional.absent();
- }
-
- // TODO(zachh): There are some conditions where this module should not be shown; consider
- // voicemail, business numbers, etc.
-
- return !TextUtils.isEmpty(normalizedNumber)
- ? Optional.of(
- new IntentModule(
- context,
- IntentUtil.getSendSmsIntent(normalizedNumber),
- R.string.send_a_message,
- R.drawable.quantum_ic_message_vd_theme_24))
- : Optional.absent();
- }
-
- /**
- * Create modules related to blocking/unblocking a number and/or reporting it as spam/not spam.
- */
- public static List<HistoryItemActionModule> createModulesHandlingBlockedOrSpamNumber(
- Context context,
- BlockReportSpamDialogInfo blockReportSpamDialogInfo,
- boolean isBlocked,
- boolean isSpam) {
- List<HistoryItemActionModule> modules = new ArrayList<>();
-
- // For a spam number, add two options:
- // (1) "Not spam" and "Block", or
- // (2) "Not spam" and "Unblock".
- if (isSpam) {
- modules.add(createModuleForMarkingNumberAsNonSpam(context, blockReportSpamDialogInfo));
- modules.add(
- createModuleForBlockingOrUnblockingNumber(context, blockReportSpamDialogInfo, isBlocked));
- return modules;
- }
-
- // For a blocked non-spam number, add "Unblock" option.
- if (isBlocked) {
- modules.add(
- createModuleForBlockingOrUnblockingNumber(context, blockReportSpamDialogInfo, isBlocked));
- return modules;
- }
-
- // For a number that is neither a spam number nor blocked, add "Block/Report spam" option.
- modules.add(
- createModuleForBlockingNumberAndOptionallyReportingSpam(
- context, blockReportSpamDialogInfo));
- return modules;
- }
-
- /** Create "Not spam" module. */
- private static HistoryItemActionModule createModuleForMarkingNumberAsNonSpam(
- Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) {
- return new HistoryItemActionModule() {
- @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() {
- ShowBlockReportSpamDialogNotifier.notifyShowDialogToReportNotSpam(
- context, blockReportSpamDialogInfo);
- return true; // Close the bottom sheet.
- }
- };
- }
-
- private static HistoryItemActionModule createModuleForBlockingOrUnblockingNumber(
- Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo, boolean isBlocked) {
- return new HistoryItemActionModule() {
- @Override
- public int getStringId() {
- return isBlocked ? R.string.unblock_number : R.string.block_number;
- }
-
- @Override
- public int getDrawableId() {
- return isBlocked
- ? R.drawable.quantum_ic_unblock_vd_theme_24
- : R.drawable.quantum_ic_block_vd_theme_24;
- }
-
- @Override
- public boolean onClick() {
- if (isBlocked) {
- ShowBlockReportSpamDialogNotifier.notifyShowDialogToUnblockNumber(
- context, blockReportSpamDialogInfo);
- } else {
- ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumber(
- context, blockReportSpamDialogInfo);
- }
- return true; // Close the bottom sheet.
- }
- };
- }
-
- /** Create "Block/Report spam" module */
- private static HistoryItemActionModule createModuleForBlockingNumberAndOptionallyReportingSpam(
- Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) {
- return new HistoryItemActionModule() {
- @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() {
- ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumberAndOptionallyReportSpam(
- context, blockReportSpamDialogInfo);
- return true; // Close the bottom sheet.
- }
- };
- }
-
- public static Optional<HistoryItemActionModule> createModuleForCopyingNumber(
- Context context, String normalizedNumber) {
- if (TextUtils.isEmpty(normalizedNumber)) {
- return Optional.absent();
- }
- return Optional.of(
- new HistoryItemActionModule() {
- @Override
- public int getStringId() {
- return R.string.copy_number;
- }
-
- @Override
- public int getDrawableId() {
- return R.drawable.quantum_ic_content_copy_vd_theme_24;
- }
-
- @Override
- public boolean onClick() {
- ClipboardUtils.copyText(context, null, normalizedNumber, true);
- return false;
- }
- });
- }
-}
diff --git a/java/com/android/dialer/historyitemactions/history_item_action_module_info.proto b/java/com/android/dialer/historyitemactions/history_item_action_module_info.proto
new file mode 100644
index 000000000..99071a7cd
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/history_item_action_module_info.proto
@@ -0,0 +1,69 @@
+syntax = "proto2";
+
+option java_package = "com.android.dialer.historyitemactions";
+option java_multiple_files = true;
+option optimize_for = LITE_RUNTIME;
+
+
+package com.android.dialer.historyitemactions;
+
+import "java/com/android/dialer/logging/contact_source.proto";
+
+// Contains information needed to construct items (modules) in a bottom sheet.
+// Next ID: 16
+message HistoryItemActionModuleInfo {
+ // The dialer-normalized version of a phone number.
+ // See DialerPhoneNumber.normalized_number.
+ optional string normalized_number = 1;
+
+ // The ISO 3166-1 two letters country code of the number.
+ optional string country_iso = 2;
+
+ // The name associated with the number.
+ optional string name = 3;
+
+ // The type of the call.
+ // See android.provider.CallLog.Calls.TYPE.
+ optional int32 call_type = 4;
+
+ // Bit-mask describing features of the call.
+ // See android.provider.CallLog.Calls.FEATURES.
+ optional int32 features = 5;
+
+ // The Contacts Provider lookup URI for the contact associated with the
+ // number.
+ optional string lookup_uri = 6;
+
+ // The component name of the account used to place or receive the call.
+ // See android.provider.CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME.
+ optional string phone_account_component_name = 7;
+
+ // Whether the number can be reported as invalid through People API
+ optional bool can_report_as_invalid_number = 8;
+
+ // Whether assisted dialing is supported.
+ optional bool can_support_assisted_dialing = 9;
+
+ // Whether carrier video call is supported.
+ optional bool can_support_carrier_video_call = 10;
+
+ // Whether the number is blocked.
+ optional bool is_blocked = 11;
+
+ // Whether the number is spam.
+ optional bool is_spam = 12;
+
+ // Whether the call is to the voicemail inbox.
+ optional bool is_voicemail_call = 13;
+
+ // The source of the contact if there is one associated with the number.
+ optional com.android.dialer.logging.ContactSource.Type contact_source = 14;
+
+ // Places that can host items (modules) in a bottom sheet
+ enum Host {
+ UNKNOWN = 0;
+ CALL_LOG = 1;
+ VOICEMAIL = 2;
+ }
+ optional Host host = 15;
+}