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