diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2018-05-10 01:14:47 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-05-10 01:14:47 +0000 |
commit | ced93f2d22bffce3b4cfb9c3bfce862b385537dd (patch) | |
tree | 2b4715070bcf45b8a8395ee0ae5c7fbb0ef8274c /java/com/android/incallui | |
parent | c49c914e53500fc661ec47e365621c9d33e046ca (diff) | |
parent | 2f4a0075e9f546514359eda60a24ac9cd49ea80a (diff) |
Merge changes Ia54e3421,Id2176e6e,I0311770e,I79f99c34,I8579afff, ...
* changes:
Add some annotations that won't influence aosp.
Update answer button logic.
Hide new after call spam blocking promo behind an additional flag.
Allow the TextView for call log primary text to adjust size when recycled.
Format callback phone number.
Added getLoggingName() to CallLogDataSource and PhoneLookup interfaces.
Do not show bubble for outgoing call if it's not a background call.
Always fetch status onResume and add logging for voicemail status in OldMainPeer and
Place Duo calls with PreCall
Creating CallIntent, AutoValue builder, to replace CallIntentBuilder.
Set the DisplayNameSource to PHONE in DefaultLookupUriGenerator.
Config correct layout boundaries to accommodate long text (call log & bottom sheet)
Use info from EmergencyPhoneLookup to render UI for an emergency number.
Implement EmergencyPhoneLookup for checking if a number is an emergency number.
Add GlobalSpamListStatus and UserSpamListStatus
Move SpamStatus classes into subpackage
Delete obsolete checkSpamStatus(Listener) API
Update callers of checkSpamStatus to use Future based API
Fix bug that showing block option for private number.
Add a null check for digitsHint.
Don't commit fragment transactions if it's not safe.
Add ListenableFuture based APIs for checkSpamStatus
Pass activity between new call log's adapter/view holder.
Replace assert checks with safety checks instead.
Add SimpleSpamStatus and use it in FakeSpam and SpamStub
Show calls to/from emergency numbers as "Emergency number" in call log & call details
Diffstat (limited to 'java/com/android/incallui')
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; |