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