blob: 69ee376291644360b7afb8d7f45b1b3e742f27ee [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
* Copyright (C) 2020 The LineageOS 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.postcall;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.annotation.Nullable;
import android.support.design.widget.BaseTransientBottomBar.BaseCallback;
import android.support.design.widget.Snackbar;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.View.OnClickListener;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.configprovider.ConfigProvider;
import com.android.dialer.configprovider.ConfigProviderComponent;
import com.android.dialer.enrichedcall.EnrichedCallCapabilities;
import com.android.dialer.enrichedcall.EnrichedCallComponent;
import com.android.dialer.enrichedcall.EnrichedCallManager;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.performancereport.PerformanceReport;
import com.android.dialer.storage.StorageComponent;
import com.android.dialer.util.DialerUtils;
import com.android.dialer.util.IntentUtil;
import org.lineageos.lib.phone.SensitivePhoneNumbers;
/** Helper class to handle all post call actions. */
public class PostCall {
private static final String KEY_POST_CALL_CALL_DISCONNECT_TIME = "post_call_call_disconnect_time";
private static final String KEY_POST_CALL_CALL_CONNECT_TIME = "post_call_call_connect_time";
private static final String KEY_POST_CALL_CALL_NUMBER = "post_call_call_number";
private static final String KEY_POST_CALL_MESSAGE_SENT = "post_call_message_sent";
private static final String KEY_POST_CALL_DISCONNECT_PRESSED = "post_call_disconnect_pressed";
private static Snackbar activeSnackbar;
public static void promptUserForMessageIfNecessary(Activity activity, View rootView) {
if (isEnabled(activity)) {
if (shouldPromptUserToViewSentMessage(activity)) {
promptUserToViewSentMessage(activity, rootView);
} else if (shouldPromptUserToSendMessage(activity)) {
promptUserToSendMessage(activity, rootView);
} else {
clear(activity);
}
}
}
public static void closePrompt() {
if (activeSnackbar != null && activeSnackbar.isShown()) {
activeSnackbar.dismiss();
activeSnackbar = null;
}
}
private static void promptUserToSendMessage(Activity activity, View rootView) {
LogUtil.i("PostCall.promptUserToSendMessage", "returned from call, showing post call SnackBar");
String number = Assert.isNotNull(getPhoneNumber(activity));
String message = activity.getString(R.string.post_call_message);
EnrichedCallManager manager = EnrichedCallComponent.get(activity).getEnrichedCallManager();
EnrichedCallCapabilities capabilities = manager.getCapabilities(number);
LogUtil.i(
"PostCall.promptUserToSendMessage",
"number: %s, capabilities: %s",
LogUtil.sanitizePhoneNumber(number),
capabilities);
boolean isRcsPostCall = capabilities != null && capabilities.isPostCallCapable();
String actionText =
isRcsPostCall
? activity.getString(R.string.post_call_add_message)
: activity.getString(R.string.post_call_send_message);
OnClickListener onClickListener =
v -> {
Logger.get(activity)
.logImpression(DialerImpression.Type.POST_CALL_PROMPT_USER_TO_SEND_MESSAGE_CLICKED);
activity.startActivity(PostCallActivity.newIntent(activity, number, isRcsPostCall));
};
int durationMs =
(int)
ConfigProviderComponent.get(activity)
.getConfigProvider()
.getLong("post_call_prompt_duration_ms", 8_000);
activeSnackbar =
Snackbar.make(rootView, message, durationMs)
.setAction(actionText, onClickListener)
.setActionTextColor(
activity.getResources().getColor(R.color.dialer_snackbar_action_text_color));
activeSnackbar.show();
Logger.get(activity).logImpression(DialerImpression.Type.POST_CALL_PROMPT_USER_TO_SEND_MESSAGE);
StorageComponent.get(activity)
.unencryptedSharedPrefs()
.edit()
.remove(KEY_POST_CALL_CALL_DISCONNECT_TIME)
.apply();
}
private static void promptUserToViewSentMessage(Activity activity, View rootView) {
LogUtil.i(
"PostCall.promptUserToViewSentMessage",
"returned from sending a post call message, message sent.");
String message = activity.getString(R.string.post_call_message_sent);
String addMessage = activity.getString(R.string.view);
String number = Assert.isNotNull(getPhoneNumber(activity));
OnClickListener onClickListener =
v -> {
Logger.get(activity)
.logImpression(
DialerImpression.Type.POST_CALL_PROMPT_USER_TO_VIEW_SENT_MESSAGE_CLICKED);
Intent intent = IntentUtil.getSendSmsIntent(number);
DialerUtils.startActivityWithErrorToast(activity, intent);
};
activeSnackbar =
Snackbar.make(rootView, message, Snackbar.LENGTH_LONG)
.setAction(addMessage, onClickListener)
.setActionTextColor(
activity.getResources().getColor(R.color.dialer_snackbar_action_text_color))
.addCallback(
new BaseCallback<Snackbar>() {
@Override
public void onDismissed(Snackbar snackbar, int i) {
super.onDismissed(snackbar, i);
clear(snackbar.getContext());
}
});
activeSnackbar.show();
Logger.get(activity)
.logImpression(DialerImpression.Type.POST_CALL_PROMPT_USER_TO_VIEW_SENT_MESSAGE);
StorageComponent.get(activity)
.unencryptedSharedPrefs()
.edit()
.remove(KEY_POST_CALL_MESSAGE_SENT)
.apply();
}
public static void onDisconnectPressed(Context context) {
StorageComponent.get(context)
.unencryptedSharedPrefs()
.edit()
.putBoolean(KEY_POST_CALL_DISCONNECT_PRESSED, true)
.apply();
}
public static void onCallDisconnected(Context context, String number, long callConnectedMillis) {
StorageComponent.get(context)
.unencryptedSharedPrefs()
.edit()
.putLong(KEY_POST_CALL_CALL_CONNECT_TIME, callConnectedMillis)
.putLong(KEY_POST_CALL_CALL_DISCONNECT_TIME, System.currentTimeMillis())
.putString(KEY_POST_CALL_CALL_NUMBER, number)
.apply();
}
public static void onMessageSent(Context context, String number) {
StorageComponent.get(context)
.unencryptedSharedPrefs()
.edit()
.putString(KEY_POST_CALL_CALL_NUMBER, number)
.putBoolean(KEY_POST_CALL_MESSAGE_SENT, true)
.apply();
}
/**
* Restart performance recording if there is a recent call (disconnect time to now is under
* threshold)
*/
public static void restartPerformanceRecordingIfARecentCallExist(Context context) {
long disconnectTimeMillis =
StorageComponent.get(context)
.unencryptedSharedPrefs()
.getLong(PostCall.KEY_POST_CALL_CALL_DISCONNECT_TIME, -1);
if (disconnectTimeMillis != -1 && PerformanceReport.isRecording()) {
PerformanceReport.startRecording();
}
}
private static void clear(Context context) {
activeSnackbar = null;
StorageComponent.get(context)
.unencryptedSharedPrefs()
.edit()
.remove(KEY_POST_CALL_CALL_DISCONNECT_TIME)
.remove(KEY_POST_CALL_CALL_NUMBER)
.remove(KEY_POST_CALL_MESSAGE_SENT)
.remove(KEY_POST_CALL_CALL_CONNECT_TIME)
.remove(KEY_POST_CALL_DISCONNECT_PRESSED)
.apply();
}
private static boolean shouldPromptUserToSendMessage(Context context) {
SharedPreferences manager = StorageComponent.get(context).unencryptedSharedPrefs();
long disconnectTimeMillis = manager.getLong(KEY_POST_CALL_CALL_DISCONNECT_TIME, -1);
long connectTimeMillis = manager.getLong(KEY_POST_CALL_CALL_CONNECT_TIME, -1);
long timeSinceDisconnect = System.currentTimeMillis() - disconnectTimeMillis;
long callDurationMillis = disconnectTimeMillis - connectTimeMillis;
boolean callDisconnectedByUser = manager.getBoolean(KEY_POST_CALL_DISCONNECT_PRESSED, false);
String number = manager.getString(KEY_POST_CALL_CALL_NUMBER, null);
boolean isSensitiveNumber = SensitivePhoneNumbers.getInstance().isSensitiveNumber(context,
number, INVALID_SUBSCRIPTION_ID);
ConfigProvider binding = ConfigProviderComponent.get(context).getConfigProvider();
return disconnectTimeMillis != -1
&& connectTimeMillis != -1
&& isSimReady(context)
&& binding.getLong("postcall_last_call_threshold", 30_000) > timeSinceDisconnect
&& (connectTimeMillis == 0
|| binding.getLong("postcall_call_duration_threshold", 35_000) > callDurationMillis)
&& getPhoneNumber(context) != null
&& callDisconnectedByUser
&& !isSensitiveNumber;
}
private static boolean shouldPromptUserToViewSentMessage(Context context) {
return StorageComponent.get(context)
.unencryptedSharedPrefs()
.getBoolean(KEY_POST_CALL_MESSAGE_SENT, false);
}
@Nullable
private static String getPhoneNumber(Context context) {
return StorageComponent.get(context)
.unencryptedSharedPrefs()
.getString(KEY_POST_CALL_CALL_NUMBER, null);
}
private static boolean isEnabled(Context context) {
return ConfigProviderComponent.get(context)
.getConfigProvider()
.getBoolean("enable_post_call_prod", true);
}
private static boolean isSimReady(Context context) {
return context.getSystemService(TelephonyManager.class).getSimState()
== TelephonyManager.SIM_STATE_READY;
}
}