• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.postcall;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.SharedPreferences;
23 import android.support.annotation.Nullable;
24 import android.support.design.widget.BaseTransientBottomBar.BaseCallback;
25 import android.support.design.widget.Snackbar;
26 import android.telephony.TelephonyManager;
27 import android.view.View;
28 import android.view.View.OnClickListener;
29 import com.android.dialer.common.Assert;
30 import com.android.dialer.common.LogUtil;
31 import com.android.dialer.configprovider.ConfigProvider;
32 import com.android.dialer.configprovider.ConfigProviderBindings;
33 import com.android.dialer.enrichedcall.EnrichedCallCapabilities;
34 import com.android.dialer.enrichedcall.EnrichedCallComponent;
35 import com.android.dialer.enrichedcall.EnrichedCallManager;
36 import com.android.dialer.logging.DialerImpression;
37 import com.android.dialer.logging.Logger;
38 import com.android.dialer.performancereport.PerformanceReport;
39 import com.android.dialer.storage.StorageComponent;
40 import com.android.dialer.util.DialerUtils;
41 import com.android.dialer.util.IntentUtil;
42 
43 /** Helper class to handle all post call actions. */
44 public class PostCall {
45 
46   private static final String KEY_POST_CALL_CALL_DISCONNECT_TIME = "post_call_call_disconnect_time";
47   private static final String KEY_POST_CALL_CALL_CONNECT_TIME = "post_call_call_connect_time";
48   private static final String KEY_POST_CALL_CALL_NUMBER = "post_call_call_number";
49   private static final String KEY_POST_CALL_MESSAGE_SENT = "post_call_message_sent";
50   private static final String KEY_POST_CALL_DISCONNECT_PRESSED = "post_call_disconnect_pressed";
51 
52   private static Snackbar activeSnackbar;
53 
promptUserForMessageIfNecessary(Activity activity, View rootView)54   public static void promptUserForMessageIfNecessary(Activity activity, View rootView) {
55     if (isEnabled(activity)) {
56       if (shouldPromptUserToViewSentMessage(activity)) {
57         promptUserToViewSentMessage(activity, rootView);
58       } else if (shouldPromptUserToSendMessage(activity)) {
59         promptUserToSendMessage(activity, rootView);
60       } else {
61         clear(activity);
62       }
63     }
64   }
65 
closePrompt()66   public static void closePrompt() {
67     if (activeSnackbar != null && activeSnackbar.isShown()) {
68       activeSnackbar.dismiss();
69       activeSnackbar = null;
70     }
71   }
72 
promptUserToSendMessage(Activity activity, View rootView)73   private static void promptUserToSendMessage(Activity activity, View rootView) {
74     LogUtil.i("PostCall.promptUserToSendMessage", "returned from call, showing post call SnackBar");
75     String message = activity.getString(R.string.post_call_message);
76     EnrichedCallManager manager = EnrichedCallComponent.get(activity).getEnrichedCallManager();
77     EnrichedCallCapabilities capabilities = manager.getCapabilities(getPhoneNumber(activity));
78     LogUtil.i(
79         "PostCall.promptUserToSendMessage",
80         "number: %s, capabilities: %s",
81         LogUtil.sanitizePhoneNumber(getPhoneNumber(activity)),
82         capabilities);
83 
84     boolean isRcsPostCall = capabilities != null && capabilities.isPostCallCapable();
85     String actionText =
86         isRcsPostCall
87             ? activity.getString(R.string.post_call_add_message)
88             : activity.getString(R.string.post_call_send_message);
89 
90     String number = Assert.isNotNull(getPhoneNumber(activity));
91     OnClickListener onClickListener =
92         v -> {
93           Logger.get(activity)
94               .logImpression(DialerImpression.Type.POST_CALL_PROMPT_USER_TO_SEND_MESSAGE_CLICKED);
95           activity.startActivity(PostCallActivity.newIntent(activity, number, isRcsPostCall));
96         };
97 
98     int durationMs =
99         (int) ConfigProviderBindings.get(activity).getLong("post_call_prompt_duration_ms", 8_000);
100     activeSnackbar =
101         Snackbar.make(rootView, message, durationMs)
102             .setAction(actionText, onClickListener)
103             .setActionTextColor(
104                 activity.getResources().getColor(R.color.dialer_snackbar_action_text_color));
105     activeSnackbar.show();
106     Logger.get(activity).logImpression(DialerImpression.Type.POST_CALL_PROMPT_USER_TO_SEND_MESSAGE);
107     StorageComponent.get(activity)
108         .unencryptedSharedPrefs()
109         .edit()
110         .remove(KEY_POST_CALL_CALL_DISCONNECT_TIME)
111         .apply();
112   }
113 
promptUserToViewSentMessage(Activity activity, View rootView)114   private static void promptUserToViewSentMessage(Activity activity, View rootView) {
115     LogUtil.i(
116         "PostCall.promptUserToViewSentMessage",
117         "returned from sending a post call message, message sent.");
118     String message = activity.getString(R.string.post_call_message_sent);
119     String addMessage = activity.getString(R.string.view);
120     String number = Assert.isNotNull(getPhoneNumber(activity));
121     OnClickListener onClickListener =
122         v -> {
123           Logger.get(activity)
124               .logImpression(
125                   DialerImpression.Type.POST_CALL_PROMPT_USER_TO_VIEW_SENT_MESSAGE_CLICKED);
126           Intent intent = IntentUtil.getSendSmsIntent(number);
127           DialerUtils.startActivityWithErrorToast(activity, intent);
128         };
129 
130     activeSnackbar =
131         Snackbar.make(rootView, message, Snackbar.LENGTH_LONG)
132             .setAction(addMessage, onClickListener)
133             .setActionTextColor(
134                 activity.getResources().getColor(R.color.dialer_snackbar_action_text_color))
135             .addCallback(
136                 new BaseCallback<Snackbar>() {
137                   @Override
138                   public void onDismissed(Snackbar snackbar, int i) {
139                     super.onDismissed(snackbar, i);
140                     clear(snackbar.getContext());
141                   }
142                 });
143     activeSnackbar.show();
144     Logger.get(activity)
145         .logImpression(DialerImpression.Type.POST_CALL_PROMPT_USER_TO_VIEW_SENT_MESSAGE);
146     StorageComponent.get(activity)
147         .unencryptedSharedPrefs()
148         .edit()
149         .remove(KEY_POST_CALL_MESSAGE_SENT)
150         .apply();
151   }
152 
onDisconnectPressed(Context context)153   public static void onDisconnectPressed(Context context) {
154     StorageComponent.get(context)
155         .unencryptedSharedPrefs()
156         .edit()
157         .putBoolean(KEY_POST_CALL_DISCONNECT_PRESSED, true)
158         .apply();
159   }
160 
onCallDisconnected(Context context, String number, long callConnectedMillis)161   public static void onCallDisconnected(Context context, String number, long callConnectedMillis) {
162     StorageComponent.get(context)
163         .unencryptedSharedPrefs()
164         .edit()
165         .putLong(KEY_POST_CALL_CALL_CONNECT_TIME, callConnectedMillis)
166         .putLong(KEY_POST_CALL_CALL_DISCONNECT_TIME, System.currentTimeMillis())
167         .putString(KEY_POST_CALL_CALL_NUMBER, number)
168         .apply();
169   }
170 
onMessageSent(Context context, String number)171   public static void onMessageSent(Context context, String number) {
172     StorageComponent.get(context)
173         .unencryptedSharedPrefs()
174         .edit()
175         .putString(KEY_POST_CALL_CALL_NUMBER, number)
176         .putBoolean(KEY_POST_CALL_MESSAGE_SENT, true)
177         .apply();
178   }
179 
180   /**
181    * Restart performance recording if there is a recent call (disconnect time to now is under
182    * threshold)
183    */
restartPerformanceRecordingIfARecentCallExist(Context context)184   public static void restartPerformanceRecordingIfARecentCallExist(Context context) {
185     long disconnectTimeMillis =
186         StorageComponent.get(context)
187             .unencryptedSharedPrefs()
188             .getLong(PostCall.KEY_POST_CALL_CALL_DISCONNECT_TIME, -1);
189     if (disconnectTimeMillis != -1 && PerformanceReport.isRecording()) {
190       PerformanceReport.startRecording();
191     }
192   }
193 
clear(Context context)194   private static void clear(Context context) {
195     activeSnackbar = null;
196 
197     StorageComponent.get(context)
198         .unencryptedSharedPrefs()
199         .edit()
200         .remove(KEY_POST_CALL_CALL_DISCONNECT_TIME)
201         .remove(KEY_POST_CALL_CALL_NUMBER)
202         .remove(KEY_POST_CALL_MESSAGE_SENT)
203         .remove(KEY_POST_CALL_CALL_CONNECT_TIME)
204         .remove(KEY_POST_CALL_DISCONNECT_PRESSED)
205         .apply();
206   }
207 
shouldPromptUserToSendMessage(Context context)208   private static boolean shouldPromptUserToSendMessage(Context context) {
209     SharedPreferences manager = StorageComponent.get(context).unencryptedSharedPrefs();
210     long disconnectTimeMillis = manager.getLong(KEY_POST_CALL_CALL_DISCONNECT_TIME, -1);
211     long connectTimeMillis = manager.getLong(KEY_POST_CALL_CALL_CONNECT_TIME, -1);
212 
213     long timeSinceDisconnect = System.currentTimeMillis() - disconnectTimeMillis;
214     long callDurationMillis = disconnectTimeMillis - connectTimeMillis;
215 
216     boolean callDisconnectedByUser = manager.getBoolean(KEY_POST_CALL_DISCONNECT_PRESSED, false);
217 
218     ConfigProvider binding = ConfigProviderBindings.get(context);
219     return disconnectTimeMillis != -1
220         && connectTimeMillis != -1
221         && isSimReady(context)
222         && binding.getLong("postcall_last_call_threshold", 30_000) > timeSinceDisconnect
223         && (connectTimeMillis == 0
224             || binding.getLong("postcall_call_duration_threshold", 35_000) > callDurationMillis)
225         && getPhoneNumber(context) != null
226         && callDisconnectedByUser;
227   }
228 
shouldPromptUserToViewSentMessage(Context context)229   private static boolean shouldPromptUserToViewSentMessage(Context context) {
230     return StorageComponent.get(context)
231         .unencryptedSharedPrefs()
232         .getBoolean(KEY_POST_CALL_MESSAGE_SENT, false);
233   }
234 
235   @Nullable
getPhoneNumber(Context context)236   private static String getPhoneNumber(Context context) {
237     return StorageComponent.get(context)
238         .unencryptedSharedPrefs()
239         .getString(KEY_POST_CALL_CALL_NUMBER, null);
240   }
241 
isEnabled(Context context)242   private static boolean isEnabled(Context context) {
243     return ConfigProviderBindings.get(context).getBoolean("enable_post_call_prod", true);
244   }
245 
isSimReady(Context context)246   private static boolean isSimReady(Context context) {
247     return context.getSystemService(TelephonyManager.class).getSimState()
248         == TelephonyManager.SIM_STATE_READY;
249   }
250 }
251