1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dialer.precall.impl;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import com.android.dialer.callintent.CallIntentBuilder;
22 import com.android.dialer.common.LogUtil;
23 import com.android.dialer.common.concurrent.Annotations.Ui;
24 import com.android.dialer.duo.Duo.ReachabilityData;
25 import com.android.dialer.duo.DuoComponent;
26 import com.android.dialer.precall.PreCallAction;
27 import com.android.dialer.precall.PreCallCoordinator;
28 import com.android.dialer.precall.PreCallCoordinator.PendingAction;
29 import com.google.common.collect.ImmutableList;
30 import com.google.common.collect.ImmutableMap;
31 import com.google.common.util.concurrent.FutureCallback;
32 import com.google.common.util.concurrent.Futures;
33 import com.google.common.util.concurrent.ListenableFuture;
34 import com.google.common.util.concurrent.ListeningExecutorService;
35 import javax.inject.Inject;
36 
37 /**
38  * Checks if a duo call is actually callable, and request an activity for {@link
39  * android.app.Activity#startActivityForResult(Intent, int)}
40  */
41 public class DuoAction implements PreCallAction {
42 
43   private final ListeningExecutorService uiExecutor;
44 
45   @Inject
DuoAction(@i ListeningExecutorService uiExecutor)46   DuoAction(@Ui ListeningExecutorService uiExecutor) {
47     this.uiExecutor = uiExecutor;
48   }
49 
50   @Override
requiresUi(Context context, CallIntentBuilder builder)51   public boolean requiresUi(Context context, CallIntentBuilder builder) {
52     // Duo call must be started with startActivityForResult() which needs a activity.
53     return builder.isDuoCall();
54   }
55 
56   @Override
runWithoutUi(Context context, CallIntentBuilder builder)57   public void runWithoutUi(Context context, CallIntentBuilder builder) {}
58 
59   @Override
runWithUi(PreCallCoordinator coordinator)60   public void runWithUi(PreCallCoordinator coordinator) {
61     if (!requiresUi(coordinator.getActivity(), coordinator.getBuilder())) {
62       return;
63     }
64     String number = coordinator.getBuilder().getUri().getSchemeSpecificPart();
65     ListenableFuture<ImmutableMap<String, ReachabilityData>> reachabilities =
66         DuoComponent.get(coordinator.getActivity())
67             .getDuo()
68             .updateReachability(coordinator.getActivity(), ImmutableList.of(number));
69     PendingAction pendingAction = coordinator.startPendingAction();
70 
71     Futures.addCallback(
72         reachabilities,
73         new FutureCallback<ImmutableMap<String, ReachabilityData>>() {
74           @Override
75           public void onSuccess(ImmutableMap<String, ReachabilityData> result) {
76             if (!result.containsKey(number) || !result.get(number).videoCallable()) {
77               LogUtil.w(
78                   "DuoAction.runWithUi",
79                   number + " number no longer duo reachable, falling back to carrier video call");
80               coordinator.getBuilder().setIsDuoCall(false);
81             }
82             pendingAction.finish();
83           }
84 
85           @Override
86           public void onFailure(Throwable throwable) {
87             LogUtil.e("DuoAction.runWithUi", "reachability query failed", throwable);
88             coordinator.getBuilder().setIsDuoCall(false);
89             pendingAction.finish();
90           }
91         },
92         uiExecutor);
93   }
94 
95   @Override
onDiscard()96   public void onDiscard() {}
97 }
98