1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dialer.spam.promo;
18 
19 import android.annotation.SuppressLint;
20 import android.app.Notification;
21 import android.app.Notification.Builder;
22 import android.app.PendingIntent;
23 import android.content.Context;
24 import android.content.DialogInterface.OnDismissListener;
25 import android.graphics.drawable.Icon;
26 import android.support.design.widget.Snackbar;
27 import android.support.v4.app.FragmentManager;
28 import android.support.v4.os.BuildCompat;
29 import android.view.View;
30 import android.widget.Toast;
31 import com.android.dialer.configprovider.ConfigProviderComponent;
32 import com.android.dialer.logging.DialerImpression;
33 import com.android.dialer.logging.Logger;
34 import com.android.dialer.notification.DialerNotificationManager;
35 import com.android.dialer.notification.NotificationChannelId;
36 import com.android.dialer.spam.SpamSettings;
37 import com.android.dialer.spam.promo.SpamBlockingPromoDialogFragment.OnEnableListener;
38 import com.android.dialer.storage.StorageComponent;
39 import com.android.dialer.theme.base.ThemeComponent;
40 
41 /** Helper class for showing spam blocking on-boarding promotions. */
42 public class SpamBlockingPromoHelper {
43 
44   static final String SPAM_BLOCKING_PROMO_PERIOD_MILLIS = "spam_blocking_promo_period_millis";
45   static final String SPAM_BLOCKING_PROMO_LAST_SHOW_MILLIS = "spam_blocking_promo_last_show_millis";
46   public static final String ENABLE_SPAM_BLOCKING_PROMO = "enable_spam_blocking_promo";
47   public static final String ENABLE_AFTER_CALL_SPAM_BLOCKING_PROMO =
48       "enable_after_call_spam_blocking_promo";
49 
50   private final Context context;
51   private final SpamSettings spamSettings;
52 
SpamBlockingPromoHelper(Context context, SpamSettings spamSettings)53   public SpamBlockingPromoHelper(Context context, SpamSettings spamSettings) {
54     this.context = context;
55     this.spamSettings = spamSettings;
56   }
57 
58   /**
59    * Returns true if we should show a spam blocking promo.
60    *
61    * <p>Should show spam blocking promo only when all of the following criteria meet 1. Spam
62    * blocking promo is enabled by flag. 2. Spam blocking setting is available. 3. Spam blocking
63    * setting is not yet enabled. 4. Time since last spam blocking promo exceeds the threshold.
64    *
65    * @return true if we should show a spam blocking promo.
66    */
shouldShowSpamBlockingPromo()67   public boolean shouldShowSpamBlockingPromo() {
68     if (!ConfigProviderComponent.get(context)
69             .getConfigProvider()
70             .getBoolean(ENABLE_SPAM_BLOCKING_PROMO, false)
71         || !spamSettings.isSpamEnabled()
72         || !spamSettings.isSpamBlockingEnabledByFlag()
73         || spamSettings.isSpamBlockingEnabledByUser()) {
74       return false;
75     }
76 
77     long lastShowMillis =
78         StorageComponent.get(context)
79             .unencryptedSharedPrefs()
80             .getLong(SPAM_BLOCKING_PROMO_LAST_SHOW_MILLIS, 0);
81     long showPeriodMillis =
82         ConfigProviderComponent.get(context)
83             .getConfigProvider()
84             .getLong(SPAM_BLOCKING_PROMO_PERIOD_MILLIS, Long.MAX_VALUE);
85     return lastShowMillis == 0 || System.currentTimeMillis() - lastShowMillis > showPeriodMillis;
86   }
87 
88   /* Returns true if we should show a spam blocking promo in after call notification scenario. */
shouldShowAfterCallSpamBlockingPromo()89   public boolean shouldShowAfterCallSpamBlockingPromo() {
90     return shouldShowSpamBlockingPromo()
91         && ConfigProviderComponent.get(context)
92             .getConfigProvider()
93             .getBoolean(ENABLE_AFTER_CALL_SPAM_BLOCKING_PROMO, false);
94   }
95 
96   /**
97    * Shows a spam blocking promo dialog.
98    *
99    * @param fragmentManager the fragment manager to show the dialog.
100    * @param onEnableListener the listener called when enable button is clicked.
101    * @param onDismissListener the listener called when the dialog is dismissed.
102    */
showSpamBlockingPromoDialog( FragmentManager fragmentManager, OnEnableListener onEnableListener, OnDismissListener onDismissListener)103   public void showSpamBlockingPromoDialog(
104       FragmentManager fragmentManager,
105       OnEnableListener onEnableListener,
106       OnDismissListener onDismissListener) {
107     updateLastShowSpamTimestamp();
108     SpamBlockingPromoDialogFragment.newInstance(onEnableListener, onDismissListener)
109         .show(fragmentManager, SpamBlockingPromoDialogFragment.SPAM_BLOCKING_PROMO_DIALOG_TAG);
110   }
111 
updateLastShowSpamTimestamp()112   private void updateLastShowSpamTimestamp() {
113     StorageComponent.get(context)
114         .unencryptedSharedPrefs()
115         .edit()
116         .putLong(SPAM_BLOCKING_PROMO_LAST_SHOW_MILLIS, System.currentTimeMillis())
117         .apply();
118   }
119 
120   /**
121    * Shows a modify setting on complete snackbar and a link to redirect to setting page.
122    *
123    * @param view the view to attach on-complete notice snackbar.
124    * @param success whether the modify setting operation succceeds.
125    */
showModifySettingOnCompleteSnackbar(View view, boolean success)126   public void showModifySettingOnCompleteSnackbar(View view, boolean success) {
127     String snackBarText =
128         success
129             ? context.getString(R.string.spam_blocking_settings_enable_complete_text)
130             : context.getString(R.string.spam_blocking_settings_enable_error_text);
131     Snackbar.make(view, snackBarText, Snackbar.LENGTH_LONG)
132         .setAction(
133             R.string.spam_blocking_setting_prompt,
134             v -> context.startActivity(spamSettings.getSpamBlockingSettingIntent(context)))
135         .setActionTextColor(
136             context.getResources().getColor(R.color.dialer_snackbar_action_text_color))
137         .show();
138   }
139 
140   /** Shows a modify setting on complete toast message. */
showModifySettingOnCompleteToast(boolean success)141   public void showModifySettingOnCompleteToast(boolean success) {
142     String toastText =
143         success
144             ? context.getString(R.string.spam_blocking_settings_enable_complete_text)
145             : context.getString(R.string.spam_blocking_settings_enable_error_text);
146     Toast.makeText(context, toastText, Toast.LENGTH_LONG).show();
147   }
148 
149   /**
150    * Shows a spam blocking promo notification.
151    *
152    * @param notificationTag a string identifier for this notification.
153    * @param notificationId an identifier for this notification.
154    * @param contentIntent pending intent to be sent when notification is clicked.
155    * @param actionIntent pending intent to be sent when enable-spam-blocking button is clicked.
156    */
showSpamBlockingPromoNotification( String notificationTag, int notificationId, PendingIntent contentIntent, PendingIntent actionIntent)157   public void showSpamBlockingPromoNotification(
158       String notificationTag,
159       int notificationId,
160       PendingIntent contentIntent,
161       PendingIntent actionIntent) {
162     updateLastShowSpamTimestamp();
163     Logger.get(context)
164         .logImpression(DialerImpression.Type.SPAM_BLOCKING_AFTER_CALL_NOTIFICATION_PROMO_SHOWN);
165     DialerNotificationManager.notify(
166         context,
167         notificationTag,
168         notificationId,
169         getSpamBlockingPromoNotification(contentIntent, actionIntent));
170   }
171 
172   /**
173    * Builds a spam blocking promo notification with given intents.
174    *
175    * @param contentIntent pending intent to be sent when notification is clicked.
176    * @param actionIntent pending intent to be sent when enable-spam-blocking button is clicked.
177    */
178   @SuppressLint("NewApi")
getSpamBlockingPromoNotification( PendingIntent contentIntent, PendingIntent actionIntent)179   private Notification getSpamBlockingPromoNotification(
180       PendingIntent contentIntent, PendingIntent actionIntent) {
181     Notification.Builder builder =
182         new Builder(context)
183             .setContentIntent(contentIntent)
184             .setCategory(Notification.CATEGORY_STATUS)
185             .setPriority(Notification.PRIORITY_DEFAULT)
186             .setColor(ThemeComponent.get(context).theme().getColorPrimary())
187             .setSmallIcon(R.drawable.quantum_ic_call_vd_theme_24)
188             .setLargeIcon(Icon.createWithResource(context, R.drawable.spam_blocking_promo_icon))
189             .setContentText(context.getString(R.string.spam_blocking_promo_text))
190             .setStyle(
191                 new Notification.BigTextStyle()
192                     .bigText(context.getString(R.string.spam_blocking_promo_text)))
193             .addAction(
194                 new Notification.Action.Builder(
195                         R.drawable.quantum_ic_block_vd_theme_24,
196                         context.getString(R.string.spam_blocking_promo_action_filter_spam),
197                         actionIntent)
198                     .build())
199             .setContentTitle(context.getString(R.string.spam_blocking_promo_title));
200 
201     if (BuildCompat.isAtLeastO()) {
202       builder.setChannelId(NotificationChannelId.DEFAULT);
203     }
204     return builder.build();
205   }
206 }
207 
208