diff options
Diffstat (limited to 'java/com/android/dialer')
18 files changed, 470 insertions, 249 deletions
diff --git a/java/com/android/dialer/app/calllog/BlockReportSpamListener.java b/java/com/android/dialer/app/calllog/BlockReportSpamListener.java index ecf629e14..5c7641c80 100644 --- a/java/com/android/dialer/app/calllog/BlockReportSpamListener.java +++ b/java/com/android/dialer/app/calllog/BlockReportSpamListener.java @@ -20,6 +20,7 @@ import android.app.FragmentManager; import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; +import android.view.View; import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.blockreportspam.BlockReportSpamDialogs; import com.android.dialer.blockreportspam.BlockReportSpamDialogs.DialogFragmentForReportingNotSpam; @@ -31,26 +32,32 @@ import com.android.dialer.logging.Logger; import com.android.dialer.logging.ReportingLocation; import com.android.dialer.spam.Spam; import com.android.dialer.spam.SpamComponent; +import com.android.dialer.spam.promo.SpamBlockingPromoHelper; /** Listener to show dialogs for block and report spam actions. */ public class BlockReportSpamListener implements CallLogListItemViewHolder.OnClickListener { private final Context context; + private final View rootView; private final FragmentManager fragmentManager; private final RecyclerView.Adapter adapter; private final FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler; private final Spam spam; + private final SpamBlockingPromoHelper spamBlockingPromoHelper; public BlockReportSpamListener( Context context, + View rootView, FragmentManager fragmentManager, RecyclerView.Adapter adapter, FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler) { this.context = context; + this.rootView = rootView; this.fragmentManager = fragmentManager; this.adapter = adapter; this.filteredNumberAsyncQueryHandler = filteredNumberAsyncQueryHandler; spam = SpamComponent.get(context).spam(); + spamBlockingPromoHelper = new SpamBlockingPromoHelper(context, spam); } @Override @@ -85,6 +92,10 @@ public class BlockReportSpamListener implements CallLogListItemViewHolder.OnClic }, number, countryIso); + + if (isSpamChecked) { + spamBlockingPromoHelper.showSpamBlockingPromoDialog(rootView, fragmentManager); + } }, null) .show(fragmentManager, BlockReportSpamDialogs.BLOCK_REPORT_SPAM_DIALOG_TAG); @@ -122,6 +133,8 @@ public class BlockReportSpamListener implements CallLogListItemViewHolder.OnClic }, number, countryIso); + + spamBlockingPromoHelper.showSpamBlockingPromoDialog(rootView, fragmentManager); }, null) .show(fragmentManager, BlockReportSpamDialogs.BLOCK_DIALOG_TAG); diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java index 7f8c889de..376057ff5 100644 --- a/java/com/android/dialer/app/calllog/CallLogAdapter.java +++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java @@ -564,6 +564,7 @@ public class CallLogAdapter extends GroupingListAdapter blockReportSpamListener = new BlockReportSpamListener( this.activity, + this.activity.findViewById(R.id.call_log_fragment_root), ((Activity) this.activity).getFragmentManager(), this, this.filteredNumberAsyncQueryHandler); diff --git a/java/com/android/dialer/app/res/layout/call_log_fragment.xml b/java/com/android/dialer/app/res/layout/call_log_fragment.xml index efc08fbb4..f0563967c 100644 --- a/java/com/android/dialer/app/res/layout/call_log_fragment.xml +++ b/java/com/android/dialer/app/res/layout/call_log_fragment.xml @@ -16,6 +16,7 @@ <!-- Layout parameters are set programmatically. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/call_log_fragment_root" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> diff --git a/java/com/android/dialer/calllog/model/CoalescedRow.java b/java/com/android/dialer/calllog/model/CoalescedRow.java deleted file mode 100644 index 737e736d6..000000000 --- a/java/com/android/dialer/calllog/model/CoalescedRow.java +++ /dev/null @@ -1,134 +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.calllog.model; - -import android.support.annotation.ColorInt; -import android.support.annotation.Nullable; -import com.android.dialer.CoalescedIds; -import com.android.dialer.DialerPhoneNumber; -import com.android.dialer.NumberAttributes; -import com.google.auto.value.AutoValue; - -/** Data class containing the contents of a row from the CoalescedAnnotatedCallLog. */ -@AutoValue -public abstract class CoalescedRow { - - public static Builder builder() { - return new AutoValue_CoalescedRow.Builder() - .setId(0) - .setTimestamp(0) - .setNumber(DialerPhoneNumber.getDefaultInstance()) - .setNumberPresentation(0) - .setIsRead(false) - .setIsNew(false) - .setPhoneAccountColor(0) - .setFeatures(0) - .setCallType(0) - .setNumberAttributes(NumberAttributes.getDefaultInstance()) - .setIsVoicemailCall(false) - .setCoalescedIds(CoalescedIds.getDefaultInstance()); - } - - public abstract Builder toBuilder(); - - public abstract int id(); - - public abstract long timestamp(); - - public abstract DialerPhoneNumber number(); - - @Nullable - public abstract String formattedNumber(); - - public abstract int numberPresentation(); - - public abstract boolean isRead(); - - public abstract boolean isNew(); - - @Nullable - public abstract String geocodedLocation(); - - @Nullable - public abstract String phoneAccountComponentName(); - - @Nullable - public abstract String phoneAccountId(); - - @Nullable - public abstract String phoneAccountLabel(); - - @ColorInt - public abstract int phoneAccountColor(); - - public abstract int features(); - - public abstract int callType(); - - public abstract NumberAttributes numberAttributes(); - - public abstract boolean isVoicemailCall(); - - @Nullable - public abstract String voicemailCallTag(); - - public abstract CoalescedIds coalescedIds(); - - /** Builder for {@link CoalescedRow}. */ - @AutoValue.Builder - public abstract static class Builder { - - public abstract Builder setId(int id); - - public abstract Builder setTimestamp(long timestamp); - - public abstract Builder setNumber(DialerPhoneNumber number); - - public abstract Builder setFormattedNumber(@Nullable String formattedNumber); - - public abstract Builder setNumberPresentation(int presentation); - - public abstract Builder setIsRead(boolean isRead); - - public abstract Builder setIsNew(boolean isNew); - - public abstract Builder setGeocodedLocation(@Nullable String geocodedLocation); - - public abstract Builder setPhoneAccountComponentName( - @Nullable String phoneAccountComponentName); - - public abstract Builder setPhoneAccountId(@Nullable String phoneAccountId); - - public abstract Builder setPhoneAccountLabel(@Nullable String phoneAccountLabel); - - public abstract Builder setPhoneAccountColor(@ColorInt int phoneAccountColor); - - public abstract Builder setFeatures(int features); - - public abstract Builder setCallType(int callType); - - public abstract Builder setNumberAttributes(NumberAttributes numberAttributes); - - public abstract Builder setIsVoicemailCall(boolean isVoicemail); - - public abstract Builder setVoicemailCallTag(@Nullable String tag); - - public abstract Builder setCoalescedIds(CoalescedIds coalescedIds); - - public abstract CoalescedRow build(); - } -} diff --git a/java/com/android/dialer/calllog/model/coalesced_row.proto b/java/com/android/dialer/calllog/model/coalesced_row.proto new file mode 100644 index 000000000..3cb10e7a6 --- /dev/null +++ b/java/com/android/dialer/calllog/model/coalesced_row.proto @@ -0,0 +1,70 @@ +syntax = "proto2"; + +option java_package = "com.android.dialer.calllog.model"; +option java_multiple_files = true; +option optimize_for = LITE_RUNTIME; + + +package com.android.dialer.calllog.model; + +import "java/com/android/dialer/calllog/database/contract/coalesced_ids.proto"; +import "java/com/android/dialer/calllog/database/contract/number_attributes.proto"; +import "java/com/android/dialer/phonenumberproto/dialer_phone_number.proto"; + +// Contains the contents of a row from the CoalescedAnnotatedCallLog. +// Next ID: 19 +message CoalescedRow { + // Value in column CoalescedAnnotatedCallLog._ID + optional int64 id = 1; + + // Value in column CoalescedAnnotatedCallLog.TIMESTAMP + optional int64 timestamp = 2; + + // Value in column CoalescedAnnotatedCallLog.NUMBER + optional com.android.dialer.DialerPhoneNumber number = 3; + + // Value in column CoalescedAnnotatedCallLog.FORMATTED_NUMBER + optional string formatted_number = 4; + + // Value in column CoalescedAnnotatedCallLog.NUMBER_PRESENTATION + optional int32 number_presentation = 5; + + // Value in column CoalescedAnnotatedCallLog.IS_READ + optional bool is_read = 6; + + // Value in column CoalescedAnnotatedCallLog.NEW + optional bool is_new = 7; + + // Value in column CoalescedAnnotatedCallLog.GEOCODED_LOCATION + optional string geocoded_location = 8; + + // Value in column CoalescedAnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME + optional string phone_account_component_name = 9; + + // Value in column CoalescedAnnotatedCallLog.PHONE_ACCOUNT_ID + optional string phone_account_id = 10; + + // Value in column CoalescedAnnotatedCallLog.PHONE_ACCOUNT_LABEL + optional string phone_account_label = 11; + + // Value in column CoalescedAnnotatedCallLog.PHONE_ACCOUNT_COLOR + optional int32 phone_account_color = 12; + + // Value in column CoalescedAnnotatedCallLog.FEATURES + optional int32 features = 13; + + // Value in column CoalescedAnnotatedCallLog.CALL_TYPE + optional int32 call_type = 14; + + // Value in column CoalescedAnnotatedCallLog.NUMBER_ATTRIBUTES + optional com.android.dialer.NumberAttributes number_attributes = 15; + + // Value in column CoalescedAnnotatedCallLog.IS_VOICEMAIL_CALL + optional bool is_voicemail_call = 16; + + // Value in column CoalescedAnnotatedCallLog.VOICEMAIL_CALL_TAG + optional string voicemail_call_tag = 17; + + // Value in column CoalescedAnnotatedCallLog.COALESCED_IDS + optional com.android.dialer.CoalescedIds coalesced_ids = 18; +} diff --git a/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java index a5cfd3f59..e2ddcc846 100644 --- a/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java +++ b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java @@ -19,6 +19,7 @@ package com.android.dialer.calllog.ui; import android.content.Context; import android.database.Cursor; import android.support.v4.content.CursorLoader; +import android.text.TextUtils; import com.android.dialer.CoalescedIds; import com.android.dialer.DialerPhoneNumber; import com.android.dialer.NumberAttributes; @@ -84,26 +85,53 @@ final class CoalescedAnnotatedCallLogCursorLoader extends CursorLoader { throw new IllegalStateException("Couldn't parse NumberAttributes bytes"); } - return CoalescedRow.builder() - .setId(cursor.getInt(ID)) - .setTimestamp(cursor.getLong(TIMESTAMP)) - .setNumber(number) - .setFormattedNumber(cursor.getString(FORMATTED_NUMBER)) - .setNumberPresentation(cursor.getInt(NUMBER_PRESENTATION)) - .setIsRead(cursor.getInt(IS_READ) == 1) - .setIsNew(cursor.getInt(NEW) == 1) - .setGeocodedLocation(cursor.getString(GEOCODED_LOCATION)) - .setPhoneAccountComponentName(cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME)) - .setPhoneAccountId(cursor.getString(PHONE_ACCOUNT_ID)) - .setPhoneAccountLabel(cursor.getString(PHONE_ACCOUNT_LABEL)) - .setPhoneAccountColor(cursor.getInt(PHONE_ACCOUNT_COLOR)) - .setFeatures(cursor.getInt(FEATURES)) - .setCallType(cursor.getInt(CALL_TYPE)) - .setNumberAttributes(numberAttributes) - .setIsVoicemailCall(cursor.getInt(IS_VOICEMAIL_CALL) == 1) - .setVoicemailCallTag(cursor.getString(VOICEMAIL_CALL_TAG)) - .setCoalescedIds(coalescedIds) - .build(); + CoalescedRow.Builder coalescedRowBuilder = + CoalescedRow.newBuilder() + .setId(cursor.getLong(ID)) + .setTimestamp(cursor.getLong(TIMESTAMP)) + .setNumber(number) + .setNumberPresentation(cursor.getInt(NUMBER_PRESENTATION)) + .setIsRead(cursor.getInt(IS_READ) == 1) + .setIsNew(cursor.getInt(NEW) == 1) + .setPhoneAccountColor(cursor.getInt(PHONE_ACCOUNT_COLOR)) + .setFeatures(cursor.getInt(FEATURES)) + .setCallType(cursor.getInt(CALL_TYPE)) + .setNumberAttributes(numberAttributes) + .setIsVoicemailCall(cursor.getInt(IS_VOICEMAIL_CALL) == 1) + .setCoalescedIds(coalescedIds); + + String formattedNumber = cursor.getString(FORMATTED_NUMBER); + if (!TextUtils.isEmpty(formattedNumber)) { + coalescedRowBuilder.setFormattedNumber(formattedNumber); + } + + String geocodedLocation = cursor.getString(GEOCODED_LOCATION); + if (!TextUtils.isEmpty(geocodedLocation)) { + coalescedRowBuilder.setGeocodedLocation(geocodedLocation); + } + + String phoneAccountComponentName = cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME); + if (!TextUtils.isEmpty(phoneAccountComponentName)) { + coalescedRowBuilder.setPhoneAccountComponentName( + cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME)); + } + + String phoneAccountId = cursor.getString(PHONE_ACCOUNT_ID); + if (!TextUtils.isEmpty(phoneAccountId)) { + coalescedRowBuilder.setPhoneAccountId(phoneAccountId); + } + + String phoneAccountLabel = cursor.getString(PHONE_ACCOUNT_LABEL); + if (!TextUtils.isEmpty(phoneAccountLabel)) { + coalescedRowBuilder.setPhoneAccountLabel(phoneAccountLabel); + } + + String voicemailCallTag = cursor.getString(VOICEMAIL_CALL_TAG); + if (!TextUtils.isEmpty(voicemailCallTag)) { + coalescedRowBuilder.setVoicemailCallTag(voicemailCallTag); + } + + return coalescedRowBuilder.build(); } static long getTimestamp(Cursor cursor) { diff --git a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java index 74be21b0c..713ca4405 100644 --- a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java +++ b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java @@ -36,7 +36,6 @@ import com.android.dialer.common.concurrent.DialerExecutorComponent; import com.android.dialer.compat.AppCompatConstants; import com.android.dialer.compat.telephony.TelephonyManagerCompat; import com.android.dialer.glidephotomanager.GlidePhotoManager; -import com.android.dialer.glidephotomanager.PhotoInfo; import com.android.dialer.oem.MotorolaUtils; import com.android.dialer.time.Clock; import com.google.common.util.concurrent.FutureCallback; @@ -65,7 +64,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { private final GlidePhotoManager glidePhotoManager; - private int currentRowId; + private long currentRowId; NewCallLogViewHolder( View view, @@ -94,7 +93,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { /** @param cursor a cursor from {@link CoalescedAnnotatedCallLogCursorLoader}. */ void bind(Cursor cursor) { CoalescedRow row = CoalescedAnnotatedCallLogCursorLoader.toRow(cursor); - currentRowId = row.id(); // Used to make sure async updates are applied to the correct views + currentRowId = row.getId(); // Used to make sure async updates are applied to the correct views // Even if there is additional real time processing necessary, we still want to immediately show // what information we have, rather than an empty card. For example, if CP2 information needs to @@ -136,7 +135,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { } private void setNumberCalls(CoalescedRow row) { - int numberCalls = row.coalescedIds().getCoalescedIdCount(); + int numberCalls = row.getCoalescedIds().getCoalescedIdCount(); if (numberCalls > 1) { callCountTextView.setText(String.format(Locale.getDefault(), "(%d)", numberCalls)); callCountTextView.setVisibility(View.VISIBLE); @@ -148,18 +147,16 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { private boolean isNewMissedCall(CoalescedRow row) { // Show missed call styling if the most recent call in the group was missed and it is still // marked as NEW. It is not clear what IS_READ should be used for and it is currently not used. - return row.callType() == Calls.MISSED_TYPE && row.isNew(); + return row.getCallType() == Calls.MISSED_TYPE && row.getIsNew(); } private void setPhoto(CoalescedRow row) { - PhotoInfo.Builder photoInfoBuilder = - NumberAttributesConverter.toPhotoInfoBuilder(row.numberAttributes()) - .setIsVoicemail(row.isVoicemailCall()); - if (!TextUtils.isEmpty(row.formattedNumber())) { - photoInfoBuilder.setFormattedNumber(row.formattedNumber()); - } - - glidePhotoManager.loadQuickContactBadge(quickContactBadge, photoInfoBuilder.build()); + glidePhotoManager.loadQuickContactBadge( + quickContactBadge, + NumberAttributesConverter.toPhotoInfoBuilder(row.getNumberAttributes()) + .setFormattedNumber(row.getFormattedNumber()) + .setIsVoicemail(row.getIsVoicemailCall()) + .build()); } private void setFeatureIcons(CoalescedRow row) { @@ -171,7 +168,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { : R.color.feature_icon_read_color)); // Handle HD Icon - if ((row.features() & Calls.FEATURES_HD_CALL) == Calls.FEATURES_HD_CALL) { + if ((row.getFeatures() & Calls.FEATURES_HD_CALL) == Calls.FEATURES_HD_CALL) { hdIcon.setVisibility(View.VISIBLE); hdIcon.setImageTintList(colorStateList); } else { @@ -179,7 +176,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { } // Handle Wifi Icon - if (MotorolaUtils.shouldShowWifiIconInCallLog(context, row.features())) { + if (MotorolaUtils.shouldShowWifiIconInCallLog(context, row.getFeatures())) { wifiIcon.setVisibility(View.VISIBLE); wifiIcon.setImageTintList(colorStateList); } else { @@ -187,7 +184,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { } // Handle Assisted Dialing Icon - if ((row.features() & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING) + if ((row.getFeatures() & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING) == TelephonyManagerCompat.FEATURES_ASSISTED_DIALING) { assistedDialIcon.setVisibility(View.VISIBLE); assistedDialIcon.setImageTintList(colorStateList); @@ -198,7 +195,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { private void setCallTypeIcon(CoalescedRow row) { @DrawableRes int resId; - switch (row.callType()) { + switch (row.getCallType()) { case AppCompatConstants.CALLS_INCOMING_TYPE: case AppCompatConstants.CALLS_ANSWERED_EXTERNALLY_TYPE: resId = R.drawable.quantum_ic_call_received_vd_theme_24; @@ -234,9 +231,9 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { } private void setPhoneAccounts(CoalescedRow row) { - if (row.phoneAccountLabel() != null) { - phoneAccountView.setText(row.phoneAccountLabel()); - phoneAccountView.setTextColor(row.phoneAccountColor()); + if (!TextUtils.isEmpty(row.getPhoneAccountLabel())) { + phoneAccountView.setText(row.getPhoneAccountLabel()); + phoneAccountView.setTextColor(row.getPhoneAccountColor()); phoneAccountView.setVisibility(View.VISIBLE); } else { phoneAccountView.setVisibility(View.GONE); @@ -269,7 +266,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder { public void onSuccess(CoalescedRow updatedRow) { // If the user scrolled then this ViewHolder may not correspond to the completed task and // there's nothing to do. - if (originalRow.id() != currentRowId) { + if (originalRow.getId() != currentRowId) { return; } // Only update the UI if the updated row differs from the original row (which has already diff --git a/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java b/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java index b7cb6d727..b955e029b 100644 --- a/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java +++ b/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java @@ -97,22 +97,22 @@ public final class RealtimeRowProcessor { @MainThread ListenableFuture<CoalescedRow> applyRealtimeProcessing(final CoalescedRow row) { // Cp2DefaultDirectoryPhoneLookup can not always efficiently process all rows. - if (!row.numberAttributes().getIsCp2InfoIncomplete()) { + if (!row.getNumberAttributes().getIsCp2InfoIncomplete()) { return Futures.immediateFuture(row); } - PhoneLookupInfo cachedPhoneLookupInfo = cache.get(row.number()); + PhoneLookupInfo cachedPhoneLookupInfo = cache.get(row.getNumber()); if (cachedPhoneLookupInfo != null) { return Futures.immediateFuture(applyPhoneLookupInfoToRow(cachedPhoneLookupInfo, row)); } ListenableFuture<PhoneLookupInfo> phoneLookupInfoFuture = - compositePhoneLookup.lookup(row.number()); + compositePhoneLookup.lookup(row.getNumber()); return Futures.transform( phoneLookupInfoFuture, phoneLookupInfo -> { - queuePhoneLookupHistoryWrite(row.number(), phoneLookupInfo); - cache.put(row.number(), phoneLookupInfo); + queuePhoneLookupHistoryWrite(row.getNumber(), phoneLookupInfo); + cache.put(row.getNumber(), phoneLookupInfo); return applyPhoneLookupInfoToRow(phoneLookupInfo, row); }, uiExecutor /* ensures the cache is updated on a single thread */); diff --git a/java/com/android/dialer/calllog/ui/menu/Modules.java b/java/com/android/dialer/calllog/ui/menu/Modules.java index 69b42e304..aeb69a7a8 100644 --- a/java/com/android/dialer/calllog/ui/menu/Modules.java +++ b/java/com/android/dialer/calllog/ui/menu/Modules.java @@ -51,15 +51,15 @@ final class Modules { // Conditionally add each module, which are items in the bottom sheet's menu. List<HistoryItemActionModule> modules = new ArrayList<>(); - String normalizedNumber = row.number().getNormalizedNumber(); + String normalizedNumber = row.getNumber().getNormalizedNumber(); boolean canPlaceCalls = - PhoneNumberHelper.canPlaceCallsTo(normalizedNumber, row.numberPresentation()); + PhoneNumberHelper.canPlaceCallsTo(normalizedNumber, row.getNumberPresentation()); if (canPlaceCalls) { modules.addAll(createModulesForCalls(context, row, normalizedNumber)); Optional<HistoryItemActionModule> moduleForSendingTextMessage = SharedModules.createModuleForSendingTextMessage( - context, normalizedNumber, row.numberAttributes().getIsBlocked()); + context, normalizedNumber, row.getNumberAttributes().getIsBlocked()); if (moduleForSendingTextMessage.isPresent()) { modules.add(moduleForSendingTextMessage.get()); } @@ -76,29 +76,29 @@ final class Modules { Optional<HistoryItemActionModule> moduleForAddingToContacts = SharedModules.createModuleForAddingToContacts( context, - row.number(), - row.numberAttributes().getName(), - row.numberAttributes().getLookupUri(), - row.numberAttributes().getIsBlocked(), - row.numberAttributes().getIsSpam()); + row.getNumber(), + row.getNumberAttributes().getName(), + row.getNumberAttributes().getLookupUri(), + row.getNumberAttributes().getIsBlocked(), + row.getNumberAttributes().getIsSpam()); if (moduleForAddingToContacts.isPresent()) { modules.add(moduleForAddingToContacts.get()); } BlockReportSpamDialogInfo blockReportSpamDialogInfo = BlockReportSpamDialogInfo.newBuilder() - .setNormalizedNumber(row.number().getNormalizedNumber()) - .setCountryIso(row.number().getCountryIso()) - .setCallType(row.callType()) + .setNormalizedNumber(row.getNumber().getNormalizedNumber()) + .setCountryIso(row.getNumber().getCountryIso()) + .setCallType(row.getCallType()) .setReportingLocation(ReportingLocation.Type.CALL_LOG_HISTORY) - .setContactSource(row.numberAttributes().getContactSource()) + .setContactSource(row.getNumberAttributes().getContactSource()) .build(); modules.addAll( SharedModules.createModulesHandlingBlockedOrSpamNumber( context, blockReportSpamDialogInfo, - row.numberAttributes().getIsBlocked(), - row.numberAttributes().getIsSpam())); + row.getNumberAttributes().getIsBlocked(), + row.getNumberAttributes().getIsSpam())); Optional<HistoryItemActionModule> moduleForCopyingNumber = SharedModules.createModuleForCopyingNumber(context, normalizedNumber); @@ -109,7 +109,7 @@ final class Modules { modules.add(createModuleForAccessingCallDetails(context, row)); - modules.add(new DeleteCallLogItemModule(context, row.coalescedIds())); + modules.add(new DeleteCallLogItemModule(context, row.getCoalescedIds())); return modules; } @@ -117,14 +117,14 @@ final class Modules { private static List<HistoryItemActionModule> createModulesForCalls( Context context, CoalescedRow row, String normalizedNumber) { // Don't add call options if a number is blocked. - if (row.numberAttributes().getIsBlocked()) { + if (row.getNumberAttributes().getIsBlocked()) { return Collections.emptyList(); } List<HistoryItemActionModule> modules = new ArrayList<>(); PhoneAccountHandle phoneAccountHandle = TelecomUtil.composePhoneAccountHandle( - row.phoneAccountComponentName(), row.phoneAccountId()); + row.getPhoneAccountComponentName(), row.getPhoneAccountId()); // Add an audio call item modules.add( @@ -132,8 +132,8 @@ final class Modules { context, normalizedNumber, phoneAccountHandle, CallInitiationType.Type.CALL_LOG)); // Add a video item if (1) the call log entry is for a video call, and (2) the call is not spam. - if ((row.features() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO - && !row.numberAttributes().getIsSpam()) { + if ((row.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO + && !row.getNumberAttributes().getIsSpam()) { modules.add( IntentModule.newVideoCallModule( context, normalizedNumber, phoneAccountHandle, CallInitiationType.Type.CALL_LOG)); @@ -147,14 +147,15 @@ final class Modules { private static HistoryItemActionModule createModuleForAccessingCallDetails( Context context, CoalescedRow row) { - boolean canReportAsInvalidNumber = row.numberAttributes().getCanReportAsInvalidNumber(); - boolean canSupportAssistedDialing = !TextUtils.isEmpty(row.numberAttributes().getLookupUri()); + boolean canReportAsInvalidNumber = row.getNumberAttributes().getCanReportAsInvalidNumber(); + boolean canSupportAssistedDialing = + !TextUtils.isEmpty(row.getNumberAttributes().getLookupUri()); return new IntentModule( context, CallDetailsActivity.newInstance( context, - row.coalescedIds(), + row.getCoalescedIds(), createCallDetailsHeaderInfoFromRow(context, row), canReportAsInvalidNumber, canSupportAssistedDialing), @@ -165,7 +166,7 @@ final class Modules { private static CallDetailsHeaderInfo createCallDetailsHeaderInfoFromRow( Context context, CoalescedRow row) { return CallDetailsHeaderInfo.newBuilder() - .setDialerPhoneNumber(row.number()) + .setDialerPhoneNumber(row.getNumber()) .setPhotoInfo(createPhotoInfoFromRow(row)) .setPrimaryText(CallLogEntryText.buildPrimaryText(context, row).toString()) .setSecondaryText( @@ -174,13 +175,10 @@ final class Modules { } private static PhotoInfo createPhotoInfoFromRow(CoalescedRow row) { - PhotoInfo.Builder photoInfoBuilder = - NumberAttributesConverter.toPhotoInfoBuilder(row.numberAttributes()) - .setIsVideo((row.features() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) - .setIsVoicemail(row.isVoicemailCall()); - if (!TextUtils.isEmpty(row.formattedNumber())) { - photoInfoBuilder.setFormattedNumber(row.formattedNumber()); - } - return photoInfoBuilder.build(); + return NumberAttributesConverter.toPhotoInfoBuilder(row.getNumberAttributes()) + .setFormattedNumber(row.getFormattedNumber()) + .setIsVideo((row.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) + .setIsVoicemail(row.getIsVoicemailCall()) + .build(); } } diff --git a/java/com/android/dialer/calllog/ui/menu/NewCallLogMenu.java b/java/com/android/dialer/calllog/ui/menu/NewCallLogMenu.java index 9efe907e3..5be19ce0c 100644 --- a/java/com/android/dialer/calllog/ui/menu/NewCallLogMenu.java +++ b/java/com/android/dialer/calllog/ui/menu/NewCallLogMenu.java @@ -42,11 +42,11 @@ public final class NewCallLogMenu { // If the user opens the bottom sheet for a new call, clear the notifications and make the row // not bold immediately. To do this, mark all of the calls in group as not new. - if (row.isNew() && row.callType() == Calls.MISSED_TYPE) { + if (row.getIsNew() && row.getCallType() == Calls.MISSED_TYPE) { Futures.addCallback( CallLogComponent.get(context) .getClearMissedCalls() - .clearBySystemCallLogId(row.coalescedIds().getCoalescedIdList()), + .clearBySystemCallLogId(row.getCoalescedIds().getCoalescedIdList()), new DefaultFutureCallback<>(), MoreExecutors.directExecutor()); } diff --git a/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java b/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java index aec4dc6d8..279869d70 100644 --- a/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java +++ b/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java @@ -18,12 +18,10 @@ package com.android.dialer.calllog.ui.menu; import android.content.Context; import android.provider.CallLog.Calls; -import android.text.TextUtils; import com.android.dialer.calllog.model.CoalescedRow; import com.android.dialer.calllogutils.CallLogEntryText; import com.android.dialer.calllogutils.CallLogIntents; import com.android.dialer.calllogutils.NumberAttributesConverter; -import com.android.dialer.glidephotomanager.PhotoInfo; import com.android.dialer.historyitemactions.HistoryItemPrimaryActionInfo; /** Configures the primary action row (top row) for the bottom sheet. */ @@ -32,16 +30,13 @@ final class PrimaryAction { static HistoryItemPrimaryActionInfo fromRow(Context context, CoalescedRow row) { CharSequence primaryText = CallLogEntryText.buildPrimaryText(context, row); - PhotoInfo.Builder photoInfoBuilder = - NumberAttributesConverter.toPhotoInfoBuilder(row.numberAttributes()) - .setIsVideo((row.features() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO); - if (!TextUtils.isEmpty(row.formattedNumber())) { - photoInfoBuilder.setFormattedNumber(row.formattedNumber()); - } - return HistoryItemPrimaryActionInfo.builder() - .setNumber(row.number()) - .setPhotoInfo(photoInfoBuilder.build()) + .setNumber(row.getNumber()) + .setPhotoInfo( + NumberAttributesConverter.toPhotoInfoBuilder(row.getNumberAttributes()) + .setFormattedNumber(row.getFormattedNumber()) + .setIsVideo((row.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) + .build()) .setPrimaryText(primaryText) .setSecondaryText(CallLogEntryText.buildSecondaryTextForBottomSheet(context, row)) .setIntent(CallLogIntents.getCallBackIntent(context, row)) diff --git a/java/com/android/dialer/calllogutils/CallLogEntryText.java b/java/com/android/dialer/calllogutils/CallLogEntryText.java index 6f1047cb7..c77869169 100644 --- a/java/com/android/dialer/calllogutils/CallLogEntryText.java +++ b/java/com/android/dialer/calllogutils/CallLogEntryText.java @@ -43,23 +43,23 @@ public final class CallLogEntryText { public static CharSequence buildPrimaryText(Context context, CoalescedRow row) { // Always prefer the presentation name, like "Restricted". Optional<String> presentationName = - PhoneNumberDisplayUtil.getNameForPresentation(context, row.numberPresentation()); + PhoneNumberDisplayUtil.getNameForPresentation(context, row.getNumberPresentation()); if (presentationName.isPresent()) { return presentationName.get(); } - if (row.isVoicemailCall() && !TextUtils.isEmpty(row.voicemailCallTag())) { - return row.voicemailCallTag(); + if (row.getIsVoicemailCall() && !TextUtils.isEmpty(row.getVoicemailCallTag())) { + return row.getVoicemailCallTag(); } // Otherwise prefer the name. - if (!TextUtils.isEmpty(row.numberAttributes().getName())) { - return row.numberAttributes().getName(); + if (!TextUtils.isEmpty(row.getNumberAttributes().getName())) { + return row.getNumberAttributes().getName(); } // Otherwise prefer the formatted number. - if (!TextUtils.isEmpty(row.formattedNumber())) { - return row.formattedNumber(); + if (!TextUtils.isEmpty(row.getFormattedNumber())) { + return row.getFormattedNumber(); } // If there's no formatted number, just return "Unknown". @@ -99,17 +99,18 @@ public final class CallLogEntryText { Context context, Clock clock, CoalescedRow row) { List<CharSequence> components = new ArrayList<>(); - if (row.numberAttributes().getIsBlocked()) { + if (row.getNumberAttributes().getIsBlocked()) { components.add(context.getText(R.string.new_call_log_secondary_blocked)); } - if (row.numberAttributes().getIsSpam()) { + if (row.getNumberAttributes().getIsSpam()) { components.add(context.getText(R.string.new_call_log_secondary_spam)); } components.add(getNumberTypeLabel(context, row)); components.add( - CallLogDates.newCallLogTimestampLabel(context, clock.currentTimeMillis(), row.timestamp())); + CallLogDates.newCallLogTimestampLabel( + context, clock.currentTimeMillis(), row.getTimestamp())); return joinSecondaryTextComponents(components); } @@ -147,10 +148,10 @@ public final class CallLogEntryText { */ List<CharSequence> components = new ArrayList<>(); - if (row.numberAttributes().getIsBlocked()) { + if (row.getNumberAttributes().getIsBlocked()) { components.add(context.getText(R.string.new_call_log_secondary_blocked)); } - if (row.numberAttributes().getIsSpam()) { + if (row.getNumberAttributes().getIsSpam()) { components.add(context.getText(R.string.new_call_log_secondary_spam)); } @@ -159,20 +160,20 @@ public final class CallLogEntryText { // If there's a presentation name, we showed it in the primary text and shouldn't show any name // or number here. Optional<String> presentationName = - PhoneNumberDisplayUtil.getNameForPresentation(context, row.numberPresentation()); + PhoneNumberDisplayUtil.getNameForPresentation(context, row.getNumberPresentation()); if (presentationName.isPresent()) { return joinSecondaryTextComponents(components); } - if (TextUtils.isEmpty(row.numberAttributes().getName())) { + if (TextUtils.isEmpty(row.getNumberAttributes().getName())) { // If the name is empty the number is shown as the primary text and there's nothing to add. return joinSecondaryTextComponents(components); } - if (TextUtils.isEmpty(row.formattedNumber())) { + if (TextUtils.isEmpty(row.getFormattedNumber())) { // If there's no number, don't append anything. return joinSecondaryTextComponents(components); } - components.add(row.formattedNumber()); + components.add(row.getFormattedNumber()); return joinSecondaryTextComponents(components); } @@ -186,19 +187,19 @@ public final class CallLogEntryText { */ private static CharSequence getNumberTypeLabel(Context context, CoalescedRow row) { StringBuilder secondaryText = new StringBuilder(); - if ((row.features() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) { + if ((row.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) { // TODO(zachh): Add "Duo" prefix? secondaryText.append(context.getText(R.string.new_call_log_video)); } - String numberTypeLabel = row.numberAttributes().getNumberTypeLabel(); + String numberTypeLabel = row.getNumberAttributes().getNumberTypeLabel(); if (!TextUtils.isEmpty(numberTypeLabel)) { if (secondaryText.length() > 0) { secondaryText.append(", "); } secondaryText.append(numberTypeLabel); - } else if (!row.numberAttributes().getIsSpam()) { + } else if (!row.getNumberAttributes().getIsSpam()) { // Don't show the location if there's a number type label or the number is spam. - String location = row.geocodedLocation(); + String location = row.getGeocodedLocation(); if (!TextUtils.isEmpty(location)) { if (secondaryText.length() > 0) { secondaryText.append(", "); diff --git a/java/com/android/dialer/calllogutils/CallLogIntents.java b/java/com/android/dialer/calllogutils/CallLogIntents.java index 64fb33d13..18927f77d 100644 --- a/java/com/android/dialer/calllogutils/CallLogIntents.java +++ b/java/com/android/dialer/calllogutils/CallLogIntents.java @@ -39,8 +39,8 @@ public final class CallLogIntents { */ @Nullable public static Intent getCallBackIntent(Context context, CoalescedRow row) { - String normalizedNumber = row.number().getNormalizedNumber(); - if (!PhoneNumberHelper.canPlaceCallsTo(normalizedNumber, row.numberPresentation())) { + String normalizedNumber = row.getNumber().getNormalizedNumber(); + if (!PhoneNumberHelper.canPlaceCallsTo(normalizedNumber, row.getNumberPresentation())) { return null; } @@ -50,7 +50,7 @@ public final class CallLogIntents { new CallIntentBuilder(normalizedNumber, CallInitiationType.Type.CALL_LOG) .setPhoneAccountHandle( TelecomUtil.composePhoneAccountHandle( - row.phoneAccountComponentName(), row.phoneAccountId())) - .setIsVideoCall((row.features() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO)); + row.getPhoneAccountComponentName(), row.getPhoneAccountId())) + .setIsVideoCall((row.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO)); } } diff --git a/java/com/android/dialer/logging/dialer_impression.proto b/java/com/android/dialer/logging/dialer_impression.proto index 96ca9c6be..16efd137c 100644 --- a/java/com/android/dialer/logging/dialer_impression.proto +++ b/java/com/android/dialer/logging/dialer_impression.proto @@ -12,7 +12,7 @@ message DialerImpression { // Event enums to be used for Impression Logging in Dialer. // It's perfectly acceptable for this enum to be large // Values should be from 1000 to 100000. - // Next Tag: 1366 + // Next Tag: 1369 enum Type { UNKNOWN_AOSP_EVENT_TYPE = 1000; @@ -719,5 +719,12 @@ message DialerImpression { VVM_USER_TURNED_TRANSCRIBE_OFF_FROM_SETTINGS = 1363; VVM_USER_TURNED_DONATION_ON_FROM_SETTINGS = 1364; VVM_USER_TURNED_DONATION_OFF_FROM_SETTINGS = 1365; + + // Spam blocking call log promo shown for user. + SPAM_BLOCKING_CALL_LOG_PROMO_SHOWN = 1366; + // User enabled spam blocking through call log promo. + SPAM_BLOCKING_ENABLED_THROUGH_CALL_LOG_PROMO = 1367; + // Failure happened while enabling spam blocking through call log promo. + SPAM_BLOCKING_MODIFY_FAILURE_THROUGH_CALL_LOG_PROMO = 1368; } } diff --git a/java/com/android/dialer/spam/promo/AndroidManifest.xml b/java/com/android/dialer/spam/promo/AndroidManifest.xml new file mode 100644 index 000000000..7d766b853 --- /dev/null +++ b/java/com/android/dialer/spam/promo/AndroidManifest.xml @@ -0,0 +1,19 @@ +<!-- + ~ 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 + --> + +<manifest + package="com.android.dialer.spam.promo"> +</manifest> diff --git a/java/com/android/dialer/spam/promo/SpamBlockingPromoDialogFragment.java b/java/com/android/dialer/spam/promo/SpamBlockingPromoDialogFragment.java new file mode 100644 index 000000000..0ea17d395 --- /dev/null +++ b/java/com/android/dialer/spam/promo/SpamBlockingPromoDialogFragment.java @@ -0,0 +1,69 @@ +/* + * 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.spam.promo; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.os.Bundle; + +/** Dialog for spam blocking on-boarding promotion. */ +public class SpamBlockingPromoDialogFragment extends DialogFragment { + + public static final String SPAM_BLOCKING_PROMO_DIALOG_TAG = "SpamBlockingPromoDialog"; + + /** Called when dialog positive button is pressed. */ + protected OnEnableListener positiveListener; + + public static DialogFragment newInstance(OnEnableListener positiveListener) { + SpamBlockingPromoDialogFragment fragment = new SpamBlockingPromoDialogFragment(); + fragment.positiveListener = positiveListener; + return fragment; + } + + @Override + public void onPause() { + // The dialog is dismissed onPause, i.e. rotation. + dismiss(); + super.onPause(); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + super.onCreateDialog(savedInstanceState); + // Return the newly created dialog + return new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme) + .setCancelable(true) + .setTitle(R.string.spam_blocking_promo_title) + .setMessage(R.string.spam_blocking_promo_text) + .setNegativeButton( + R.string.spam_blocking_promo_action_dismiss, (dialog, which) -> dismiss()) + .setPositiveButton( + R.string.spam_blocking_promo_action_filter_spam, + (dialog, which) -> { + dismiss(); + positiveListener.onClick(); + }) + .create(); + } + + /** Positive listener for spam blocking promotion dialog. */ + public interface OnEnableListener { + /** Called when user clicks on positive button in the spam blocking promo dialog. */ + void onClick(); + } +} diff --git a/java/com/android/dialer/spam/promo/SpamBlockingPromoHelper.java b/java/com/android/dialer/spam/promo/SpamBlockingPromoHelper.java new file mode 100644 index 000000000..9349577c5 --- /dev/null +++ b/java/com/android/dialer/spam/promo/SpamBlockingPromoHelper.java @@ -0,0 +1,117 @@ +/* + * 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.spam.promo; + +import android.app.FragmentManager; +import android.content.Context; +import android.preference.PreferenceManager; +import android.support.annotation.VisibleForTesting; +import android.support.design.widget.Snackbar; +import android.view.View; +import com.android.dialer.configprovider.ConfigProviderBindings; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; +import com.android.dialer.spam.Spam; + +/** Helper class for showing spam blocking on-boarding promotions. */ +public class SpamBlockingPromoHelper { + + static final String SPAM_BLOCKING_PROMO_PERIOD_MILLIS = "spam_blocking_promo_period_millis"; + static final String SPAM_BLOCKING_PROMO_LAST_SHOW_MILLIS = "spam_blocking_promo_last_show_millis"; + + private final Context context; + private final Spam spam; + + public SpamBlockingPromoHelper(Context context, Spam spam) { + this.context = context; + this.spam = spam; + } + + /** Shows a spam blocking promo dialog with on complete snackbar if all the prerequisites meet. */ + public void showSpamBlockingPromoDialog(View view, FragmentManager fragmentManager) { + if (!shouldShowSpamBlockingPromo()) { + return; + } + + updateLastShowSpamTimestamp(); + Logger.get(context).logImpression(DialerImpression.Type.SPAM_BLOCKING_CALL_LOG_PROMO_SHOWN); + SpamBlockingPromoDialogFragment.newInstance( + () -> { + Logger.get(context) + .logImpression( + DialerImpression.Type.SPAM_BLOCKING_ENABLED_THROUGH_CALL_LOG_PROMO); + spam.modifySpamBlockingSetting( + true, success -> showModifySettingOnCompleteSnackbar(view, success)); + }) + .show(fragmentManager, SpamBlockingPromoDialogFragment.SPAM_BLOCKING_PROMO_DIALOG_TAG); + } + + /** + * Returns true if we should show a spam blocking promo. + * + * <p>Should show spam blocking promo only when all of the following criteria meet 1. Spam + * blocking setting is available. 2. Spam blocking setting is not yet enabled. 3. Time since last + * spam blocking promo exceeds the threshold. + * + * @return true if we should show a spam blocking promo. + */ + @VisibleForTesting + boolean shouldShowSpamBlockingPromo() { + if (!spam.isSpamEnabled() || !spam.isSpamBlockingAvailable() || spam.isSpamBlockingEnabled()) { + return false; + } + + long lastShowMillis = + PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()) + .getLong(SPAM_BLOCKING_PROMO_LAST_SHOW_MILLIS, 0); + long showPeriodMillis = + ConfigProviderBindings.get(context) + .getLong(SPAM_BLOCKING_PROMO_PERIOD_MILLIS, Long.MAX_VALUE); + return lastShowMillis == 0 || System.currentTimeMillis() - lastShowMillis > showPeriodMillis; + } + + private void updateLastShowSpamTimestamp() { + PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()) + .edit() + .putLong(SPAM_BLOCKING_PROMO_LAST_SHOW_MILLIS, System.currentTimeMillis()) + .commit(); + } + + /** + * Shows a modify setting on complete snackbar and a link to redirect to setting page + * + * @param view the view to attach on-complete notice snackbar + * @param success whether the modify setting operation succceeds + */ + private void showModifySettingOnCompleteSnackbar(View view, boolean success) { + if (!success) { + Logger.get(context) + .logImpression(DialerImpression.Type.SPAM_BLOCKING_MODIFY_FAILURE_THROUGH_CALL_LOG_PROMO); + } + String snackBarText = + success + ? context.getString(R.string.spam_blocking_settings_enable_complete_text) + : context.getString(R.string.spam_blocking_settings_enable_error_text); + Snackbar.make(view, snackBarText, Snackbar.LENGTH_LONG) + .setAction( + R.string.spam_blocking_setting_prompt, + v -> context.startActivity(spam.getSpamBlockingSettingIntent(context))) + .setActionTextColor( + context.getResources().getColor(R.color.dialer_snackbar_action_text_color)) + .show(); + } +} diff --git a/java/com/android/dialer/spam/promo/res/values/strings.xml b/java/com/android/dialer/spam/promo/res/values/strings.xml new file mode 100644 index 000000000..bef73812c --- /dev/null +++ b/java/com/android/dialer/spam/promo/res/values/strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> + +<resources> + <!-- Title for the spam blocking promo dialog. [CHAR LIMIT=100] --> + <string name="spam_blocking_promo_title">Filter suspected spam calls?</string> + <!-- Text for the spam blocking promo dialog. [CHAR LIMIT=100] --> + <string name="spam_blocking_promo_text">Filtered spam calls will go straight to your voicemail</string> + <!-- Label for filter spam dialog action. [CHAR LIMIT=32] --> + <string name="spam_blocking_promo_action_filter_spam">Filter Spam</string> + <!-- Label for "Dismiss" dialog action. [CHAR LIMIT=32] --> + <string name="spam_blocking_promo_action_dismiss">Dismiss</string> + <!-- Button text to prompt a user to open spam blocking setting [CHAR LIMIT=NONE] --> + <string name="spam_blocking_setting_prompt">Settings</string> + + <!-- Spam blocking error text, shown when error happens during setting enabling. --> + <string name="spam_blocking_settings_enable_error_text">Problem turning on spam filtering</string> + <!-- Spam blocking error text, shown when error happens during setting disabling. --> + <string name="spam_blocking_settings_disable_error_text">Problem turning off spam filtering</string> + + <!-- On complete text shown when spam blocking is enabled successfully. --> + <string name="spam_blocking_settings_enable_complete_text">Spam filtering turned on</string> + <!-- On complete text shown when spam blocking is disabled successfully. --> + <string name="spam_blocking_settings_disable_complete_text">Spam filtering turned off</string> +</resources> |