diff options
21 files changed, 227 insertions, 338 deletions
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<Duo.IntentType> 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<Intent> 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<String> numbers); + ListenableFuture<ImmutableMap<String, ReachabilityData>> updateReachability( + @NonNull Context context, @NonNull List<String> numbers); /** * Clears the current reachability data and starts a task to load the latest reachability data @@ -95,19 +98,6 @@ public interface Duo { */ Optional<Intent> 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<IntentType> getIntentType(Intent intent); - Optional<Intent> 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. - * - * <p>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. - * - * <p>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<String> numbers) { + public ListenableFuture<ImmutableMap<String, ReachabilityData>> updateReachability( + @NonNull Context context, @NonNull List<String> numbers) { Assert.isMainThread(); Assert.isNotNull(context); Assert.isNotNull(numbers); + return Futures.immediateFuture(ImmutableMap.of()); } @Override @@ -115,11 +120,6 @@ public class DuoStub implements Duo { } @Override - public Optional<IntentType> getIntentType(Intent intent) { - return Optional.absent(); - } - - @Override public Optional<Intent> 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(); - <Output> void listen( - ListenableFuture<Output> future, - Consumer<Output> successListener, + <OutputT> void listen( + ListenableFuture<OutputT> future, + Consumer<OutputT> successListener, Consumer<Throwable> 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<ImmutableMap<String, ReachabilityData>> reachabilities = + DuoComponent.get(coordinator.getActivity()) + .getDuo() + .updateReachability(coordinator.getActivity(), ImmutableList.of(number)); + PendingAction pendingAction = coordinator.startPendingAction(); + + Futures.addCallback( + reachabilities, + new FutureCallback<ImmutableMap<String, ReachabilityData>>() { + @Override + public void onSuccess(ImmutableMap<String, ReachabilityData> 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> 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<PreCallAction> 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; |