summaryrefslogtreecommitdiff
path: root/java/com/android/incallui
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/incallui')
-rw-r--r--java/com/android/incallui/AnswerScreenPresenter.java38
-rw-r--r--java/com/android/incallui/NotificationBroadcastReceiver.java47
-rw-r--r--java/com/android/incallui/ReturnToCallController.java3
-rw-r--r--java/com/android/incallui/call/CallList.java90
-rw-r--r--java/com/android/incallui/contactgrid/ContactGridManager.java6
-rw-r--r--java/com/android/incallui/spam/SpamNotificationActivity.java2
-rw-r--r--java/com/android/incallui/spam/SpamNotificationService.java2
-rw-r--r--java/com/android/incallui/speakeasy/SpeakEasyCallManager.java8
-rw-r--r--java/com/android/incallui/speakeasy/SpeakEasyCallManagerStub.java7
-rw-r--r--java/com/android/incallui/videotech/duo/DuoVideoTech.java8
10 files changed, 160 insertions, 51 deletions
diff --git a/java/com/android/incallui/AnswerScreenPresenter.java b/java/com/android/incallui/AnswerScreenPresenter.java
index 0b79e4be7..e41bac606 100644
--- a/java/com/android/incallui/AnswerScreenPresenter.java
+++ b/java/com/android/incallui/AnswerScreenPresenter.java
@@ -24,6 +24,7 @@ import android.support.v4.os.UserManagerCompat;
import android.telecom.VideoProfile;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
@@ -35,6 +36,9 @@ import com.android.incallui.call.CallList;
import com.android.incallui.call.DialerCall;
import com.android.incallui.call.DialerCallListener;
import com.android.incallui.incalluilock.InCallUiLock;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
/** Manages changes for an incoming call screen. */
public class AnswerScreenPresenter
@@ -90,6 +94,39 @@ public class AnswerScreenPresenter
@Override
public void onAnswer(boolean answerVideoAsAudio) {
+
+ DialerCall incomingCall = CallList.getInstance().getIncomingCall();
+ InCallActivity inCallActivity =
+ (InCallActivity) answerScreen.getAnswerScreenFragment().getActivity();
+ ListenableFuture<Void> answerPrecondition;
+
+ if (incomingCall != null && inCallActivity != null) {
+ answerPrecondition = inCallActivity.getSpeakEasyCallManager().onNewIncomingCall(incomingCall);
+ } else {
+ answerPrecondition = Futures.immediateFuture(null);
+ }
+
+ Futures.addCallback(
+ answerPrecondition,
+ new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void result) {
+ onAnswerCallback(answerVideoAsAudio);
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ onAnswerCallback(answerVideoAsAudio);
+ // TODO(erfanian): Enumerate all error states and specify recovery strategies.
+ throw new RuntimeException("Failed to successfully complete pre call tasks.", t);
+ }
+ },
+ DialerExecutorComponent.get(context).uiExecutor());
+ addTimeoutCheck();
+ }
+
+ private void onAnswerCallback(boolean answerVideoAsAudio) {
+
if (answerScreen.isVideoUpgradeRequest()) {
if (answerVideoAsAudio) {
Logger.get(context)
@@ -113,7 +150,6 @@ public class AnswerScreenPresenter
call.answer();
}
}
- addTimeoutCheck();
}
@Override
diff --git a/java/com/android/incallui/NotificationBroadcastReceiver.java b/java/com/android/incallui/NotificationBroadcastReceiver.java
index 52d01f5c4..602eb5c5a 100644
--- a/java/com/android/incallui/NotificationBroadcastReceiver.java
+++ b/java/com/android/incallui/NotificationBroadcastReceiver.java
@@ -20,15 +20,21 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build.VERSION_CODES;
+import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.telecom.CallAudioState;
import android.telecom.VideoProfile;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.incallui.call.CallList;
import com.android.incallui.call.DialerCall;
import com.android.incallui.call.TelecomAdapter;
+import com.android.incallui.speakeasy.SpeakEasyCallManager;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
/**
* Accepts broadcast Intents which will be prepared by {@link StatusBarNotifier} and thus sent from
@@ -72,9 +78,9 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
// TODO: Commands of this nature should exist in the CallList.
if (action.equals(ACTION_ANSWER_VIDEO_INCOMING_CALL)) {
- answerIncomingCall(VideoProfile.STATE_BIDIRECTIONAL);
+ answerIncomingCall(VideoProfile.STATE_BIDIRECTIONAL, context);
} else if (action.equals(ACTION_ANSWER_VOICE_INCOMING_CALL)) {
- answerIncomingCall(VideoProfile.STATE_AUDIO_ONLY);
+ answerIncomingCall(VideoProfile.STATE_AUDIO_ONLY, context);
} else if (action.equals(ACTION_DECLINE_INCOMING_CALL)) {
Logger.get(context)
.logImpression(DialerImpression.Type.REJECT_INCOMING_CALL_FROM_NOTIFICATION);
@@ -140,7 +146,7 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
}
}
- private void answerIncomingCall(int videoState) {
+ private void answerIncomingCall(int videoState, @NonNull Context context) {
CallList callList = InCallPresenter.getInstance().getCallList();
if (callList == null) {
StatusBarNotifier.clearAllCallNotifications();
@@ -148,13 +154,42 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
} else {
DialerCall call = callList.getIncomingCall();
if (call != null) {
- call.answer(videoState);
- InCallPresenter.getInstance()
- .showInCall(false /* showDialpad */, false /* newOutgoingCall */);
+
+ SpeakEasyCallManager speakEasyCallManager =
+ InCallPresenter.getInstance().getSpeakEasyCallManager();
+ ListenableFuture<Void> answerPrecondition;
+
+ if (speakEasyCallManager != null) {
+ answerPrecondition = speakEasyCallManager.onNewIncomingCall(call);
+ } else {
+ answerPrecondition = Futures.immediateFuture(null);
+ }
+
+ Futures.addCallback(
+ answerPrecondition,
+ new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void result) {
+ answerIncomingCallCallback(call, videoState);
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ answerIncomingCallCallback(call, videoState);
+ // TODO(erfanian): Enumerate all error states and specify recovery strategies.
+ throw new RuntimeException("Failed to successfully complete pre call tasks.", t);
+ }
+ },
+ DialerExecutorComponent.get(context).uiExecutor());
}
}
}
+ private void answerIncomingCallCallback(@NonNull DialerCall call, int videoState) {
+ call.answer(videoState);
+ InCallPresenter.getInstance().showInCall(false /* showDialpad */, false /* newOutgoingCall */);
+ }
+
private void declineIncomingCall() {
CallList callList = InCallPresenter.getInstance().getCallList();
if (callList == null) {
diff --git a/java/com/android/incallui/ReturnToCallController.java b/java/com/android/incallui/ReturnToCallController.java
index 96bdda1ba..7c4585ca1 100644
--- a/java/com/android/incallui/ReturnToCallController.java
+++ b/java/com/android/incallui/ReturnToCallController.java
@@ -196,12 +196,13 @@ public class ReturnToCallController implements InCallUiListener, Listener, Audio
newInCallState != inCallState
&& newInCallState == InCallState.OUTGOING
&& shouldStartInBubbleMode;
+ boolean bubbleNeverVisible = (bubble == null || !(bubble.isVisible() || bubble.isDismissed()));
if (bubble != null && isNewBackgroundCall) {
// If new outgoing call is in bubble mode, update bubble info.
// We don't update if new call is not in bubble mode even if the existing call is.
bubble.setBubbleInfo(generateBubbleInfoForBackgroundCalling());
}
- if ((bubble == null || !(bubble.isVisible() || bubble.isDismissed()) || isNewBackgroundCall)
+ if (((bubbleNeverVisible && newInCallState != InCallState.OUTGOING) || isNewBackgroundCall)
&& getCall() != null
&& !InCallPresenter.getInstance().isShowingInCallUi()) {
LogUtil.i("ReturnToCallController.onCallListChange", "going to show bubble");
diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java
index 5d9db32d9..0e89ac75d 100644
--- a/java/com/android/incallui/call/CallList.java
+++ b/java/com/android/incallui/call/CallList.java
@@ -32,6 +32,7 @@ import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler;
import com.android.dialer.blocking.FilteredNumbersUtil;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.enrichedcall.EnrichedCallComponent;
import com.android.dialer.enrichedcall.EnrichedCallManager;
import com.android.dialer.logging.DialerImpression;
@@ -41,10 +42,14 @@ import com.android.dialer.metrics.MetricsComponent;
import com.android.dialer.shortcuts.ShortcutUsageReporter;
import com.android.dialer.spam.Spam;
import com.android.dialer.spam.SpamComponent;
+import com.android.dialer.spam.status.SpamStatus;
import com.android.dialer.telecom.TelecomCallUtil;
import com.android.incallui.call.state.DialerCallState;
import com.android.incallui.latencyreport.LatencyReport;
import com.android.incallui.videotech.utils.SessionModificationState;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
@@ -146,46 +151,53 @@ public class CallList implements DialerCallDelegate {
LogUtil.d("CallList.onCallAdded", "callState=" + call.getState());
if (SpamComponent.get(context).spamSettings().isSpamEnabled()) {
String number = TelecomCallUtil.getNumber(telecomCall);
- SpamComponent.get(context)
- .spam()
- .checkSpamStatus(
- number,
- call.getCountryIso(),
- new Spam.Listener() {
- @Override
- public void onComplete(boolean isSpam) {
- boolean isIncomingCall =
- call.getState() == DialerCallState.INCOMING
- || call.getState() == DialerCallState.CALL_WAITING;
- if (isSpam) {
- if (!isIncomingCall) {
- LogUtil.i(
- "CallList.onCallAdded",
- "marking spam call as not spam because it's not an incoming call");
- isSpam = false;
- } else if (isPotentialEmergencyCallback(context, call)) {
- LogUtil.i(
- "CallList.onCallAdded",
- "marking spam call as not spam because an emergency call was made on this"
- + " device recently");
- isSpam = false;
- }
- }
-
- if (isIncomingCall) {
- Logger.get(context)
- .logCallImpression(
- isSpam
- ? DialerImpression.Type.INCOMING_SPAM_CALL
- : DialerImpression.Type.INCOMING_NON_SPAM_CALL,
- call.getUniqueCallId(),
- call.getTimeAddedMs());
- }
- call.setSpam(isSpam);
- onUpdateCall(call);
- notifyGenericListeners();
+ ListenableFuture<SpamStatus> futureSpamStatus =
+ SpamComponent.get(context).spam().checkSpamStatus(number, call.getCountryIso());
+
+ Futures.addCallback(
+ futureSpamStatus,
+ new FutureCallback<SpamStatus>() {
+ @Override
+ public void onSuccess(@Nullable SpamStatus result) {
+ boolean isIncomingCall =
+ call.getState() == DialerCallState.INCOMING
+ || call.getState() == DialerCallState.CALL_WAITING;
+ boolean isSpam = result.isSpam();
+ if (isSpam) {
+ if (!isIncomingCall) {
+ LogUtil.i(
+ "CallList.onCallAdded",
+ "marking spam call as not spam because it's not an incoming call");
+ isSpam = false;
+ } else if (isPotentialEmergencyCallback(context, call)) {
+ LogUtil.i(
+ "CallList.onCallAdded",
+ "marking spam call as not spam because an emergency call was made on this"
+ + " device recently");
+ isSpam = false;
}
- });
+ }
+
+ if (isIncomingCall) {
+ Logger.get(context)
+ .logCallImpression(
+ isSpam
+ ? DialerImpression.Type.INCOMING_SPAM_CALL
+ : DialerImpression.Type.INCOMING_NON_SPAM_CALL,
+ call.getUniqueCallId(),
+ call.getTimeAddedMs());
+ }
+ call.setSpam(isSpam);
+ onUpdateCall(call);
+ notifyGenericListeners();
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ LogUtil.e("CallList.onFailure", "unable to query spam status", t);
+ }
+ },
+ DialerExecutorComponent.get(context).uiExecutor());
Trace.beginSection("updateUserMarkedSpamStatus");
updateUserMarkedSpamStatus(call, context, number);
diff --git a/java/com/android/incallui/contactgrid/ContactGridManager.java b/java/com/android/incallui/contactgrid/ContactGridManager.java
index d8b1f5004..493f2d583 100644
--- a/java/com/android/incallui/contactgrid/ContactGridManager.java
+++ b/java/com/android/incallui/contactgrid/ContactGridManager.java
@@ -23,6 +23,8 @@ import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.telephony.PhoneNumberUtils;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
import android.text.TextUtils;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
@@ -416,7 +418,9 @@ public class ContactGridManager {
// This is used for carriers like Project Fi to show the callback number for emergency calls.
deviceNumberTextView.setText(
context.getString(
- R.string.contact_grid_callback_number, primaryCallState.callbackNumber()));
+ R.string.contact_grid_callback_number,
+ BidiFormatter.getInstance()
+ .unicodeWrap(primaryCallState.callbackNumber(), TextDirectionHeuristics.LTR)));
deviceNumberTextView.setVisibility(View.VISIBLE);
if (primaryInfo.shouldShowLocation()) {
deviceNumberDivider.setVisibility(View.VISIBLE);
diff --git a/java/com/android/incallui/spam/SpamNotificationActivity.java b/java/com/android/incallui/spam/SpamNotificationActivity.java
index e10dea381..2cf486874 100644
--- a/java/com/android/incallui/spam/SpamNotificationActivity.java
+++ b/java/com/android/incallui/spam/SpamNotificationActivity.java
@@ -528,7 +528,7 @@ public class SpamNotificationActivity extends FragmentActivity {
}
private void maybeShowSpamBlockingPromoAndFinish() {
- if (!spamBlockingPromoHelper.shouldShowSpamBlockingPromo()) {
+ if (!spamBlockingPromoHelper.shouldShowAfterCallSpamBlockingPromo()) {
finish();
return;
}
diff --git a/java/com/android/incallui/spam/SpamNotificationService.java b/java/com/android/incallui/spam/SpamNotificationService.java
index b418ea23e..82a943da7 100644
--- a/java/com/android/incallui/spam/SpamNotificationService.java
+++ b/java/com/android/incallui/spam/SpamNotificationService.java
@@ -122,7 +122,7 @@ public class SpamNotificationService extends Service {
ReportingLocation.Type.FEEDBACK_PROMPT,
contactLookupResultType);
new FilteredNumberAsyncQueryHandler(this).blockNumber(null, number, countryIso);
- if (spamBlockingPromoHelper.shouldShowSpamBlockingPromo()) {
+ if (spamBlockingPromoHelper.shouldShowAfterCallSpamBlockingPromo()) {
spamBlockingPromoHelper.showSpamBlockingPromoNotification(
notificationTag,
notificationId,
diff --git a/java/com/android/incallui/speakeasy/SpeakEasyCallManager.java b/java/com/android/incallui/speakeasy/SpeakEasyCallManager.java
index 8a815d385..b060f64cb 100644
--- a/java/com/android/incallui/speakeasy/SpeakEasyCallManager.java
+++ b/java/com/android/incallui/speakeasy/SpeakEasyCallManager.java
@@ -21,6 +21,7 @@ import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import com.android.incallui.call.DialerCall;
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
/** Provides operations necessary to SpeakEasy. */
public interface SpeakEasyCallManager {
@@ -40,6 +41,13 @@ public interface SpeakEasyCallManager {
void onCallRemoved(@NonNull DialerCall call);
/**
+ * Indicates there is a new incoming call that is about to be answered.
+ *
+ * @param call The call which is about to become active.
+ */
+ ListenableFuture<Void> onNewIncomingCall(@NonNull DialerCall call);
+
+ /**
* Indicates the feature is available.
*
* @param context The application context.
diff --git a/java/com/android/incallui/speakeasy/SpeakEasyCallManagerStub.java b/java/com/android/incallui/speakeasy/SpeakEasyCallManagerStub.java
index a0409737b..da5e88aa3 100644
--- a/java/com/android/incallui/speakeasy/SpeakEasyCallManagerStub.java
+++ b/java/com/android/incallui/speakeasy/SpeakEasyCallManagerStub.java
@@ -22,6 +22,8 @@ import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import com.android.incallui.call.DialerCall;
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import javax.inject.Inject;
/** Default implementation of SpeakEasyCallManager. */
@@ -41,6 +43,11 @@ public class SpeakEasyCallManagerStub implements SpeakEasyCallManager {
@Override
public void onCallRemoved(DialerCall call) {}
+ @Override
+ public ListenableFuture<Void> onNewIncomingCall(@NonNull DialerCall call) {
+ return Futures.immediateFuture(null);
+ }
+
/** Always returns false. */
@Override
public boolean isAvailable(@NonNull Context unused) {
diff --git a/java/com/android/incallui/videotech/duo/DuoVideoTech.java b/java/com/android/incallui/videotech/duo/DuoVideoTech.java
index fdaed077b..ac74e54df 100644
--- a/java/com/android/incallui/videotech/duo/DuoVideoTech.java
+++ b/java/com/android/incallui/videotech/duo/DuoVideoTech.java
@@ -23,6 +23,7 @@ import android.telecom.Call;
import android.telecom.PhoneAccountHandle;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DefaultFutureCallback;
import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.duo.Duo;
import com.android.dialer.duo.DuoListener;
@@ -33,6 +34,8 @@ import com.android.incallui.videotech.VideoTech;
import com.android.incallui.videotech.utils.SessionModificationState;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
public class DuoVideoTech implements VideoTech, DuoListener {
private final Duo duo;
@@ -77,7 +80,10 @@ public class DuoVideoTech implements VideoTech, DuoListener {
if (!isRemoteUpgradeAvailabilityQueried) {
LogUtil.v("DuoVideoTech.isAvailable", "reachability unknown, starting remote query");
isRemoteUpgradeAvailabilityQueried = true;
- duo.updateReachability(context, ImmutableList.of(callingNumber));
+ Futures.addCallback(
+ duo.updateReachability(context, ImmutableList.of(callingNumber)),
+ new DefaultFutureCallback<>(),
+ MoreExecutors.directExecutor());
}
return false;