summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/historyitemactions
diff options
context:
space:
mode:
authorEric Erfanian <erfanian@google.com>2018-05-07 14:58:35 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-05-07 14:58:35 +0000
commit84b862acd2c53f665386f1dfd23b57c2bdcf5baf (patch)
tree78bf30ec2633948a69facf84ebfa84a979d814f3 /java/com/android/dialer/historyitemactions
parent95c2775dd2b77f9fce454d655d2b23ed700d7f22 (diff)
parent763ce4404ae8e4199da719359a1b01389884cec4 (diff)
Merge changes Ibab0bc7e,I1cb26187,I64225b78,I4806ab65,I7d431e74, ...
* changes: Remove TODOs for showing SIM info in the bottom sheet & call details. Use Telecom Bluetooth API instead of system Bluetooth API. Update audio route after user select different audio route. Clear NewCallLogViewHolder.onClickListener if row is not callable. Filter out unnecessary bottom sheet options for a call to a voicemail box. Aosp fix for v28-support-prelease bottom sheet. Mark photo info as voicemails in bottom sheet Simplify how we build bottom sheet options (a.k.a. modules). Add test to verify no crash on multiple DialerCall#onRemovedFromCallList. Add spam status tests for CallList#onCallAdded More refactoring
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.java422
-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
-rw-r--r--java/com/android/dialer/historyitemactions/history_item_bottom_sheet_header_info.proto2
6 files changed, 620 insertions, 249 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..9af08be50
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java
@@ -0,0 +1,422 @@
+/*
+ * 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>This method is a no-op if
+ *
+ * <ul>
+ * <li>the call is one made to a voicemail box,
+ * <li>the number is blocked, or
+ * <li>the number is marked as spam.
+ * </ul>
+ *
+ * <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.getIsVoicemailCall() || 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
+ *
+ * <ul>
+ * <li>the call is one made to a voicemail box,
+ * <li>the number is blocked, or
+ * <li>the number is empty.
+ * </ul>
+ */
+ public HistoryItemActionModulesBuilder addModuleForSendingTextMessage() {
+ // TODO(zachh): There are other conditions where this module should not be shown
+ // (e.g., business numbers).
+ if (moduleInfo.getIsVoicemailCall()
+ || 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 call is one made to a voicemail box,
+ * <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.getIsVoicemailCall()
+ || 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>The method is a no-op if the call is one made to a voicemail box.
+ *
+ * <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() {
+ if (moduleInfo.getIsVoicemailCall()) {
+ return this;
+ }
+
+ 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;
+}
diff --git a/java/com/android/dialer/historyitemactions/history_item_bottom_sheet_header_info.proto b/java/com/android/dialer/historyitemactions/history_item_bottom_sheet_header_info.proto
index ef71ecd7e..04d9f2259 100644
--- a/java/com/android/dialer/historyitemactions/history_item_bottom_sheet_header_info.proto
+++ b/java/com/android/dialer/historyitemactions/history_item_bottom_sheet_header_info.proto
@@ -36,6 +36,4 @@ message HistoryItemBottomSheetHeaderInfo {
// "Blocked • Mobile • 555-1234", and
// "Spam • Mobile • 555-1234".
optional string secondary_text = 4;
-
- // TODO(a bug): Add SIM info.
}