diff options
4 files changed, 195 insertions, 19 deletions
diff --git a/java/com/android/dialer/calllog/ui/menu/DeleteCallLogItemModule.java b/java/com/android/dialer/calllog/ui/menu/DeleteCallLogItemModule.java index ad5671e45..a929961d6 100644 --- a/java/com/android/dialer/calllog/ui/menu/DeleteCallLogItemModule.java +++ b/java/com/android/dialer/calllog/ui/menu/DeleteCallLogItemModule.java @@ -29,18 +29,20 @@ import com.android.dialer.common.concurrent.DialerExecutor.Worker; import com.android.dialer.common.concurrent.DialerExecutorComponent; import com.android.dialer.common.database.Selection; import com.android.dialer.historyitemactions.HistoryItemActionModule; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; /** {@link HistoryItemActionModule} for deleting a call log item in the new call log. */ -public final class DeleteCallLogItemModule implements HistoryItemActionModule { +final class DeleteCallLogItemModule implements HistoryItemActionModule { private static final String TAG = DeleteCallLogItemModule.class.getName(); private final Context context; private final CoalescedIds coalescedIds; - public DeleteCallLogItemModule(Context context, CoalescedIds coalescedIds) { + DeleteCallLogItemModule(Context context, CoalescedIds coalescedIds) { this.context = context; this.coalescedIds = coalescedIds; } @@ -62,6 +64,8 @@ public final class DeleteCallLogItemModule implements HistoryItemActionModule { .createNonUiTaskBuilder(new CallLogItemDeletionWorker(context)) .build() .executeSerial(coalescedIds); + + Logger.get(context).logImpression(DialerImpression.Type.USER_DELETED_CALL_LOG_ITEM); return true; } diff --git a/java/com/android/dialer/historyitemactions/BlockReportSpamModules.java b/java/com/android/dialer/historyitemactions/BlockReportSpamModules.java index 396c03376..c47b097b7 100644 --- a/java/com/android/dialer/historyitemactions/BlockReportSpamModules.java +++ b/java/com/android/dialer/historyitemactions/BlockReportSpamModules.java @@ -19,6 +19,9 @@ package com.android.dialer.historyitemactions; import android.content.Context; import com.android.dialer.blockreportspam.BlockReportSpamDialogInfo; import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogNotifier; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; +import java.util.Optional; /** Modules for blocking/unblocking a number and/or reporting it as spam/not spam. */ final class BlockReportSpamModules { @@ -26,7 +29,9 @@ final class BlockReportSpamModules { private BlockReportSpamModules() {} static HistoryItemActionModule moduleForMarkingNumberAsNotSpam( - Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) { + Context context, + BlockReportSpamDialogInfo blockReportSpamDialogInfo, + Optional<DialerImpression.Type> impression) { return new HistoryItemActionModule() { @Override @@ -43,13 +48,17 @@ final class BlockReportSpamModules { public boolean onClick() { ShowBlockReportSpamDialogNotifier.notifyShowDialogToReportNotSpam( context, blockReportSpamDialogInfo); + + impression.ifPresent(Logger.get(context)::logImpression); return true; // Close the bottom sheet. } }; } static HistoryItemActionModule moduleForBlockingNumber( - Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) { + Context context, + BlockReportSpamDialogInfo blockReportSpamDialogInfo, + Optional<DialerImpression.Type> impression) { return new HistoryItemActionModule() { @Override @@ -66,13 +75,17 @@ final class BlockReportSpamModules { public boolean onClick() { ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumber( context, blockReportSpamDialogInfo); + + impression.ifPresent(Logger.get(context)::logImpression); return true; // Close the bottom sheet. } }; } static HistoryItemActionModule moduleForUnblockingNumber( - Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) { + Context context, + BlockReportSpamDialogInfo blockReportSpamDialogInfo, + Optional<DialerImpression.Type> impression) { return new HistoryItemActionModule() { @Override @@ -90,13 +103,16 @@ final class BlockReportSpamModules { ShowBlockReportSpamDialogNotifier.notifyShowDialogToUnblockNumber( context, blockReportSpamDialogInfo); + impression.ifPresent(Logger.get(context)::logImpression); return true; // Close the bottom sheet. } }; } static HistoryItemActionModule moduleForBlockingNumberAndOptionallyReportingSpam( - Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) { + Context context, + BlockReportSpamDialogInfo blockReportSpamDialogInfo, + Optional<DialerImpression.Type> impression) { return new HistoryItemActionModule() { @Override @@ -113,6 +129,8 @@ final class BlockReportSpamModules { public boolean onClick() { ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumberAndOptionallyReportSpam( context, blockReportSpamDialogInfo); + + impression.ifPresent(Logger.get(context)::logImpression); return true; // Close the bottom sheet. } }; diff --git a/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java b/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java index 0e78d70f5..917aa953d 100644 --- a/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java +++ b/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.net.Uri; import android.provider.CallLog.Calls; import android.provider.ContactsContract; +import android.support.annotation.IntDef; import android.text.TextUtils; import com.android.dialer.blockreportspam.BlockReportSpamDialogInfo; import com.android.dialer.callintent.CallInitiationType; @@ -29,13 +30,19 @@ 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.DialerImpression; import com.android.dialer.logging.ReportingLocation; import com.android.dialer.spam.Spam; import com.android.dialer.util.CallUtil; import com.android.dialer.util.PermissionsUtil; import com.android.dialer.util.UriUtils; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.Optional; /** * Builds a list of {@link HistoryItemActionModule HistoryItemActionModules}. @@ -76,6 +83,54 @@ import java.util.List; */ public final class HistoryItemActionModulesBuilder { + /** Represents events when a module is tapped by the user. */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + Event.ADD_TO_CONTACT, + Event.BLOCK_NUMBER, + Event.BLOCK_NUMBER_AND_REPORT_SPAM, + Event.REPORT_NOT_SPAM, + Event.REQUEST_CARRIER_VIDEO_CALL, + Event.REQUEST_DUO_VIDEO_CALL, + Event.REQUEST_DUO_VIDEO_CALL_FOR_NON_CONTACT, + Event.SEND_TEXT_MESSAGE, + Event.UNBLOCK_NUMBER + }) + @interface Event { + int ADD_TO_CONTACT = 1; + int BLOCK_NUMBER = 2; + int BLOCK_NUMBER_AND_REPORT_SPAM = 3; + int REPORT_NOT_SPAM = 4; + int REQUEST_CARRIER_VIDEO_CALL = 5; + int REQUEST_DUO_VIDEO_CALL = 6; + int REQUEST_DUO_VIDEO_CALL_FOR_NON_CONTACT = 7; + int SEND_TEXT_MESSAGE = 8; + int UNBLOCK_NUMBER = 9; + } + + /** + * Maps each {@link Event} to a {@link DialerImpression.Type} to be logged when the modules are + * hosted by the call log. + */ + private static final ImmutableMap<Integer, DialerImpression.Type> CALL_LOG_IMPRESSIONS = + new ImmutableMap.Builder<Integer, DialerImpression.Type>() + .put(Event.ADD_TO_CONTACT, DialerImpression.Type.ADD_TO_A_CONTACT_FROM_CALL_LOG) + .put(Event.BLOCK_NUMBER, DialerImpression.Type.CALL_LOG_BLOCK_NUMBER) + .put(Event.BLOCK_NUMBER_AND_REPORT_SPAM, DialerImpression.Type.CALL_LOG_BLOCK_REPORT_SPAM) + .put(Event.REPORT_NOT_SPAM, DialerImpression.Type.CALL_LOG_REPORT_AS_NOT_SPAM) + .put( + Event.REQUEST_CARRIER_VIDEO_CALL, + DialerImpression.Type.IMS_VIDEO_REQUESTED_FROM_CALL_LOG) + .put( + Event.REQUEST_DUO_VIDEO_CALL, + DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FROM_CALL_LOG) + .put( + Event.REQUEST_DUO_VIDEO_CALL_FOR_NON_CONTACT, + DialerImpression.Type.LIGHTBRINGER_NON_CONTACT_VIDEO_REQUESTED_FROM_CALL_LOG) + .put(Event.SEND_TEXT_MESSAGE, DialerImpression.Type.CALL_LOG_SEND_MESSAGE) + .put(Event.UNBLOCK_NUMBER, DialerImpression.Type.CALL_LOG_UNBLOCK_NUMBER) + .build(); + private final Context context; private final HistoryItemActionModuleInfo moduleInfo; private final List<HistoryItemActionModule> modules; @@ -158,7 +213,14 @@ public final class HistoryItemActionModulesBuilder { // 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(IntentModule.newCallModule(context, callIntentBuilder.setIsDuoCall(isDuoCall()))); + boolean isDuoCall = isDuoCall(); + modules.add( + IntentModule.newCallModule( + context, + callIntentBuilder.setIsDuoCall(isDuoCall), + isDuoCall + ? getImpressionsForDuoVideoCall() + : getImpressions(Event.REQUEST_CARRIER_VIDEO_CALL))); return this; } @@ -167,14 +229,29 @@ public final class HistoryItemActionModulesBuilder { // // The carrier video call module takes precedence over the Duo module. if (canPlaceCarrierVideoCall()) { - modules.add(IntentModule.newCallModule(context, callIntentBuilder)); + modules.add( + IntentModule.newCallModule( + context, callIntentBuilder, getImpressions(Event.REQUEST_CARRIER_VIDEO_CALL))); } else if (canPlaceDuoCall()) { - modules.add(IntentModule.newCallModule(context, callIntentBuilder.setIsDuoCall(true))); + modules.add( + IntentModule.newCallModule( + context, callIntentBuilder.setIsDuoCall(true), getImpressionsForDuoVideoCall())); } return this; } /** + * Returns a list of impressions to be logged when the user taps the module that attempts to + * initiate a Duo video call. + */ + private ImmutableList<DialerImpression.Type> getImpressionsForDuoVideoCall() { + return isExistingContact() + ? getImpressions(Event.REQUEST_DUO_VIDEO_CALL) + : getImpressions( + Event.REQUEST_DUO_VIDEO_CALL, Event.REQUEST_DUO_VIDEO_CALL_FOR_NON_CONTACT); + } + + /** * Adds a module for sending text messages. * * <p>The method is a no-op if @@ -199,7 +276,8 @@ public final class HistoryItemActionModulesBuilder { } modules.add( - IntentModule.newModuleForSendingTextMessage(context, moduleInfo.getNormalizedNumber())); + IntentModule.newModuleForSendingTextMessage( + context, moduleInfo.getNormalizedNumber(), getImpressions(Event.SEND_TEXT_MESSAGE))); return this; } @@ -256,7 +334,8 @@ public final class HistoryItemActionModulesBuilder { context, intent, R.string.add_to_contacts, - R.drawable.quantum_ic_person_add_vd_theme_24)); + R.drawable.quantum_ic_person_add_vd_theme_24, + getImpressions(Event.ADD_TO_CONTACT))); return this; } @@ -302,11 +381,13 @@ public final class HistoryItemActionModulesBuilder { if (Spam.shouldShowAsSpam(moduleInfo.getIsSpam(), moduleInfo.getCallType())) { modules.add( BlockReportSpamModules.moduleForMarkingNumberAsNotSpam( - context, blockReportSpamDialogInfo)); + context, blockReportSpamDialogInfo, getImpression(Event.REPORT_NOT_SPAM))); modules.add( moduleInfo.getIsBlocked() - ? BlockReportSpamModules.moduleForUnblockingNumber(context, blockReportSpamDialogInfo) - : BlockReportSpamModules.moduleForBlockingNumber(context, blockReportSpamDialogInfo)); + ? BlockReportSpamModules.moduleForUnblockingNumber( + context, blockReportSpamDialogInfo, getImpression(Event.UNBLOCK_NUMBER)) + : BlockReportSpamModules.moduleForBlockingNumber( + context, blockReportSpamDialogInfo, getImpression(Event.BLOCK_NUMBER))); return this; } @@ -314,7 +395,8 @@ public final class HistoryItemActionModulesBuilder { // "Unblock" module. if (moduleInfo.getIsBlocked()) { modules.add( - BlockReportSpamModules.moduleForUnblockingNumber(context, blockReportSpamDialogInfo)); + BlockReportSpamModules.moduleForUnblockingNumber( + context, blockReportSpamDialogInfo, getImpression(Event.UNBLOCK_NUMBER))); return this; } @@ -322,7 +404,7 @@ public final class HistoryItemActionModulesBuilder { // spam, add the "Block/Report spam" module. modules.add( BlockReportSpamModules.moduleForBlockingNumberAndOptionallyReportingSpam( - context, blockReportSpamDialogInfo)); + context, blockReportSpamDialogInfo, getImpression(Event.BLOCK_NUMBER_AND_REPORT_SPAM))); return this; } @@ -437,4 +519,34 @@ public final class HistoryItemActionModulesBuilder { String.format("Unsupported host: %s", moduleInfo.getHost())); } } + + /** Returns a list of impressions to be logged for the given {@link Event events}. */ + private ImmutableList<DialerImpression.Type> getImpressions(@Event int... events) { + Assert.isNotNull(events); + + ImmutableList.Builder<DialerImpression.Type> impressionListBuilder = + new ImmutableList.Builder<>(); + for (@Event int event : events) { + getImpression(event).ifPresent(impressionListBuilder::add); + } + + return impressionListBuilder.build(); + } + + /** + * Returns an impression to be logged for the given {@link Event}, or {@link Optional#empty()} if + * no impression is available for the event. + */ + private Optional<DialerImpression.Type> getImpression(@Event int event) { + switch (moduleInfo.getHost()) { + case CALL_LOG: + return Optional.of(CALL_LOG_IMPRESSIONS.get(event)); + case VOICEMAIL: + // TODO(a bug): Return proper impressions for voicemail. + return Optional.empty(); + 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 dc53064af..f4fc678fd 100644 --- a/java/com/android/dialer/historyitemactions/IntentModule.java +++ b/java/com/android/dialer/historyitemactions/IntentModule.java @@ -21,9 +21,12 @@ import android.content.Intent; import android.support.annotation.DrawableRes; import android.support.annotation.StringRes; import com.android.dialer.callintent.CallIntentBuilder; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; import com.android.dialer.precall.PreCall; import com.android.dialer.util.DialerUtils; import com.android.dialer.util.IntentUtil; +import com.google.common.collect.ImmutableList; /** * {@link HistoryItemActionModule} useful for making easy to build modules based on starting an @@ -35,12 +38,28 @@ public class IntentModule implements HistoryItemActionModule { private final Intent intent; private final @StringRes int text; private final @DrawableRes int image; + private final ImmutableList<DialerImpression.Type> impressions; + /** + * @deprecated use {@link IntentModule#IntentModule(Context, Intent, int, int, ImmutableList)} + * instead. + */ + @Deprecated public IntentModule(Context context, Intent intent, @StringRes int text, @DrawableRes int image) { + this(context, intent, text, image, /* impressions = */ ImmutableList.of()); + } + + IntentModule( + Context context, + Intent intent, + @StringRes int text, + @DrawableRes int image, + ImmutableList<DialerImpression.Type> impressions) { this.context = context; this.intent = intent; this.text = text; this.image = image; + this.impressions = impressions; } @Override @@ -56,11 +75,21 @@ public class IntentModule implements HistoryItemActionModule { @Override public boolean onClick() { DialerUtils.startActivityWithErrorToast(context, intent); + impressions.forEach(Logger.get(context)::logImpression); return true; } - /** Creates a module for starting an outgoing call with a {@link CallIntentBuilder}. */ + /** @deprecated Use {@link #newCallModule(Context, CallIntentBuilder, ImmutableList)} instead. */ + @Deprecated public static IntentModule newCallModule(Context context, CallIntentBuilder callIntentBuilder) { + return newCallModule(context, callIntentBuilder, /* impressions = */ ImmutableList.of()); + } + + /** Creates a module for starting an outgoing call with a {@link CallIntentBuilder}. */ + static IntentModule newCallModule( + Context context, + CallIntentBuilder callIntentBuilder, + ImmutableList<DialerImpression.Type> impressions) { @StringRes int text; @DrawableRes int image; @@ -72,14 +101,27 @@ public class IntentModule implements HistoryItemActionModule { image = R.drawable.quantum_ic_call_white_24; } - return new IntentModule(context, PreCall.getIntent(context, callIntentBuilder), text, image); + return new IntentModule( + context, PreCall.getIntent(context, callIntentBuilder), text, image, impressions); } + /** + * @deprecated Use {@link #newModuleForSendingTextMessage(Context, String, ImmutableList)} + * instead. + */ + @Deprecated public static IntentModule newModuleForSendingTextMessage(Context context, String number) { + return newModuleForSendingTextMessage(context, number, /* impressions = */ ImmutableList.of()); + } + + /** Creates a module for sending a text message to the given number. */ + static IntentModule newModuleForSendingTextMessage( + Context context, String number, ImmutableList<DialerImpression.Type> impressions) { return new IntentModule( context, IntentUtil.getSendSmsIntent(number), R.string.send_a_message, - R.drawable.quantum_ic_message_vd_theme_24); + R.drawable.quantum_ic_message_vd_theme_24, + impressions); } } |