blob: 35290dee94ec6a6fc91083f618f1cc3374e5c57c [file] [log] [blame]
Eric Erfanianccca3152017-02-22 16:32:36 -08001/*
2 * Copyright (C) 2016 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
17package com.android.incallui;
18
19import android.content.Context;
Eric Erfanian2ca43182017-08-31 06:57:16 -070020import android.os.SystemClock;
Eric Erfanianccca3152017-02-22 16:32:36 -080021import android.support.annotation.NonNull;
22import android.support.v4.os.UserManagerCompat;
Eric Erfaniand5e47f62017-03-15 14:41:07 -070023import android.telecom.VideoProfile;
Eric Erfanianccca3152017-02-22 16:32:36 -080024import com.android.dialer.common.Assert;
25import com.android.dialer.common.LogUtil;
erfanian270663c2018-05-09 13:38:18 -070026import com.android.dialer.common.concurrent.DialerExecutorComponent;
Eric Erfanian2ca43182017-08-31 06:57:16 -070027import com.android.dialer.common.concurrent.ThreadUtil;
Eric Erfanian8369df02017-05-03 10:27:13 -070028import com.android.dialer.logging.DialerImpression;
29import com.android.dialer.logging.Logger;
Eric Erfanianccca3152017-02-22 16:32:36 -080030import com.android.incallui.answer.protocol.AnswerScreen;
31import com.android.incallui.answer.protocol.AnswerScreenDelegate;
32import com.android.incallui.answerproximitysensor.AnswerProximitySensor;
33import com.android.incallui.answerproximitysensor.PseudoScreenState;
Eric Erfanian90508232017-03-24 09:31:16 -070034import com.android.incallui.call.CallList;
Eric Erfanianccca3152017-02-22 16:32:36 -080035import com.android.incallui.call.DialerCall;
Eric Erfanian90508232017-03-24 09:31:16 -070036import com.android.incallui.call.DialerCallListener;
twyen8efb4952017-10-06 16:35:54 -070037import com.android.incallui.incalluilock.InCallUiLock;
erfanian270663c2018-05-09 13:38:18 -070038import com.google.common.util.concurrent.FutureCallback;
39import com.google.common.util.concurrent.Futures;
40import com.google.common.util.concurrent.ListenableFuture;
Eric Erfanianccca3152017-02-22 16:32:36 -080041
42/** Manages changes for an incoming call screen. */
43public class AnswerScreenPresenter
44 implements AnswerScreenDelegate, DialerCall.CannedTextResponsesLoadedListener {
Eric Erfanian2ca43182017-08-31 06:57:16 -070045 private static final int ACCEPT_REJECT_CALL_TIME_OUT_IN_MILLIS = 5000;
46
Eric Erfanianccca3152017-02-22 16:32:36 -080047 @NonNull private final Context context;
48 @NonNull private final AnswerScreen answerScreen;
49 @NonNull private final DialerCall call;
Eric Erfanian2ca43182017-08-31 06:57:16 -070050 private long actionPerformedTimeMillis;
Eric Erfanianccca3152017-02-22 16:32:36 -080051
Eric Erfanian2ca43182017-08-31 06:57:16 -070052 AnswerScreenPresenter(
Eric Erfanianccca3152017-02-22 16:32:36 -080053 @NonNull Context context, @NonNull AnswerScreen answerScreen, @NonNull DialerCall call) {
54 LogUtil.i("AnswerScreenPresenter.constructor", null);
55 this.context = Assert.isNotNull(context);
56 this.answerScreen = Assert.isNotNull(answerScreen);
57 this.call = Assert.isNotNull(call);
58 if (isSmsResponseAllowed(call)) {
59 answerScreen.setTextResponses(call.getCannedSmsResponses());
60 }
61 call.addCannedTextResponsesLoadedListener(this);
62
63 PseudoScreenState pseudoScreenState = InCallPresenter.getInstance().getPseudoScreenState();
64 if (AnswerProximitySensor.shouldUse(context, call)) {
65 new AnswerProximitySensor(context, call, pseudoScreenState);
66 } else {
67 pseudoScreenState.setOn(true);
68 }
69 }
70
71 @Override
Eric Erfanian2ca43182017-08-31 06:57:16 -070072 public boolean isActionTimeout() {
73 return actionPerformedTimeMillis != 0
74 && SystemClock.elapsedRealtime() - actionPerformedTimeMillis
75 >= ACCEPT_REJECT_CALL_TIME_OUT_IN_MILLIS;
76 }
77
78 @Override
twyen8efb4952017-10-06 16:35:54 -070079 public InCallUiLock acquireInCallUiLock(String tag) {
80 return InCallPresenter.getInstance().acquireInCallUiLock(tag);
81 }
82
83 @Override
Eric Erfanianccca3152017-02-22 16:32:36 -080084 public void onAnswerScreenUnready() {
85 call.removeCannedTextResponsesLoadedListener(this);
86 }
87
88 @Override
Eric Erfanianccca3152017-02-22 16:32:36 -080089 public void onRejectCallWithMessage(String message) {
90 call.reject(true /* rejectWithMessage */, message);
Eric Erfanian2ca43182017-08-31 06:57:16 -070091 addTimeoutCheck();
Eric Erfanianccca3152017-02-22 16:32:36 -080092 }
93
94 @Override
Eric Erfaniand5e47f62017-03-15 14:41:07 -070095 public void onAnswer(boolean answerVideoAsAudio) {
erfanian270663c2018-05-09 13:38:18 -070096
97 DialerCall incomingCall = CallList.getInstance().getIncomingCall();
98 InCallActivity inCallActivity =
99 (InCallActivity) answerScreen.getAnswerScreenFragment().getActivity();
100 ListenableFuture<Void> answerPrecondition;
101
102 if (incomingCall != null && inCallActivity != null) {
103 answerPrecondition = inCallActivity.getSpeakEasyCallManager().onNewIncomingCall(incomingCall);
104 } else {
105 answerPrecondition = Futures.immediateFuture(null);
106 }
107
108 Futures.addCallback(
109 answerPrecondition,
110 new FutureCallback<Void>() {
111 @Override
112 public void onSuccess(Void result) {
113 onAnswerCallback(answerVideoAsAudio);
114 }
115
116 @Override
117 public void onFailure(Throwable t) {
118 onAnswerCallback(answerVideoAsAudio);
119 // TODO(erfanian): Enumerate all error states and specify recovery strategies.
120 throw new RuntimeException("Failed to successfully complete pre call tasks.", t);
121 }
122 },
123 DialerExecutorComponent.get(context).uiExecutor());
124 addTimeoutCheck();
125 }
126
127 private void onAnswerCallback(boolean answerVideoAsAudio) {
128
Eric Erfanianccca3152017-02-22 16:32:36 -0800129 if (answerScreen.isVideoUpgradeRequest()) {
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700130 if (answerVideoAsAudio) {
Eric Erfanian8369df02017-05-03 10:27:13 -0700131 Logger.get(context)
132 .logCallImpression(
133 DialerImpression.Type.VIDEO_CALL_REQUEST_ACCEPTED_AS_AUDIO,
134 call.getUniqueCallId(),
135 call.getTimeAddedMs());
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700136 call.getVideoTech().acceptVideoRequestAsAudio();
137 } else {
Eric Erfanian8369df02017-05-03 10:27:13 -0700138 Logger.get(context)
139 .logCallImpression(
140 DialerImpression.Type.VIDEO_CALL_REQUEST_ACCEPTED,
141 call.getUniqueCallId(),
142 call.getTimeAddedMs());
twyen59209802017-09-13 10:37:01 -0700143 call.getVideoTech().acceptVideoRequest(context);
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700144 }
Eric Erfanianccca3152017-02-22 16:32:36 -0800145 } else {
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700146 if (answerVideoAsAudio) {
147 call.answer(VideoProfile.STATE_AUDIO_ONLY);
148 } else {
149 call.answer();
150 }
Eric Erfanianccca3152017-02-22 16:32:36 -0800151 }
152 }
153
154 @Override
155 public void onReject() {
156 if (answerScreen.isVideoUpgradeRequest()) {
Eric Erfanian8369df02017-05-03 10:27:13 -0700157 Logger.get(context)
158 .logCallImpression(
159 DialerImpression.Type.VIDEO_CALL_REQUEST_DECLINED,
160 call.getUniqueCallId(),
161 call.getTimeAddedMs());
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700162 call.getVideoTech().declineVideoRequest();
Eric Erfanianccca3152017-02-22 16:32:36 -0800163 } else {
164 call.reject(false /* rejectWithMessage */, null);
165 }
Eric Erfanian2ca43182017-08-31 06:57:16 -0700166 addTimeoutCheck();
Eric Erfanianccca3152017-02-22 16:32:36 -0800167 }
168
169 @Override
erfaniand05d8992018-03-20 19:42:26 -0700170 public void onSpeakEasyCall() {
171 LogUtil.enterBlock("AnswerScreenPresenter.onSpeakEasyCall");
172 DialerCall incomingCall = CallList.getInstance().getIncomingCall();
173 if (incomingCall == null) {
174 LogUtil.i("AnswerScreenPresenter.onSpeakEasyCall", "incomingCall == null");
175 return;
176 }
177 incomingCall.setIsSpeakEasyCall(true);
erfaniand05d8992018-03-20 19:42:26 -0700178 }
179
180 @Override
Eric Erfanian90508232017-03-24 09:31:16 -0700181 public void onAnswerAndReleaseCall() {
Eric Erfaniand8046e52017-04-06 09:41:50 -0700182 LogUtil.enterBlock("AnswerScreenPresenter.onAnswerAndReleaseCall");
Eric Erfanian90508232017-03-24 09:31:16 -0700183 DialerCall activeCall = CallList.getInstance().getActiveCall();
184 if (activeCall == null) {
Eric Erfaniand8046e52017-04-06 09:41:50 -0700185 LogUtil.i("AnswerScreenPresenter.onAnswerAndReleaseCall", "activeCall == null");
Eric Erfanian90508232017-03-24 09:31:16 -0700186 onAnswer(false);
187 } else {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700188 activeCall.setReleasedByAnsweringSecondCall(true);
Eric Erfanian90508232017-03-24 09:31:16 -0700189 activeCall.addListener(new AnswerOnDisconnected(activeCall));
190 activeCall.disconnect();
191 }
Eric Erfanian2ca43182017-08-31 06:57:16 -0700192 addTimeoutCheck();
193 }
194
195 @Override
196 public void onAnswerAndReleaseButtonDisabled() {
197 DialerCall activeCall = CallList.getInstance().getActiveCall();
198 if (activeCall != null) {
199 activeCall.increaseSecondCallWithoutAnswerAndReleasedButtonTimes();
200 }
201 }
202
203 @Override
204 public void onAnswerAndReleaseButtonEnabled() {
205 DialerCall activeCall = CallList.getInstance().getActiveCall();
206 if (activeCall != null) {
207 activeCall.increaseAnswerAndReleaseButtonDisplayedTimes();
208 }
Eric Erfanian90508232017-03-24 09:31:16 -0700209 }
210
211 @Override
Eric Erfanianccca3152017-02-22 16:32:36 -0800212 public void onCannedTextResponsesLoaded(DialerCall call) {
213 if (isSmsResponseAllowed(call)) {
214 answerScreen.setTextResponses(call.getCannedSmsResponses());
215 }
216 }
217
Eric Erfanian90508232017-03-24 09:31:16 -0700218 private class AnswerOnDisconnected implements DialerCallListener {
219
220 private final DialerCall disconnectingCall;
221
Eric Erfanian2ca43182017-08-31 06:57:16 -0700222 AnswerOnDisconnected(DialerCall disconnectingCall) {
Eric Erfanian90508232017-03-24 09:31:16 -0700223 this.disconnectingCall = disconnectingCall;
224 }
225
226 @Override
227 public void onDialerCallDisconnect() {
Eric Erfaniand8046e52017-04-06 09:41:50 -0700228 LogUtil.i(
229 "AnswerScreenPresenter.AnswerOnDisconnected", "call disconnected, answering new call");
Eric Erfanian90508232017-03-24 09:31:16 -0700230 call.answer();
231 disconnectingCall.removeListener(this);
232 }
233
234 @Override
235 public void onDialerCallUpdate() {}
236
237 @Override
238 public void onDialerCallChildNumberChange() {}
239
240 @Override
241 public void onDialerCallLastForwardedNumberChange() {}
242
243 @Override
244 public void onDialerCallUpgradeToVideo() {}
245
246 @Override
247 public void onDialerCallSessionModificationStateChange() {}
248
249 @Override
250 public void onWiFiToLteHandover() {}
251
252 @Override
253 public void onHandoverToWifiFailure() {}
Eric Erfanianc857f902017-05-15 14:05:33 -0700254
255 @Override
256 public void onInternationalCallOnWifi() {}
Eric Erfanian2ca43182017-08-31 06:57:16 -0700257
258 @Override
259 public void onEnrichedCallSessionUpdate() {}
Eric Erfanian90508232017-03-24 09:31:16 -0700260 }
261
Eric Erfanianccca3152017-02-22 16:32:36 -0800262 private boolean isSmsResponseAllowed(DialerCall call) {
263 return UserManagerCompat.isUserUnlocked(context)
264 && call.can(android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT);
265 }
Eric Erfanian2ca43182017-08-31 06:57:16 -0700266
267 private void addTimeoutCheck() {
268 actionPerformedTimeMillis = SystemClock.elapsedRealtime();
269 if (answerScreen.getAnswerScreenFragment().isVisible()) {
270 ThreadUtil.postDelayedOnUiThread(
271 () -> {
272 if (!answerScreen.getAnswerScreenFragment().isVisible()) {
273 LogUtil.d(
274 "AnswerScreenPresenter.addTimeoutCheck",
275 "accept/reject call timed out, do nothing");
276 return;
277 }
278 LogUtil.i("AnswerScreenPresenter.addTimeoutCheck", "accept/reject call timed out");
279 // Force re-evaluate which fragment to show.
280 InCallPresenter.getInstance().refreshUi();
281 },
282 ACCEPT_REJECT_CALL_TIME_OUT_IN_MILLIS);
283 }
284 }
Eric Erfanianccca3152017-02-22 16:32:36 -0800285}