From 830da7cfa269e7af044cf6df5a86cb9ea6aef685 Mon Sep 17 00:00:00 2001 From: maxwelb Date: Fri, 4 May 2018 15:27:08 -0700 Subject: Update callers of checkSpamStatus to use Future based API Bug: 79171382 Test: Tap, manually verified spam calls (and autoblock) PiperOrigin-RevId: 195480993 Change-Id: Ifefee382ae6181c20e83d16b2e0519dd05e60c6a --- java/com/android/incallui/call/CallList.java | 90 ++++++++++++++++------------ 1 file changed, 51 insertions(+), 39 deletions(-) (limited to 'java/com/android/incallui') diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java index 5d9db32d9..1b2670eed 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.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 futureSpamStatus = + SpamComponent.get(context).spam().checkSpamStatus(number, call.getCountryIso()); + + Futures.addCallback( + futureSpamStatus, + new FutureCallback() { + @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); -- cgit v1.2.3 From 80e3892b5bc6c6f5294f9bf0bd2aada06677de1d Mon Sep 17 00:00:00 2001 From: maxwelb Date: Fri, 4 May 2018 17:32:56 -0700 Subject: Move SpamStatus classes into subpackage Test: Build PiperOrigin-RevId: 195498557 Change-Id: I28525d0475f847b2ff5a128580256e2688ed47d5 --- .../dialer/phonelookup/spam/SpamPhoneLookup.java | 2 +- java/com/android/dialer/spam/SimpleSpamStatus.java | 36 ------------------- java/com/android/dialer/spam/Spam.java | 1 + java/com/android/dialer/spam/SpamStatus.java | 40 ---------------------- java/com/android/dialer/spam/SpamStub.java | 2 ++ .../dialer/spam/status/SimpleSpamStatus.java | 36 +++++++++++++++++++ .../com/android/dialer/spam/status/SpamStatus.java | 40 ++++++++++++++++++++++ java/com/android/incallui/call/CallList.java | 2 +- 8 files changed, 81 insertions(+), 78 deletions(-) delete mode 100644 java/com/android/dialer/spam/SimpleSpamStatus.java delete mode 100644 java/com/android/dialer/spam/SpamStatus.java create mode 100644 java/com/android/dialer/spam/status/SimpleSpamStatus.java create mode 100644 java/com/android/dialer/spam/status/SpamStatus.java (limited to 'java/com/android/incallui') diff --git a/java/com/android/dialer/phonelookup/spam/SpamPhoneLookup.java b/java/com/android/dialer/phonelookup/spam/SpamPhoneLookup.java index 6b77036cf..71341ba64 100644 --- a/java/com/android/dialer/phonelookup/spam/SpamPhoneLookup.java +++ b/java/com/android/dialer/phonelookup/spam/SpamPhoneLookup.java @@ -27,7 +27,7 @@ import com.android.dialer.phonelookup.PhoneLookup; import com.android.dialer.phonelookup.PhoneLookupInfo; import com.android.dialer.phonelookup.PhoneLookupInfo.SpamInfo; import com.android.dialer.spam.Spam; -import com.android.dialer.spam.SpamStatus; +import com.android.dialer.spam.status.SpamStatus; import com.android.dialer.storage.Unencrypted; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; diff --git a/java/com/android/dialer/spam/SimpleSpamStatus.java b/java/com/android/dialer/spam/SimpleSpamStatus.java deleted file mode 100644 index b49241cf8..000000000 --- a/java/com/android/dialer/spam/SimpleSpamStatus.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source 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.spam; - -import android.support.annotation.Nullable; -import com.google.auto.value.AutoValue; -import com.google.common.base.Optional; - -/** Holds a boolean and long to represent spam status. */ -@AutoValue -public abstract class SimpleSpamStatus implements SpamStatus { - - /** Returns a SimpleSpamStatus with the given boolean and timestamp. */ - public static SimpleSpamStatus create(boolean isSpam, @Nullable Long timestampMillis) { - return new AutoValue_SimpleSpamStatus(isSpam, Optional.fromNullable(timestampMillis)); - } - - /** Returns a SimpleSpamStatus that's not marked as spam and has no timestamp. */ - public static SimpleSpamStatus notSpam() { - return create(false, null); - } -} diff --git a/java/com/android/dialer/spam/Spam.java b/java/com/android/dialer/spam/Spam.java index 6aa69af4a..181a55dea 100644 --- a/java/com/android/dialer/spam/Spam.java +++ b/java/com/android/dialer/spam/Spam.java @@ -24,6 +24,7 @@ import com.android.dialer.DialerPhoneNumber; import com.android.dialer.logging.ContactLookupResult; import com.android.dialer.logging.ContactSource; import com.android.dialer.logging.ReportingLocation; +import com.android.dialer.spam.status.SpamStatus; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.ListenableFuture; diff --git a/java/com/android/dialer/spam/SpamStatus.java b/java/com/android/dialer/spam/SpamStatus.java deleted file mode 100644 index 0b859d1c7..000000000 --- a/java/com/android/dialer/spam/SpamStatus.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source 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.spam; - -import com.google.common.base.Optional; - -/** An interface representing a number's spam status. */ -@SuppressWarnings("Guava") -public interface SpamStatus { - - /** Returns true if the number is spam. */ - boolean isSpam(); - - /** - * Returns the timestamp (in milliseconds) indicating when the number's spam status entered the - * underlying data source. - * - *

{@code Optional.absent()} is returned if - * - *

    - *
  • the number's spam status doesn't exist in the underlying data source, or - *
  • the underlying data source can't provide a timestamp. - *
- */ - Optional getTimestampMillis(); -} diff --git a/java/com/android/dialer/spam/SpamStub.java b/java/com/android/dialer/spam/SpamStub.java index a2e7258ee..2789c01e7 100644 --- a/java/com/android/dialer/spam/SpamStub.java +++ b/java/com/android/dialer/spam/SpamStub.java @@ -22,6 +22,8 @@ import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; import com.android.dialer.logging.ContactLookupResult; import com.android.dialer.logging.ContactSource; import com.android.dialer.logging.ReportingLocation; +import com.android.dialer.spam.status.SimpleSpamStatus; +import com.android.dialer.spam.status.SpamStatus; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.Futures; diff --git a/java/com/android/dialer/spam/status/SimpleSpamStatus.java b/java/com/android/dialer/spam/status/SimpleSpamStatus.java new file mode 100644 index 000000000..ec28b9dce --- /dev/null +++ b/java/com/android/dialer/spam/status/SimpleSpamStatus.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 The Android Open Source 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.spam.status; + +import android.support.annotation.Nullable; +import com.google.auto.value.AutoValue; +import com.google.common.base.Optional; + +/** Holds a boolean and long to represent spam status. */ +@AutoValue +public abstract class SimpleSpamStatus implements SpamStatus { + + /** Returns a SimpleSpamStatus with the given boolean and timestamp. */ + public static SimpleSpamStatus create(boolean isSpam, @Nullable Long timestampMillis) { + return new AutoValue_SimpleSpamStatus(isSpam, Optional.fromNullable(timestampMillis)); + } + + /** Returns a SimpleSpamStatus that's not marked as spam and has no timestamp. */ + public static SimpleSpamStatus notSpam() { + return create(false, null); + } +} diff --git a/java/com/android/dialer/spam/status/SpamStatus.java b/java/com/android/dialer/spam/status/SpamStatus.java new file mode 100644 index 000000000..8186ac5cc --- /dev/null +++ b/java/com/android/dialer/spam/status/SpamStatus.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 The Android Open Source 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.spam.status; + +import com.google.common.base.Optional; + +/** An interface representing a number's spam status. */ +@SuppressWarnings("Guava") +public interface SpamStatus { + + /** Returns true if the number is spam. */ + boolean isSpam(); + + /** + * Returns the timestamp (in milliseconds) indicating when the number's spam status entered the + * underlying data source. + * + *

{@code Optional.absent()} is returned if + * + *

    + *
  • the number's spam status doesn't exist in the underlying data source, or + *
  • the underlying data source can't provide a timestamp. + *
+ */ + Optional getTimestampMillis(); +} diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java index 1b2670eed..0e89ac75d 100644 --- a/java/com/android/incallui/call/CallList.java +++ b/java/com/android/incallui/call/CallList.java @@ -42,7 +42,7 @@ 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.SpamStatus; +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; -- cgit v1.2.3 From b2b6365629aed422a006529fe7940612f778baed Mon Sep 17 00:00:00 2001 From: twyen Date: Mon, 7 May 2018 16:36:17 -0700 Subject: Place Duo calls with PreCall This CL consolidates common duo calling operations into precall, including checking reachability, falling back to carrier video call, placing the call to duo with startActivityForResult. TEST=TAP Bug: 78783816 Test: TAP PiperOrigin-RevId: 195742478 Change-Id: I9fea1e4999f604e1f3a153b28079cd0db77b7393 --- .../android/dialer/app/calllog/CallLogAdapter.java | 22 ----- .../app/calllog/CallLogListItemViewHolder.java | 53 +++--------- .../android/dialer/app/calllog/IntentProvider.java | 38 ++++++++- .../calldetails/CallDetailsActivityCommon.java | 24 ++---- .../dialer/callintent/CallIntentBuilder.java | 12 +++ .../dialer/calllogutils/CallLogRowActions.java | 7 +- java/com/android/dialer/duo/Duo.java | 18 +--- .../android/dialer/duo/PlaceDuoCallNotifier.java | 45 ---------- .../android/dialer/duo/PlaceDuoCallReceiver.java | 77 ----------------- java/com/android/dialer/duo/stub/DuoStub.java | 12 +-- .../dialer/historyitemactions/DuoCallModule.java | 56 ------------- .../HistoryItemActionModulesBuilder.java | 18 ++-- .../com/android/dialer/main/impl/MainActivity.java | 8 -- .../android/dialer/precall/PreCallCoordinator.java | 6 +- .../com/android/dialer/precall/impl/DuoAction.java | 97 ++++++++++++++++++++++ .../precall/impl/PreCallCoordinatorImpl.java | 20 ++++- .../android/dialer/precall/impl/PreCallModule.java | 3 +- .../searchfragment/list/NewSearchFragment.java | 9 +- .../android/dialer/speeddial/DisambigDialog.java | 10 +-- .../dialer/speeddial/SpeedDialFragment.java | 22 ++--- .../incallui/videotech/duo/DuoVideoTech.java | 8 +- 21 files changed, 227 insertions(+), 338 deletions(-) delete mode 100644 java/com/android/dialer/duo/PlaceDuoCallNotifier.java delete mode 100644 java/com/android/dialer/duo/PlaceDuoCallReceiver.java delete mode 100644 java/com/android/dialer/historyitemactions/DuoCallModule.java create mode 100644 java/com/android/dialer/precall/impl/DuoAction.java (limited to 'java/com/android/incallui') diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java index b99cef11f..c2c753e43 100644 --- a/java/com/android/dialer/app/calllog/CallLogAdapter.java +++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java @@ -64,7 +64,6 @@ import com.android.dialer.app.voicemail.VoicemailPlaybackPresenter.OnVoicemailDe import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.calldetails.CallDetailsEntries; import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry; -import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction; import com.android.dialer.calllogutils.PhoneCallDetails; import com.android.dialer.common.Assert; @@ -407,28 +406,7 @@ public class CallLogAdapter extends GroupingListAdapter } } expandViewHolderActions(viewHolder); - - if (isDuoCallButtonVisible(viewHolder.videoCallButtonView)) { - CallIntentBuilder.increaseLightbringerCallButtonAppearInExpandedCallLogItemCount(); - } - } - } - - private boolean isDuoCallButtonVisible(View videoCallButtonView) { - if (videoCallButtonView == null) { - return false; - } - if (videoCallButtonView.getVisibility() != View.VISIBLE) { - return false; - } - IntentProvider intentProvider = (IntentProvider) videoCallButtonView.getTag(); - if (intentProvider == null) { - return false; } - return DuoComponent.get(activity) - .getDuo() - .getIntentType(intentProvider.getIntent(activity)) - .isPresent(); } }; diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java index b7781f343..9b7741df4 100644 --- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java +++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java @@ -19,7 +19,6 @@ package com.android.dialer.app.calllog; import android.Manifest.permission; import android.annotation.SuppressLint; import android.app.Activity; -import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.res.Resources; @@ -51,7 +50,6 @@ import android.view.ViewStub; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; -import android.widget.Toast; import com.android.contacts.common.dialog.CallSubjectDialog; import com.android.dialer.app.DialtactsActivity; import com.android.dialer.app.R; @@ -96,7 +94,6 @@ import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.CallUtil; import com.android.dialer.util.DialerUtils; import com.android.dialer.util.UriUtils; -import com.google.common.base.Optional; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; @@ -550,7 +547,8 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder case CallbackAction.DUO: if (showDuoPrimaryButton()) { CallIntentBuilder.increaseLightbringerCallButtonAppearInCollapsedCallLogItemCount(); - primaryActionButtonView.setTag(IntentProvider.getDuoVideoIntentProvider(number)); + primaryActionButtonView.setTag( + IntentProvider.getDuoVideoIntentProvider(number, isNonContactEntry(info))); } else { primaryActionButtonView.setTag(IntentProvider.getReturnVideoCallIntentProvider(number)); } @@ -684,14 +682,17 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder boolean identifiedSpamCall = isSpamFeatureEnabled && isSpam; if (duo.isReachable(context, number)) { - videoCallButtonView.setTag(IntentProvider.getDuoVideoIntentProvider(number)); + videoCallButtonView.setTag( + IntentProvider.getDuoVideoIntentProvider(number, isNonContactEntry(info))); videoCallButtonView.setVisibility(View.VISIBLE); + CallIntentBuilder.increaseLightbringerCallButtonAppearInExpandedCallLogItemCount(); } else if (duo.isActivated(context) && !identifiedSpamCall) { if (ConfigProviderBindings.get(context) .getBoolean("enable_call_log_duo_invite_button", false)) { inviteVideoButtonView.setTag(IntentProvider.getDuoInviteIntentProvider(number)); inviteVideoButtonView.setVisibility(View.VISIBLE); Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_INVITE_SHOWN); + CallIntentBuilder.increaseLightbringerCallButtonAppearInExpandedCallLogItemCount(); } } else if (duo.isEnabled(context) && !identifiedSpamCall) { if (!duo.isInstalled(context)) { @@ -701,6 +702,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder setUpVideoButtonView.setVisibility(View.VISIBLE); Logger.get(context) .logImpression(DialerImpression.Type.DUO_CALL_LOG_SET_UP_INSTALL_SHOWN); + CallIntentBuilder.increaseLightbringerCallButtonAppearInExpandedCallLogItemCount(); } } else { if (ConfigProviderBindings.get(context) @@ -709,6 +711,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder setUpVideoButtonView.setVisibility(View.VISIBLE); Logger.get(context) .logImpression(DialerImpression.Type.DUO_CALL_LOG_SET_UP_ACTIVATE_SHOWN); + CallIntentBuilder.increaseLightbringerCallButtonAppearInExpandedCallLogItemCount(); } } } @@ -1024,20 +1027,13 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder if (intentProvider == null) { return; } - + intentProvider.logInteraction(context); final Intent intent = intentProvider.getIntent(context); // See IntentProvider.getCallDetailIntentProvider() for why this may be null. if (intent == null) { return; } - - // We check to see if we are starting a Duo intent. The reason is Duo - // intents need to be started using startActivityForResult instead of the usual startActivity - Optional duoIntentType = - DuoComponent.get(context).getDuo().getIntentType(intent); - if (duoIntentType.isPresent()) { - startDuoActivity(intent, duoIntentType.get()); - } else if (OldCallDetailsActivity.isLaunchIntent(intent)) { + if (OldCallDetailsActivity.isLaunchIntent(intent)) { PerformanceReport.recordClick(UiAction.Type.OPEN_CALL_DETAIL); ((Activity) context) .startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_CALL_DETAILS); @@ -1046,9 +1042,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder && intent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, -1) == VideoProfile.STATE_BIDIRECTIONAL) { Logger.get(context).logImpression(DialerImpression.Type.IMS_VIDEO_REQUESTED_FROM_CALL_LOG); - } else if (intent.filterEquals( - DuoComponent.get(context).getDuo().getInstallDuoIntent().orNull())) { - Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_SET_UP_INSTALL); } DialerUtils.startActivityWithErrorToast(context, intent); @@ -1062,32 +1055,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder return false; } - private void startDuoActivity(Intent intent, Duo.IntentType intentType) { - switch (intentType) { - case CALL: - Logger.get(context) - .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FROM_CALL_LOG); - if (isNonContactEntry(info)) { - Logger.get(context) - .logImpression( - DialerImpression.Type.LIGHTBRINGER_NON_CONTACT_VIDEO_REQUESTED_FROM_CALL_LOG); - } - break; - case INVITE: - Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_INVITE); - break; - case ACTIVATE: - Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_SET_UP_ACTIVATE); - break; - } - try { - Activity activity = (Activity) context; - activity.startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO); - } catch (ActivityNotFoundException e) { - Toast.makeText(context, R.string.activity_not_available, Toast.LENGTH_SHORT).show(); - } - } - private DialerContact buildContact() { DialerContact.Builder contact = DialerContact.newBuilder(); contact.setPhotoId(info.photoId); diff --git a/java/com/android/dialer/app/calllog/IntentProvider.java b/java/com/android/dialer/app/calllog/IntentProvider.java index 1bc726f64..21f341815 100644 --- a/java/com/android/dialer/app/calllog/IntentProvider.java +++ b/java/com/android/dialer/app/calllog/IntentProvider.java @@ -32,6 +32,8 @@ import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.dialercontact.DialerContact; import com.android.dialer.duo.DuoComponent; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; import com.android.dialer.precall.PreCall; import com.android.dialer.util.IntentUtil; import java.util.ArrayList; @@ -93,11 +95,26 @@ public abstract class IntentProvider { }; } - public static IntentProvider getDuoVideoIntentProvider(String number) { + public static IntentProvider getDuoVideoIntentProvider(String number, boolean isNonContact) { return new IntentProvider() { @Override public Intent getIntent(Context context) { - return DuoComponent.get(context).getDuo().getCallIntent(number).orNull(); + return PreCall.getIntent( + context, + new CallIntentBuilder(number, CallInitiationType.Type.CALL_LOG) + .setIsDuoCall(true) + .setIsVideoCall(true)); + } + + @Override + public void logInteraction(Context context) { + Logger.get(context) + .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FROM_CALL_LOG); + if (isNonContact) { + Logger.get(context) + .logImpression( + DialerImpression.Type.LIGHTBRINGER_NON_CONTACT_VIDEO_REQUESTED_FROM_CALL_LOG); + } } }; } @@ -108,6 +125,11 @@ public abstract class IntentProvider { public Intent getIntent(Context context) { return DuoComponent.get(context).getDuo().getInstallDuoIntent().orNull(); } + + @Override + public void logInteraction(Context context) { + Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_SET_UP_INSTALL); + } }; } @@ -117,6 +139,11 @@ public abstract class IntentProvider { public Intent getIntent(Context context) { return DuoComponent.get(context).getDuo().getActivateIntent().orNull(); } + + @Override + public void logInteraction(Context context) { + Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_SET_UP_ACTIVATE); + } }; } @@ -126,6 +153,11 @@ public abstract class IntentProvider { public Intent getIntent(Context context) { return DuoComponent.get(context).getDuo().getInviteIntent(number).orNull(); } + + @Override + public void logInteraction(Context context) { + Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_INVITE); + } }; } @@ -244,4 +276,6 @@ public abstract class IntentProvider { } public abstract Intent getIntent(Context context); + + public void logInteraction(Context context) {} } diff --git a/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java b/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java index 80a41919d..86a2676f5 100644 --- a/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java +++ b/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java @@ -19,7 +19,6 @@ package com.android.dialer.calldetails; import android.Manifest.permission; import android.annotation.SuppressLint; import android.app.Activity; -import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -35,7 +34,6 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; -import android.widget.Toast; import com.android.dialer.assisteddialing.ui.AssistedDialingSettingActivity; import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry; import com.android.dialer.callintent.CallInitiationType; @@ -48,9 +46,6 @@ import com.android.dialer.common.concurrent.DialerExecutor.Worker; import com.android.dialer.common.concurrent.DialerExecutorComponent; import com.android.dialer.common.concurrent.UiListener; import com.android.dialer.common.database.Selection; -import com.android.dialer.constants.ActivityRequestCodes; -import com.android.dialer.duo.Duo; -import com.android.dialer.duo.DuoComponent; import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.enrichedcall.EnrichedCallManager; import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult; @@ -63,7 +58,6 @@ import com.android.dialer.postcall.PostCall; import com.android.dialer.precall.PreCall; import com.android.dialer.rtt.RttTranscriptActivity; import com.android.dialer.rtt.RttTranscriptUtil; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.i18n.phonenumbers.NumberParseException; @@ -327,19 +321,11 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity { public void placeDuoVideoCall(String phoneNumber) { Logger.get(getActivity()) .logImpression(DialerImpression.Type.CALL_DETAILS_LIGHTBRINGER_CALL_BACK); - Duo duo = DuoComponent.get(getActivity()).getDuo(); - Optional intentOptional = duo.getCallIntent(phoneNumber); - if (!duo.isReachable(getActivity(), phoneNumber) || !intentOptional.isPresent()) { - placeImsVideoCall(phoneNumber); - return; - } - - try { - getActivity() - .startActivityForResult(intentOptional.get(), ActivityRequestCodes.DIALTACTS_DUO); - } catch (ActivityNotFoundException e) { - Toast.makeText(getActivity(), R.string.activity_not_available, Toast.LENGTH_SHORT).show(); - } + PreCall.start( + getActivity(), + new CallIntentBuilder(phoneNumber, CallInitiationType.Type.CALL_DETAILS) + .setIsDuoCall(true) + .setIsVideoCall(true)); } @Override diff --git a/java/com/android/dialer/callintent/CallIntentBuilder.java b/java/com/android/dialer/callintent/CallIntentBuilder.java index 92efd392b..613fdf6a3 100644 --- a/java/com/android/dialer/callintent/CallIntentBuilder.java +++ b/java/com/android/dialer/callintent/CallIntentBuilder.java @@ -43,6 +43,7 @@ public class CallIntentBuilder implements Parcelable { private final CallSpecificAppData callSpecificAppData; @Nullable private PhoneAccountHandle phoneAccountHandle; private boolean isVideoCall; + private boolean isDuoCall; private String callSubject; private boolean allowAssistedDial; @@ -109,6 +110,7 @@ public class CallIntentBuilder implements Parcelable { callSpecificAppData = data; phoneAccountHandle = parcel.readParcelable(classLoader); isVideoCall = parcel.readInt() != 0; + isDuoCall = parcel.readInt() != 0; callSubject = parcel.readString(); allowAssistedDial = parcel.readInt() != 0; inCallUiIntentExtras.putAll(parcel.readBundle(classLoader)); @@ -152,6 +154,15 @@ public class CallIntentBuilder implements Parcelable { return isVideoCall; } + public CallIntentBuilder setIsDuoCall(boolean isDuoCall) { + this.isDuoCall = isDuoCall; + return this; + } + + public boolean isDuoCall() { + return isDuoCall; + } + /** Default false. Should only be set to true if the number has a lookup URI. */ public CallIntentBuilder setAllowAssistedDial(boolean allowAssistedDial) { this.allowAssistedDial = allowAssistedDial; @@ -267,6 +278,7 @@ public class CallIntentBuilder implements Parcelable { dest.writeByteArray(callSpecificAppData.toByteArray()); dest.writeParcelable(phoneAccountHandle, flags); dest.writeInt(isVideoCall ? 1 : 0); + dest.writeInt(isDuoCall ? 1 : 0); dest.writeString(callSubject); dest.writeInt(allowAssistedDial ? 1 : 0); dest.writeBundle(inCallUiIntentExtras); diff --git a/java/com/android/dialer/calllogutils/CallLogRowActions.java b/java/com/android/dialer/calllogutils/CallLogRowActions.java index d23a15f78..65f3c5fd6 100644 --- a/java/com/android/dialer/calllogutils/CallLogRowActions.java +++ b/java/com/android/dialer/calllogutils/CallLogRowActions.java @@ -20,6 +20,7 @@ import android.provider.CallLog.Calls; import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.calllog.model.CoalescedRow; +import com.android.dialer.duo.DuoComponent; import com.android.dialer.precall.PreCall; /** Actions which can be performed on a call log row. */ @@ -37,6 +38,10 @@ public final class CallLogRowActions { activity, new CallIntentBuilder( row.getNumber().getNormalizedNumber(), CallInitiationType.Type.CALL_LOG) - .setIsVideoCall((row.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO)); + .setIsVideoCall((row.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) + .setIsDuoCall( + DuoComponent.get(activity) + .getDuo() + .isDuoAccount(row.getPhoneAccountComponentName()))); } } diff --git a/java/com/android/dialer/duo/Duo.java b/java/com/android/dialer/duo/Duo.java index 06a3db063..85fe9fbc1 100644 --- a/java/com/android/dialer/duo/Duo.java +++ b/java/com/android/dialer/duo/Duo.java @@ -27,6 +27,8 @@ import android.telecom.Call; import android.telecom.PhoneAccountHandle; import com.google.auto.value.AutoValue; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.ListenableFuture; import java.util.List; /** Interface for Duo video call integration. */ @@ -61,7 +63,8 @@ public interface Duo { /** Starts a task to update the reachability of the parameter numbers asynchronously. */ @MainThread - void updateReachability(@NonNull Context context, @NonNull List numbers); + ListenableFuture> updateReachability( + @NonNull Context context, @NonNull List numbers); /** * Clears the current reachability data and starts a task to load the latest reachability data @@ -95,19 +98,6 @@ public interface Duo { */ Optional getInviteIntent(String number); - /** Return value of {@link #getIntentType(Intent)} */ - enum IntentType { - /** The intent is returned by {@link #getCallIntent(String)} */ - CALL, - /** The intent is returned by {@link #getActivateIntent()} */ - ACTIVATE, - /** The intent is returned by {@link #getInviteIntent(String)} */ - INVITE - } - - /** Classifies a Duo intent. Absent if the intent is not a Duo intent. */ - Optional getIntentType(Intent intent); - Optional getInstallDuoIntent(); /** Requests upgrading the parameter ongoing call to a Duo video call. */ diff --git a/java/com/android/dialer/duo/PlaceDuoCallNotifier.java b/java/com/android/dialer/duo/PlaceDuoCallNotifier.java deleted file mode 100644 index 8fde981a0..000000000 --- a/java/com/android/dialer/duo/PlaceDuoCallNotifier.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source 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.duo; - -import android.content.Context; -import android.content.Intent; -import android.support.v4.content.LocalBroadcastManager; -import com.android.dialer.common.LogUtil; - -/** Notifies that a Duo video call should be started. */ -public final class PlaceDuoCallNotifier { - - private PlaceDuoCallNotifier() {} - - /** - * Broadcasts an intent notifying that a Duo call should be started. - * - *

See {@link PlaceDuoCallReceiver} for how the intent is handled. - * - * @param phoneNumber The number to start a Duo call. It can be of any format. - */ - public static void notify(Context context, String phoneNumber) { - LogUtil.enterBlock("PlaceDuoCallNotifier.notify"); - - Intent intent = new Intent(); - intent.setAction(PlaceDuoCallReceiver.ACTION_START_DUO_CALL); - intent.putExtra(PlaceDuoCallReceiver.EXTRA_PHONE_NUMBER, phoneNumber); - - LocalBroadcastManager.getInstance(context).sendBroadcast(intent); - } -} diff --git a/java/com/android/dialer/duo/PlaceDuoCallReceiver.java b/java/com/android/dialer/duo/PlaceDuoCallReceiver.java deleted file mode 100644 index f504aef57..000000000 --- a/java/com/android/dialer/duo/PlaceDuoCallReceiver.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source 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.duo; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import com.android.dialer.common.Assert; -import com.android.dialer.common.LogUtil; -import com.android.dialer.constants.ActivityRequestCodes; - -/** A {@link BroadcastReceiver} that starts a Duo video call. */ -public final class PlaceDuoCallReceiver extends BroadcastReceiver { - - static final String ACTION_START_DUO_CALL = "start_duo_call"; - static final String EXTRA_PHONE_NUMBER = "phone_number"; - - /** - * {@link Activity} needed to launch Duo. - * - *

A Duo call can only be placed via {@link Activity#startActivityForResult(Intent, int)}. - */ - private final Activity activity; - - /** Returns an {@link IntentFilter} containing all actions accepted by this broadcast receiver. */ - public static IntentFilter getIntentFilter() { - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(ACTION_START_DUO_CALL); - return intentFilter; - } - - public PlaceDuoCallReceiver(Activity activity) { - this.activity = activity; - } - - @Override - public void onReceive(Context context, Intent intent) { - LogUtil.enterBlock("PlaceDuoCallReceiver.onReceive"); - - String action = intent.getAction(); - - switch (Assert.isNotNull(action)) { - case ACTION_START_DUO_CALL: - startDuoCall(context, intent); - break; - default: - throw new IllegalStateException("Unsupported action: " + action); - } - } - - private void startDuoCall(Context context, Intent intent) { - LogUtil.enterBlock("PlaceDuoCallReceiver.startDuoCall"); - - Assert.checkArgument(intent.hasExtra(EXTRA_PHONE_NUMBER)); - String phoneNumber = intent.getStringExtra(EXTRA_PHONE_NUMBER); - - Duo duo = DuoComponent.get(context).getDuo(); - activity.startActivityForResult( - duo.getCallIntent(phoneNumber).orNull(), ActivityRequestCodes.DIALTACTS_DUO); - } -} diff --git a/java/com/android/dialer/duo/stub/DuoStub.java b/java/com/android/dialer/duo/stub/DuoStub.java index b0867148f..2131d16f7 100644 --- a/java/com/android/dialer/duo/stub/DuoStub.java +++ b/java/com/android/dialer/duo/stub/DuoStub.java @@ -29,6 +29,9 @@ import com.android.dialer.common.Assert; import com.android.dialer.duo.Duo; import com.android.dialer.duo.DuoListener; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import java.util.List; import javax.inject.Inject; @@ -72,10 +75,12 @@ public class DuoStub implements Duo { } @Override - public void updateReachability(@NonNull Context context, @NonNull List numbers) { + public ListenableFuture> updateReachability( + @NonNull Context context, @NonNull List numbers) { Assert.isMainThread(); Assert.isNotNull(context); Assert.isNotNull(numbers); + return Futures.immediateFuture(ImmutableMap.of()); } @Override @@ -114,11 +119,6 @@ public class DuoStub implements Duo { return Optional.absent(); } - @Override - public Optional getIntentType(Intent intent) { - return Optional.absent(); - } - @Override public Optional getInstallDuoIntent() { return null; diff --git a/java/com/android/dialer/historyitemactions/DuoCallModule.java b/java/com/android/dialer/historyitemactions/DuoCallModule.java deleted file mode 100644 index e6f31e293..000000000 --- a/java/com/android/dialer/historyitemactions/DuoCallModule.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source 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.historyitemactions; - -import android.Manifest.permission; -import android.content.Context; -import android.support.annotation.RequiresPermission; -import com.android.dialer.duo.PlaceDuoCallNotifier; - -/** {@link HistoryItemActionModule} for making a Duo call. */ -public class DuoCallModule implements HistoryItemActionModule { - - private final Context context; - private final String phoneNumber; - - /** - * Creates a module for making a Duo call. - * - * @param phoneNumber The number to start a Duo call. It can be of any format. - */ - public DuoCallModule(Context context, String phoneNumber) { - this.context = context; - this.phoneNumber = phoneNumber; - } - - @Override - public int getStringId() { - return R.string.video_call; - } - - @Override - public int getDrawableId() { - return R.drawable.quantum_ic_videocam_vd_white_24; - } - - @Override - @RequiresPermission(permission.READ_PHONE_STATE) - public boolean onClick() { - PlaceDuoCallNotifier.notify(context, phoneNumber); - return true; // Close the bottom sheet. - } -} diff --git a/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java b/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java index 5da56a127..e1c6c9666 100644 --- a/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java +++ b/java/com/android/dialer/historyitemactions/HistoryItemActionModulesBuilder.java @@ -149,18 +149,14 @@ public final class HistoryItemActionModulesBuilder { // Do not set PhoneAccountHandle so that regular PreCall logic will be used. The account used to // place or receive the call should be ignored for carrier video calls. // TODO(a bug): figure out the correct video call behavior - HistoryItemActionModule carrierVideoCallModule = - IntentModule.newCallModule( - context, - new CallIntentBuilder(moduleInfo.getNormalizedNumber(), getCallInitiationType()) - .setAllowAssistedDial(moduleInfo.getCanSupportAssistedDialing()) - .setIsVideoCall(true)); - HistoryItemActionModule duoVideoCallModule = - new DuoCallModule(context, moduleInfo.getNormalizedNumber()); + CallIntentBuilder callIntentBuilder = + new CallIntentBuilder(moduleInfo.getNormalizedNumber(), getCallInitiationType()) + .setAllowAssistedDial(moduleInfo.getCanSupportAssistedDialing()) + .setIsVideoCall(true); // If the module info is for a video call, add an appropriate video call module. if ((moduleInfo.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) { - modules.add(isDuoCall() && canPlaceDuoCall() ? duoVideoCallModule : carrierVideoCallModule); + modules.add(IntentModule.newCallModule(context, callIntentBuilder.setIsDuoCall(isDuoCall()))); return this; } @@ -169,9 +165,9 @@ public final class HistoryItemActionModulesBuilder { // // The carrier video call module takes precedence over the Duo module. if (canPlaceCarrierVideoCall()) { - modules.add(carrierVideoCallModule); + modules.add(IntentModule.newCallModule(context, callIntentBuilder)); } else if (canPlaceDuoCall()) { - modules.add(duoVideoCallModule); + modules.add(IntentModule.newCallModule(context, callIntentBuilder.setIsDuoCall(true))); } return this; } diff --git a/java/com/android/dialer/main/impl/MainActivity.java b/java/com/android/dialer/main/impl/MainActivity.java index 3f660f56c..2046b048f 100644 --- a/java/com/android/dialer/main/impl/MainActivity.java +++ b/java/com/android/dialer/main/impl/MainActivity.java @@ -24,7 +24,6 @@ import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogReceiver; import com.android.dialer.calllog.config.CallLogConfigComponent; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; -import com.android.dialer.duo.PlaceDuoCallReceiver; import com.android.dialer.interactions.PhoneNumberInteraction.DisambigDialogDismissedListener; import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorCode; import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorListener; @@ -48,9 +47,6 @@ public class MainActivity extends TransactionSafeActivity */ private ShowBlockReportSpamDialogReceiver showBlockReportSpamDialogReceiver; - /** {@link android.content.BroadcastReceiver} that starts a Duo call. */ - private PlaceDuoCallReceiver placeDuoCallReceiver; - public static Intent getShowCallLogIntent(Context context) { return getShowTabIntent(context, TabIndex.CALL_LOG); } @@ -83,7 +79,6 @@ public class MainActivity extends TransactionSafeActivity activePeer.onActivityCreate(savedInstanceState); showBlockReportSpamDialogReceiver = new ShowBlockReportSpamDialogReceiver(getFragmentManager()); - placeDuoCallReceiver = new PlaceDuoCallReceiver(/* activity = */ this); } protected MainActivityPeer getNewPeer() { @@ -109,8 +104,6 @@ public class MainActivity extends TransactionSafeActivity LocalBroadcastManager.getInstance(this) .registerReceiver( showBlockReportSpamDialogReceiver, ShowBlockReportSpamDialogReceiver.getIntentFilter()); - LocalBroadcastManager.getInstance(this) - .registerReceiver(placeDuoCallReceiver, PlaceDuoCallReceiver.getIntentFilter()); } @Override @@ -125,7 +118,6 @@ public class MainActivity extends TransactionSafeActivity activePeer.onActivityPause(); LocalBroadcastManager.getInstance(this).unregisterReceiver(showBlockReportSpamDialogReceiver); - LocalBroadcastManager.getInstance(this).unregisterReceiver(placeDuoCallReceiver); } @Override diff --git a/java/com/android/dialer/precall/PreCallCoordinator.java b/java/com/android/dialer/precall/PreCallCoordinator.java index 9c24e0d69..4d4859a80 100644 --- a/java/com/android/dialer/precall/PreCallCoordinator.java +++ b/java/com/android/dialer/precall/PreCallCoordinator.java @@ -68,8 +68,8 @@ public interface PreCallCoordinator { @NonNull PendingAction startPendingAction(); - void listen( - ListenableFuture future, - Consumer successListener, + void listen( + ListenableFuture future, + Consumer successListener, Consumer failureListener); } diff --git a/java/com/android/dialer/precall/impl/DuoAction.java b/java/com/android/dialer/precall/impl/DuoAction.java new file mode 100644 index 000000000..c05fbe12f --- /dev/null +++ b/java/com/android/dialer/precall/impl/DuoAction.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2018 The Android Open Source 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.precall.impl; + +import android.content.Context; +import android.content.Intent; +import com.android.dialer.callintent.CallIntentBuilder; +import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.Annotations.Ui; +import com.android.dialer.duo.Duo.ReachabilityData; +import com.android.dialer.duo.DuoComponent; +import com.android.dialer.precall.PreCallAction; +import com.android.dialer.precall.PreCallCoordinator; +import com.android.dialer.precall.PreCallCoordinator.PendingAction; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import javax.inject.Inject; + +/** + * Checks if a duo call is actually callable, and request an activity for {@link + * android.app.Activity#startActivityForResult(Intent, int)} + */ +public class DuoAction implements PreCallAction { + + private final ListeningExecutorService uiExecutor; + + @Inject + DuoAction(@Ui ListeningExecutorService uiExecutor) { + this.uiExecutor = uiExecutor; + } + + @Override + public boolean requiresUi(Context context, CallIntentBuilder builder) { + // Duo call must be started with startActivityForResult() which needs a activity. + return builder.isDuoCall(); + } + + @Override + public void runWithoutUi(Context context, CallIntentBuilder builder) {} + + @Override + public void runWithUi(PreCallCoordinator coordinator) { + if (!requiresUi(coordinator.getActivity(), coordinator.getBuilder())) { + return; + } + String number = coordinator.getBuilder().getUri().getSchemeSpecificPart(); + ListenableFuture> reachabilities = + DuoComponent.get(coordinator.getActivity()) + .getDuo() + .updateReachability(coordinator.getActivity(), ImmutableList.of(number)); + PendingAction pendingAction = coordinator.startPendingAction(); + + Futures.addCallback( + reachabilities, + new FutureCallback>() { + @Override + public void onSuccess(ImmutableMap result) { + if (!result.containsKey(number) || !result.get(number).videoCallable()) { + LogUtil.w( + "DuoAction.runWithUi", + number + " number no longer duo reachable, falling back to carrier video call"); + coordinator.getBuilder().setIsDuoCall(false); + } + pendingAction.finish(); + } + + @Override + public void onFailure(Throwable throwable) { + LogUtil.e("DuoAction.runWithUi", "reachability query failed", throwable); + coordinator.getBuilder().setIsDuoCall(false); + pendingAction.finish(); + } + }, + uiExecutor); + } + + @Override + public void onDiscard() {} +} diff --git a/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java b/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java index f2ff0e3e3..240549ca5 100644 --- a/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java +++ b/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java @@ -26,6 +26,7 @@ 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.UiListener; +import com.android.dialer.duo.DuoComponent; import com.android.dialer.function.Consumer; import com.android.dialer.logging.DialerImpression.Type; import com.android.dialer.logging.Logger; @@ -33,6 +34,7 @@ import com.android.dialer.precall.PreCallAction; import com.android.dialer.precall.PreCallComponent; import com.android.dialer.precall.PreCallCoordinator; import com.android.dialer.telecom.TelecomUtil; +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.ListenableFuture; @@ -101,7 +103,7 @@ public class PreCallCoordinatorImpl implements PreCallCoordinator { LogUtil.enterBlock("PreCallCoordinatorImpl.runNextAction"); Assert.checkArgument(currentAction == null); if (currentActionIndex >= actions.size()) { - TelecomUtil.placeCall(activity, builder.build()); + placeCall(); activity.finish(); return; } @@ -177,4 +179,20 @@ public class PreCallCoordinatorImpl implements PreCallCoordinator { output -> successListener.accept((OutputT) output), failureListener::accept); } + + private void placeCall() { + if (builder.isDuoCall()) { + Optional intent = + DuoComponent.get(activity) + .getDuo() + .getCallIntent(builder.getUri().getSchemeSpecificPart()); + if (intent.isPresent()) { + activity.startActivityForResult(intent.get(), 0); + return; + } else { + LogUtil.e("PreCallCoordinatorImpl.placeCall", "duo.getCallIntent() returned absent"); + } + } + TelecomUtil.placeCall(activity, builder.build()); + } } diff --git a/java/com/android/dialer/precall/impl/PreCallModule.java b/java/com/android/dialer/precall/impl/PreCallModule.java index 9820e2b66..455453ef3 100644 --- a/java/com/android/dialer/precall/impl/PreCallModule.java +++ b/java/com/android/dialer/precall/impl/PreCallModule.java @@ -37,12 +37,13 @@ public abstract class PreCallModule { @Provides @Singleton public static ImmutableList provideActions( - CallingAccountSelector callingAccountSelector) { + DuoAction duoAction, CallingAccountSelector callingAccountSelector) { return ImmutableList.of( new PermissionCheckAction(), new MalformedNumberRectifier( ImmutableList.of(new UkRegionPrefixInInternationalFormatHandler())), callingAccountSelector, + duoAction, new AssistedDialAction()); } } diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java index f1eed91ba..abb3aecd4 100644 --- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java +++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java @@ -51,9 +51,7 @@ import com.android.dialer.common.Assert; import com.android.dialer.common.FragmentUtils; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.ThreadUtil; -import com.android.dialer.constants.ActivityRequestCodes; import com.android.dialer.dialercontact.DialerContact; -import com.android.dialer.duo.DuoComponent; import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.enrichedcall.EnrichedCallManager.CapabilitiesListener; import com.android.dialer.logging.DialerImpression; @@ -549,8 +547,11 @@ public final class NewSearchFragment extends Fragment public void placeDuoCall(String phoneNumber) { Logger.get(getContext()) .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FROM_SEARCH); - Intent intent = DuoComponent.get(getContext()).getDuo().getCallIntent(phoneNumber).orNull(); - getActivity().startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO); + PreCall.start( + getContext(), + new CallIntentBuilder(phoneNumber, CallInitiationType.Type.REGULAR_SEARCH) + .setIsVideoCall(true) + .setIsDuoCall(true)); FragmentUtils.getParentUnsafe(this, SearchFragmentListener.class).onCallPlacedFromSearch(); } diff --git a/java/com/android/dialer/speeddial/DisambigDialog.java b/java/com/android/dialer/speeddial/DisambigDialog.java index 98fc992f8..2dd43fa0a 100644 --- a/java/com/android/dialer/speeddial/DisambigDialog.java +++ b/java/com/android/dialer/speeddial/DisambigDialog.java @@ -18,7 +18,6 @@ package com.android.dialer.speeddial; import android.app.Dialog; import android.content.Context; -import android.content.Intent; import android.os.Bundle; import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; @@ -40,8 +39,6 @@ import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DefaultFutureCallback; import com.android.dialer.common.concurrent.DialerExecutorComponent; -import com.android.dialer.constants.ActivityRequestCodes; -import com.android.dialer.duo.DuoComponent; import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; import com.android.dialer.precall.PreCall; @@ -184,16 +181,13 @@ public class DisambigDialog extends DialogFragment { Logger.get(getContext()) .logImpression( DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT_DISAMBIG); - Intent intent = - DuoComponent.get(getContext()).getDuo().getCallIntent(channel.number()).orNull(); - getActivity().startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO); - return; } PreCall.start( getContext(), new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL) - .setIsVideoCall(true)); + .setIsVideoCall(true) + .setIsDuoCall(channel.technology() == Channel.DUO)); dismiss(); } diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java index aa306d214..fac9a13d2 100644 --- a/java/com/android/dialer/speeddial/SpeedDialFragment.java +++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java @@ -41,7 +41,6 @@ import com.android.dialer.common.concurrent.DefaultFutureCallback; import com.android.dialer.common.concurrent.DialerExecutorComponent; import com.android.dialer.common.concurrent.SupportUiListener; import com.android.dialer.constants.ActivityRequestCodes; -import com.android.dialer.duo.DuoComponent; import com.android.dialer.historyitemactions.DividerModule; import com.android.dialer.historyitemactions.HistoryItemActionBottomSheet; import com.android.dialer.historyitemactions.HistoryItemActionModule; @@ -243,16 +242,13 @@ public class SpeedDialFragment extends Fragment { if (channel.technology() == Channel.DUO) { Logger.get(activity) .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT); - Intent intent = - DuoComponent.get(activity).getDuo().getCallIntent(channel.number()).orNull(); - activity.startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO); - return; } PreCall.start( activity, new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL) - .setIsVideoCall(channel.isVideoTechnology())); + .setIsVideoCall(channel.isVideoTechnology()) + .setIsDuoCall(channel.technology() == Channel.DUO)); } @Override @@ -341,15 +337,12 @@ public class SpeedDialFragment extends Fragment { Logger.get(getContext()) .logImpression( DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_SUGGESTED_CONTACT); - Intent intent = - DuoComponent.get(getContext()).getDuo().getCallIntent(channel.number()).orNull(); - getActivity().startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO); - return; } PreCall.start( getContext(), new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL) - .setIsVideoCall(channel.isVideoTechnology())); + .setIsVideoCall(channel.isVideoTechnology()) + .setIsDuoCall(channel.technology() == Channel.DUO)); } private final class StarContactModule implements HistoryItemActionModule { @@ -426,15 +419,12 @@ public class SpeedDialFragment extends Fragment { if (channel.technology() == Channel.DUO) { Logger.get(activity) .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT); - Intent intent = - DuoComponent.get(activity).getDuo().getCallIntent(channel.number()).orNull(); - activity.startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO); - return; } PreCall.start( activity, new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL) - .setIsVideoCall(channel.isVideoTechnology())); + .setIsVideoCall(channel.isVideoTechnology()) + .setIsDuoCall(channel.technology() == Channel.DUO)); } @Override 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; -- cgit v1.2.3 From c0200c4d60cf662f5e6aa422a810646ff02928b8 Mon Sep 17 00:00:00 2001 From: yueg Date: Mon, 7 May 2018 17:13:13 -0700 Subject: Do not show bubble for outgoing call if it's not a background call. Test: ReturnToCallControllerTest PiperOrigin-RevId: 195747611 Change-Id: Ibce7ef45af2f79cc5a35825a2bb38fe268a4681c --- java/com/android/incallui/ReturnToCallController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'java/com/android/incallui') 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"); -- cgit v1.2.3 From 267cdad8f95c541d421292a5675a2e13f81850e0 Mon Sep 17 00:00:00 2001 From: yueg Date: Tue, 8 May 2018 12:09:45 -0700 Subject: Format callback phone number. Test: manual PiperOrigin-RevId: 195856176 Change-Id: I8579afff48e9c07d422505b81d703adc03656435 --- java/com/android/incallui/contactgrid/ContactGridManager.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'java/com/android/incallui') 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); -- cgit v1.2.3 From ebaf6303bab244e8eb930d19f0e61a2660861812 Mon Sep 17 00:00:00 2001 From: Android Dialer Date: Wed, 9 May 2018 10:58:42 -0700 Subject: Hide new after call spam blocking promo behind an additional flag. Test: N/A PiperOrigin-RevId: 195995975 Change-Id: I0311770eecdf36f275d81ba481098259344cbf5b --- java/com/android/dialer/spam/promo/SpamBlockingPromoHelper.java | 9 +++++++++ java/com/android/incallui/spam/SpamNotificationActivity.java | 2 +- java/com/android/incallui/spam/SpamNotificationService.java | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'java/com/android/incallui') diff --git a/java/com/android/dialer/spam/promo/SpamBlockingPromoHelper.java b/java/com/android/dialer/spam/promo/SpamBlockingPromoHelper.java index a117e1908..42fb39f38 100644 --- a/java/com/android/dialer/spam/promo/SpamBlockingPromoHelper.java +++ b/java/com/android/dialer/spam/promo/SpamBlockingPromoHelper.java @@ -42,6 +42,8 @@ public class SpamBlockingPromoHelper { static final String SPAM_BLOCKING_PROMO_PERIOD_MILLIS = "spam_blocking_promo_period_millis"; static final String SPAM_BLOCKING_PROMO_LAST_SHOW_MILLIS = "spam_blocking_promo_last_show_millis"; public static final String ENABLE_SPAM_BLOCKING_PROMO = "enable_spam_blocking_promo"; + public static final String ENABLE_AFTER_CALL_SPAM_BLOCKING_PROMO = + "enable_after_call_spam_blocking_promo"; private final Context context; private final SpamSettings spamSettings; @@ -77,6 +79,13 @@ public class SpamBlockingPromoHelper { return lastShowMillis == 0 || System.currentTimeMillis() - lastShowMillis > showPeriodMillis; } + /* Returns true if we should show a spam blocking promo in after call notification scenario. */ + public boolean shouldShowAfterCallSpamBlockingPromo() { + return shouldShowSpamBlockingPromo() + && ConfigProviderBindings.get(context) + .getBoolean(ENABLE_AFTER_CALL_SPAM_BLOCKING_PROMO, false); + } + /** * Shows a spam blocking promo dialog. * 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, -- cgit v1.2.3 From 270663ce6dcec369f557c368c3e022b94b2cdf60 Mon Sep 17 00:00:00 2001 From: erfanian Date: Wed, 9 May 2018 13:38:18 -0700 Subject: Update answer button logic. Bug: 73774884 Test: unit PiperOrigin-RevId: 196021103 Change-Id: Id2176e6ef4259dc6e1136564051dae14e30175d4 --- .../android/incallui/AnswerScreenPresenter.java | 38 ++++++++++++++++- .../incallui/NotificationBroadcastReceiver.java | 47 +++++++++++++++++++--- .../incallui/speakeasy/SpeakEasyCallManager.java | 8 ++++ .../speakeasy/SpeakEasyCallManagerStub.java | 7 ++++ 4 files changed, 93 insertions(+), 7 deletions(-) (limited to 'java/com/android/incallui') 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 answerPrecondition; + + if (incomingCall != null && inCallActivity != null) { + answerPrecondition = inCallActivity.getSpeakEasyCallManager().onNewIncomingCall(incomingCall); + } else { + answerPrecondition = Futures.immediateFuture(null); + } + + Futures.addCallback( + answerPrecondition, + new FutureCallback() { + @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 answerPrecondition; + + if (speakEasyCallManager != null) { + answerPrecondition = speakEasyCallManager.onNewIncomingCall(call); + } else { + answerPrecondition = Futures.immediateFuture(null); + } + + Futures.addCallback( + answerPrecondition, + new FutureCallback() { + @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/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 { @@ -39,6 +40,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 onNewIncomingCall(@NonNull DialerCall call); + /** * Indicates the feature is available. * 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 onNewIncomingCall(@NonNull DialerCall call) { + return Futures.immediateFuture(null); + } + /** Always returns false. */ @Override public boolean isAvailable(@NonNull Context unused) { -- cgit v1.2.3