From 4bbb9c8b606eee55462bfd5d96c50d4fbabe819f Mon Sep 17 00:00:00 2001 From: Qi Wang Date: Thu, 31 Mar 2016 11:11:01 -0700 Subject: Integrate spam feature into call logs. + Add block and report spam actions. + Show spam icon and label for call log item. + Add stableIds for CallLogAdapter to improve performance(reuse same viewItem to minimize update work). * Fix funky UI of call log. Change-Id: I6144d70b6a8e38061e1447d0d01910d53026d1db Fix: 27295728 Fix: 26907466 --- InCallUI/src/com/android/incallui/CallList.java | 2 +- res/layout/call_log_list_item_actions.xml | 59 +++++++- res/values/strings.xml | 23 ++++ src/com/android/dialer/PhoneCallDetails.java | 3 + src/com/android/dialer/calllog/CallLogAdapter.java | 151 +++++++++++++++------ .../dialer/calllog/CallLogListItemHelper.java | 2 + .../dialer/calllog/CallLogListItemViewHolder.java | 115 +++++++++------- .../dialer/calllog/PhoneCallDetailsHelper.java | 6 +- .../dialer/service/ExtendedCallInfoService.java | 17 ++- 9 files changed, 278 insertions(+), 100 deletions(-) diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java index a3a9d743e..61e8aa452 100644 --- a/InCallUI/src/com/android/incallui/CallList.java +++ b/InCallUI/src/com/android/incallui/CallList.java @@ -96,7 +96,7 @@ public class CallList { onIncoming(call, call.getCannedSmsResponses()); if (mExtendedCallInfoService != null) { String number = TelecomCallUtil.getNumber(telecomCall); - mExtendedCallInfoService.getExtendedCallInfo(number, + mExtendedCallInfoService.getExtendedCallInfo(number, null, new ExtendedCallInfoService.Listener() { @Override public void onComplete(boolean isSpam) { diff --git a/res/layout/call_log_list_item_actions.xml b/res/layout/call_log_list_item_actions.xml index 78203b72d..4aad6195a 100644 --- a/res/layout/call_log_list_item_actions.xml +++ b/res/layout/call_log_list_item_actions.xml @@ -129,10 +129,61 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + ^1 is active + + + Block/report spam + + + Block + + + Not spam + + + Unblock + + + Spam diff --git a/src/com/android/dialer/PhoneCallDetails.java b/src/com/android/dialer/PhoneCallDetails.java index b332b43cc..16192fc11 100644 --- a/src/com/android/dialer/PhoneCallDetails.java +++ b/src/com/android/dialer/PhoneCallDetails.java @@ -111,6 +111,9 @@ public class PhoneCallDetails { */ public boolean isRead = true; + // If this call is a spam number. + public boolean isSpam = false; + /** * Constructor with required fields for the details of a call with a number associated with a * contact. diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java index 165594efa..e826867ab 100644 --- a/src/com/android/dialer/calllog/CallLogAdapter.java +++ b/src/com/android/dialer/calllog/CallLogAdapter.java @@ -16,8 +16,13 @@ package com.android.dialer.calllog; +import com.android.dialer.compat.FilteredNumberCompat; +import com.android.dialer.filterednumber.BlockNumberDialogFragment; +import com.android.dialer.service.ExtendedCallInfoService; +import com.android.dialerbind.ObjectFactory; import com.google.common.annotations.VisibleForTesting; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -32,10 +37,8 @@ import android.provider.ContactsContract.CommonDataKinds.Phone; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; import android.telecom.PhoneAccountHandle; -import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.text.TextUtils; -import android.util.ArrayMap; import android.view.LayoutInflater; import android.view.View; import android.view.View.AccessibilityDelegate; @@ -55,15 +58,12 @@ import com.android.dialer.contactinfo.ContactInfoCache; import com.android.dialer.contactinfo.ContactInfoCache.OnContactInfoChangedListener; import com.android.dialer.database.FilteredNumberAsyncQueryHandler; import com.android.dialer.database.VoicemailArchiveContract; -import com.android.dialer.filterednumber.BlockNumberDialogFragment.Callback; import com.android.dialer.logging.InteractionEvent; import com.android.dialer.logging.Logger; -import com.android.dialer.service.ExtendedBlockingButtonRenderer; import com.android.dialer.util.PhoneNumberUtil; import com.android.dialer.voicemail.VoicemailPlaybackPresenter; import java.util.HashMap; -import java.util.Map; /** * Adapter class to fill in data for the Call Log. @@ -71,7 +71,7 @@ import java.util.Map; public class CallLogAdapter extends GroupingListAdapter implements CallLogGroupBuilder.GroupCreator, VoicemailPlaybackPresenter.OnVoicemailDeletedListener, - ExtendedBlockingButtonRenderer.Listener { + CallLogListItemViewHolder.OnClickListener { // Types of activities the call log adapter is used for public static final int ACTIVITY_TYPE_CALL_LOG = 1; @@ -104,7 +104,6 @@ public class CallLogAdapter extends GroupingListAdapter protected final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; private final CallFetcher mCallFetcher; private final FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler; - private final Map mBlockedNumberCache = new ArrayMap<>(); protected ContactInfoCache mContactInfoCache; @@ -121,6 +120,26 @@ public class CallLogAdapter extends GroupingListAdapter private int mHiddenPosition = RecyclerView.NO_POSITION; private Uri mHiddenItemUri = null; private boolean mPendingHide = false; + private BlockNumberDialogFragment.Callback mBlockedNumberDialogCallback = + new BlockNumberDialogFragment.Callback() { + @Override + public void onFilterNumberSuccess() { + Logger.logInteraction( + InteractionEvent.BLOCK_NUMBER_CALL_LOG); + notifyDataSetChanged(); + } + + @Override + public void onUnfilterNumberSuccess() { + Logger.logInteraction( + InteractionEvent.UNBLOCK_NUMBER_CALL_LOG); + notifyDataSetChanged(); + } + + @Override + public void onChangeFilteredNumberUndo() { + } + }; /** * Hashmap, keyed by call Id, used to track the day group for a call. As call log entries are @@ -153,6 +172,8 @@ public class CallLogAdapter extends GroupingListAdapter /** Helper to group call log entries. */ private final CallLogGroupBuilder mCallLogGroupBuilder; + private ExtendedCallInfoService mExtendedCallInfoService; + /** * The OnClickListener used to expand or collapse the action buttons of a call log entry. */ @@ -296,6 +317,9 @@ public class CallLogAdapter extends GroupingListAdapter mPrefs = PreferenceManager.getDefaultSharedPreferences(context); mContactsPreferences = new ContactsPreferences(mContext); maybeShowVoicemailPromoCard(); + + mExtendedCallInfoService = ObjectFactory.newExtendedCallInfoService(context); + setHasStableIds(true); } public void onSaveInstanceState(Bundle outState) { @@ -313,21 +337,33 @@ public class CallLogAdapter extends GroupingListAdapter } @Override - public void onBlockedNumber(String number,String countryIso) { - String cacheKey = PhoneNumberUtils.formatNumberToE164(number, countryIso); - if (!TextUtils.isEmpty(cacheKey)) { - mBlockedNumberCache.put(cacheKey, true); - notifyDataSetChanged(); - } + public void onBlockReportSpam(String number, String countryIso, String displayNumber) { + mExtendedCallInfoService.reportSpam(number, countryIso); + notifyDataSetChanged(); } @Override - public void onUnblockedNumber( String number, String countryIso) { - String cacheKey = PhoneNumberUtils.formatNumberToE164(number, countryIso); - if (!TextUtils.isEmpty(cacheKey)) { - mBlockedNumberCache.put(cacheKey, false); - notifyDataSetChanged(); - } + public void onBlock(String number, String countryIso, String displayNumber) { + FilteredNumberCompat + .showBlockNumberDialogFlow(mContext.getContentResolver(), null, number, + countryIso, displayNumber, R.id.floating_action_button_container, + ((Activity) mContext).getFragmentManager(), + mBlockedNumberDialogCallback); + } + + @Override + public void onUnblock(String number, String countryIso, Integer blockId, String displayNumber) { + FilteredNumberCompat + .showBlockNumberDialogFlow(mContext.getContentResolver(), blockId, number, + countryIso, displayNumber, R.id.floating_action_button_container, + ((Activity) mContext).getFragmentManager(), + mBlockedNumberDialogCallback); + } + + @Override + public void onReportNotSpam(String number, String countryIso, String displayNumber) { + mExtendedCallInfoService.reportNotSpam(number, countryIso); + notifyDataSetChanged(); } /** @@ -412,22 +448,8 @@ public class CallLogAdapter extends GroupingListAdapter mCallLogListItemHelper, mVoicemailPlaybackPresenter, mFilteredNumberAsyncQueryHandler, - new Callback() { - @Override - public void onFilterNumberSuccess() { - Logger.logInteraction( - InteractionEvent.BLOCK_NUMBER_CALL_LOG); - } - - @Override - public void onUnfilterNumberSuccess() { - Logger.logInteraction( - InteractionEvent.UNBLOCK_NUMBER_CALL_LOG); - } - - @Override - public void onChangeFilteredNumberUndo() {} - }, mActivityType == ACTIVITY_TYPE_ARCHIVE); + mBlockedNumberDialogCallback, + mActivityType == ACTIVITY_TYPE_ARCHIVE); viewHolder.callLogEntryView.setTag(viewHolder); viewHolder.callLogEntryView.setAccessibilityDelegate(mAccessibilityDelegate); @@ -481,7 +503,40 @@ public class CallLogAdapter extends GroupingListAdapter * @param position The position of the list item. */ - private void bindCallLogListViewHolder(ViewHolder viewHolder, int position) { + private void bindCallLogListViewHolder(final ViewHolder viewHolder, final int position) { + Cursor c = (Cursor) getItem(position); + if (c == null) { + return; + } + + final String number = c.getString(CallLogQuery.NUMBER); + final String countryIso = c.getString(CallLogQuery.COUNTRY_ISO); + + mFilteredNumberAsyncQueryHandler.isBlockedNumber( + new FilteredNumberAsyncQueryHandler.OnCheckBlockedListener() { + @Override + public void onCheckComplete(Integer id) { + final CallLogListItemViewHolder views = + (CallLogListItemViewHolder) viewHolder; + views.blockId = id; + if (mExtendedCallInfoService == null) { + loadDataAndRender(views); + } else { + mExtendedCallInfoService.getExtendedCallInfo(number, countryIso, + new ExtendedCallInfoService.Listener() { + @Override + public void onComplete(boolean isSpam) { + views.isSpam = isSpam; + loadDataAndRender(views); + } + }); + } + } + }, number, countryIso); + } + + private void loadDataAndRender(CallLogListItemViewHolder views) { + int position = views.getAdapterPosition(); Cursor c = (Cursor) getItem(position); if (c == null) { return; @@ -544,7 +599,6 @@ public class CallLogAdapter extends GroupingListAdapter details.contactUserType = info.userType; } - final CallLogListItemViewHolder views = (CallLogListItemViewHolder) viewHolder; views.info = info; views.rowId = c.getLong(CallLogQuery.ID); // Store values used when the actions ViewStub is inflated on expansion. @@ -589,19 +643,22 @@ public class CallLogAdapter extends GroupingListAdapter views.voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI); } - mCallLogListItemHelper.setPhoneCallDetails(views, details); + // Reversely pass spam information from views since details is not constructed when spam + // information comes back. This is used to render phone call details. + details.isSpam = views.isSpam; + render(views, details); + } + private void render(CallLogListItemViewHolder views, PhoneCallDetails details) { + mCallLogListItemHelper.setPhoneCallDetails(views, details); if (mCurrentlyExpandedRowId == views.rowId) { // In case ViewHolders were added/removed, update the expanded position if the rowIds // match so that we can restore the correct expanded state on rebind. - mCurrentlyExpandedPosition = position; + mCurrentlyExpandedPosition = views.getAdapterPosition(); views.showActions(true); } else { views.showActions(false); } - views.updatePhoto(); - - mCallLogListItemHelper.setPhoneCallDetails(views, details); } private String getPreferredDisplayName(ContactInfo contactInfo) { @@ -640,6 +697,16 @@ public class CallLogAdapter extends GroupingListAdapter ? 1 : 0)); } + @Override + public long getItemId(int position) { + Cursor cursor = (Cursor) getItem(position); + if (cursor != null) { + return cursor.getLong(CallLogQuery.ID); + } else { + return 0; + } + } + @Override public int getGroupSize(int position) { return super.getGroupSize(position - (mShowVoicemailPromoCard ? 1 : 0)); diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java index 5d2bc8591..7919a0985 100644 --- a/src/com/android/dialer/calllog/CallLogListItemHelper.java +++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java @@ -82,6 +82,8 @@ import com.android.dialer.calllog.calllogcache.CallLogCache; // Cache country iso. Used for number filtering. views.countryIso = details.countryIso; + + views.updatePhoto(); } /** diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java index baf2e1ab5..53e6fbba8 100644 --- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java +++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java @@ -57,15 +57,10 @@ import com.android.dialer.filterednumber.BlockNumberDialogFragment; import com.android.dialer.filterednumber.FilteredNumbersUtil; import com.android.dialer.logging.Logger; import com.android.dialer.logging.ScreenEvent; -import com.android.dialer.service.ExtendedBlockingButtonRenderer; import com.android.dialer.util.DialerUtils; import com.android.dialer.util.PhoneNumberUtil; import com.android.dialer.voicemail.VoicemailPlaybackLayout; import com.android.dialer.voicemail.VoicemailPlaybackPresenter; -import com.android.dialerbind.ObjectFactory; -import com.google.common.collect.Lists; - -import java.util.List; /** * This is an object containing references to views contained by the call log list item. This @@ -77,6 +72,13 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, MenuItem.OnMenuItemClickListener, View.OnCreateContextMenuListener { + public interface OnClickListener { + void onBlockReportSpam(String number, String countryIso, String displayNumber); + void onBlock(String number, String countryIso, String displayNumber); + void onUnblock(String number, String countryIso, Integer blockId, String displayNumber); + void onReportNotSpam(String number, String countryIso, String displayNumber); + } + /** The root view of the call log list item */ public final View rootView; /** The quick contact badge for the contact. */ @@ -101,6 +103,10 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder public View createNewContactButtonView; public View addToExistingContactButtonView; public View sendMessageView; + public View blockReportView; + public View blockView; + public View unblockView; + public View reportNotSpamView; public View detailsButtonView; public View callWithNoteButtonView; public ImageView workIconView; @@ -198,9 +204,9 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder public ContactInfo info; /** - * Whether the current log entry is a blocked number or not. Used in updatePhoto() + * Whether the current log entry is a spam number or not. Used in updatePhoto() */ - public boolean isBlocked; + public boolean isSpam; /** * Whether this is the archive tab or not. @@ -212,19 +218,18 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder private final CallLogListItemHelper mCallLogListItemHelper; private final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; private final FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler; + private final OnClickListener mBlockReportListener; private final BlockNumberDialogFragment.Callback mFilteredNumberDialogCallback; private final int mPhotoSize; - private ViewStub mExtendedBlockingViewStub; - private final ExtendedBlockingButtonRenderer mExtendedBlockingButtonRenderer; private View.OnClickListener mExpandCollapseListener; private boolean mVoicemailPrimaryActionButtonClicked; private CallLogListItemViewHolder( Context context, - ExtendedBlockingButtonRenderer.Listener eventListener, + OnClickListener blockReportListener, View.OnClickListener expandCollapseListener, CallLogCache callLogCache, CallLogListItemHelper callLogListItemHelper, @@ -248,6 +253,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder mVoicemailPlaybackPresenter = voicemailPlaybackPresenter; mFilteredNumberAsyncQueryHandler = filteredNumberAsyncQueryHandler; mFilteredNumberDialogCallback = filteredNumberDialogCallback; + mBlockReportListener = blockReportListener; this.rootView = rootView; this.quickContactView = quickContactView; @@ -272,14 +278,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder primaryActionButtonView.setOnClickListener(this); primaryActionView.setOnClickListener(mExpandCollapseListener); primaryActionView.setOnCreateContextMenuListener(this); - mExtendedBlockingButtonRenderer = - ObjectFactory.newExtendedBlockingButtonRenderer(mContext, eventListener); } public static CallLogListItemViewHolder create( View view, Context context, - ExtendedBlockingButtonRenderer.Listener eventListener, + OnClickListener blockReportListener, View.OnClickListener expandCollapseListener, CallLogCache callLogCache, CallLogListItemHelper callLogListItemHelper, @@ -290,7 +294,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder return new CallLogListItemViewHolder( context, - eventListener, + blockReportListener, expandCollapseListener, callLogCache, callLogListItemHelper, @@ -428,14 +432,23 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder sendMessageView = actionsView.findViewById(R.id.send_message_action); sendMessageView.setOnClickListener(this); + blockReportView = actionsView.findViewById(R.id.block_report_action); + blockReportView.setOnClickListener(this); + + blockView = actionsView.findViewById(R.id.block_action); + blockView.setOnClickListener(this); + + unblockView = actionsView.findViewById(R.id.unblock_action); + unblockView.setOnClickListener(this); + + reportNotSpamView = actionsView.findViewById(R.id.report_not_spam_action); + reportNotSpamView.setOnClickListener(this); + detailsButtonView = actionsView.findViewById(R.id.details_action); detailsButtonView.setOnClickListener(this); callWithNoteButtonView = actionsView.findViewById(R.id.call_with_note_action); callWithNoteButtonView.setOnClickListener(this); - - mExtendedBlockingViewStub = - (ViewStub) actionsView.findViewById(R.id.extended_blocking_actions_container); } bindActionButtons(); @@ -568,32 +581,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder callWithNoteButtonView.setVisibility( supportsCallSubject && !isVoicemailNumber ? View.VISIBLE : View.GONE); - if(mExtendedBlockingButtonRenderer != null){ - List completeLogListItems = Lists.newArrayList( - createNewContactButtonView, - addToExistingContactButtonView, - sendMessageView, - callButtonView, - callWithNoteButtonView, - detailsButtonView, - voicemailPlaybackView); - - List blockedNumberVisibleViews = Lists.newArrayList(detailsButtonView); - List extendedBlockingVisibleViews = Lists.newArrayList(detailsButtonView); - - ExtendedBlockingButtonRenderer.ViewHolderInfo viewHolderInfo = - new ExtendedBlockingButtonRenderer.ViewHolderInfo( - completeLogListItems, - extendedBlockingVisibleViews, - blockedNumberVisibleViews, - number, - countryIso, - nameOrNumber.toString(), - displayNumber); - mExtendedBlockingButtonRenderer.setViewHolderInfo(viewHolderInfo); - - mExtendedBlockingButtonRenderer.render(mExtendedBlockingViewStub); - } + updateBlockReportActions(); } /** @@ -635,6 +623,11 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder } public void updatePhoto() { + if (isSpam) { + quickContactView.setImageDrawable( + mContext.getDrawable(R.drawable.blocked_contact)); + return; + } quickContactView.assignContactUri(info.lookupUri); final boolean isVoicemail = mCallLogCache.isVoicemailNumber(accountHandle, number); @@ -658,14 +651,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder ContactPhotoManager.getInstance(mContext).loadThumbnail(quickContactView, info.photoId, false /* darkTheme */, true /* isCircular */, request); } - - if (mExtendedBlockingButtonRenderer != null) { - mExtendedBlockingButtonRenderer.updatePhotoAndLabelIfNecessary( - number, - countryIso, - quickContactView, - phoneCallDetailsViews.callLocationAndDate); - } } @Override @@ -686,6 +671,14 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder view in dialog. */ numberType, /* phone number type (e.g. mobile) in second line of contact view */ accountHandle); + } else if (view.getId() == R.id.block_report_action) { + mBlockReportListener.onBlockReportSpam(number, countryIso, displayNumber); + } else if (view.getId() == R.id.block_action) { + mBlockReportListener.onBlock(number, countryIso, displayNumber); + } else if (view.getId() == R.id.unblock_action) { + mBlockReportListener.onUnblock(number, countryIso, blockId, displayNumber); + } else if (view.getId() == R.id.report_not_spam_action) { + mBlockReportListener.onReportNotSpam(number, countryIso, displayNumber); } else { final IntentProvider intentProvider = (IntentProvider) view.getTag(); if (intentProvider != null) { @@ -729,4 +722,24 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder viewHolder.workIconView = new ImageButton(context); return viewHolder; } + + private void updateBlockReportActions() { + // Set block/spam actions. + blockReportView.setVisibility(View.GONE); + blockView.setVisibility(View.GONE); + unblockView.setVisibility(View.GONE); + reportNotSpamView.setVisibility(View.GONE); + boolean isBlocked = blockId != null; + if (isBlocked) { + unblockView.setVisibility(View.VISIBLE); + } else { + if (isSpam) { + blockView.setVisibility(View.VISIBLE); + reportNotSpamView.setVisibility(View.VISIBLE); + } else { + blockReportView.setVisibility(View.VISIBLE); + } + } + + } } \ No newline at end of file diff --git a/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java b/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java index 7b149e24e..ff1a44ff7 100644 --- a/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java +++ b/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java @@ -316,6 +316,11 @@ public class PhoneCallDetailsHelper { /** Sets the call count, date, and if it is a voicemail, sets the duration. */ private void setDetailText(PhoneCallDetailsViews views, Integer callCount, PhoneCallDetails details) { + if (details.isSpam) { + views.callLocationAndDate.setText( + mContext.getString(R.string.spam_number_call_log_label)); + return; + } // Combine the count (if present) and the date. CharSequence dateText = getCallLocationAndDate(details); final CharSequence text; @@ -333,7 +338,6 @@ public class PhoneCallDetailsHelper { } else { views.callLocationAndDate.setText(text); } - } private String getVoicemailDuration(PhoneCallDetails details) { diff --git a/src/com/android/dialer/service/ExtendedCallInfoService.java b/src/com/android/dialer/service/ExtendedCallInfoService.java index 33a85f485..412cece74 100644 --- a/src/com/android/dialer/service/ExtendedCallInfoService.java +++ b/src/com/android/dialer/service/ExtendedCallInfoService.java @@ -35,7 +35,22 @@ public interface ExtendedCallInfoService { /** * Gets extended call information. * @param number The phone number of the call. + * @param countryIso The country ISO of the call. * @param listener The callback to be invoked after {@code Info} is fetched. */ - void getExtendedCallInfo(String number, Listener listener); + void getExtendedCallInfo(String number, String countryIso, Listener listener); + + /** + * Reports number as spam. + * @param number The number to be reported. + * @param countryIso The country ISO of the number. + */ + void reportSpam(String number, String countryIso); + + /** + * Reports number as not spam. + * @param number The number to be reported. + * @param countryIso The country ISO of the number. + */ + void reportNotSpam(String number, String countryIso); } -- cgit v1.2.3