blob: b3fb97fadc148aa81c989b81b5788151bb2bc54f [file] [log] [blame]
Eric Erfanianccca3152017-02-22 16:32:36 -08001/*
2 * Copyright (C) 2013 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 Erfanianccca3152017-02-22 16:32:36 -080020import android.os.Bundle;
Eric Erfanian2ca43182017-08-31 06:57:16 -070021import android.os.Trace;
Eric Erfanianccca3152017-02-22 16:32:36 -080022import android.support.v4.app.Fragment;
23import android.support.v4.os.UserManagerCompat;
24import android.telecom.CallAudioState;
twyen00623aa2017-10-10 12:15:08 -070025import android.telecom.PhoneAccountHandle;
Eric Erfanianccca3152017-02-22 16:32:36 -080026import com.android.contacts.common.compat.CallCompat;
27import com.android.dialer.common.Assert;
28import com.android.dialer.common.LogUtil;
twyen00623aa2017-10-10 12:15:08 -070029import com.android.dialer.common.concurrent.DialerExecutorComponent;
Eric Erfanian8369df02017-05-03 10:27:13 -070030import com.android.dialer.logging.DialerImpression;
Eric Erfanianccca3152017-02-22 16:32:36 -080031import com.android.dialer.logging.Logger;
twyen00623aa2017-10-10 12:15:08 -070032import com.android.dialer.telecom.TelecomUtil;
Eric Erfanianccca3152017-02-22 16:32:36 -080033import com.android.incallui.InCallCameraManager.Listener;
34import com.android.incallui.InCallPresenter.CanAddCallListener;
35import com.android.incallui.InCallPresenter.InCallDetailsListener;
36import com.android.incallui.InCallPresenter.InCallState;
37import com.android.incallui.InCallPresenter.InCallStateListener;
38import com.android.incallui.InCallPresenter.IncomingCallListener;
Eric Erfanian8369df02017-05-03 10:27:13 -070039import com.android.incallui.audiomode.AudioModeProvider;
40import com.android.incallui.audiomode.AudioModeProvider.AudioModeListener;
Eric Erfanianccca3152017-02-22 16:32:36 -080041import com.android.incallui.call.CallList;
42import com.android.incallui.call.DialerCall;
Eric Erfaniand5e47f62017-03-15 14:41:07 -070043import com.android.incallui.call.DialerCall.CameraDirection;
Eric Erfanianccca3152017-02-22 16:32:36 -080044import com.android.incallui.call.TelecomAdapter;
Eric Erfanianccca3152017-02-22 16:32:36 -080045import com.android.incallui.incall.protocol.InCallButtonIds;
46import com.android.incallui.incall.protocol.InCallButtonUi;
47import com.android.incallui.incall.protocol.InCallButtonUiDelegate;
twyen00623aa2017-10-10 12:15:08 -070048import com.android.incallui.multisim.SwapSimWorker;
Eric Erfanian90508232017-03-24 09:31:16 -070049import com.android.incallui.videotech.utils.VideoUtils;
Eric Erfanianccca3152017-02-22 16:32:36 -080050
51/** Logic for call buttons. */
52public class CallButtonPresenter
53 implements InCallStateListener,
54 AudioModeListener,
55 IncomingCallListener,
56 InCallDetailsListener,
57 CanAddCallListener,
58 Listener,
59 InCallButtonUiDelegate {
60
61 private static final String KEY_AUTOMATICALLY_MUTED = "incall_key_automatically_muted";
62 private static final String KEY_PREVIOUS_MUTE_STATE = "incall_key_previous_mute_state";
63
64 private final Context mContext;
65 private InCallButtonUi mInCallButtonUi;
66 private DialerCall mCall;
67 private boolean mAutomaticallyMuted = false;
68 private boolean mPreviousMuteState = false;
69 private boolean isInCallButtonUiReady;
twyen00623aa2017-10-10 12:15:08 -070070 private PhoneAccountHandle mOtherAccount;
Eric Erfanianccca3152017-02-22 16:32:36 -080071
72 public CallButtonPresenter(Context context) {
73 mContext = context.getApplicationContext();
74 }
75
76 @Override
77 public void onInCallButtonUiReady(InCallButtonUi ui) {
78 Assert.checkState(!isInCallButtonUiReady);
79 mInCallButtonUi = ui;
80 AudioModeProvider.getInstance().addListener(this);
81
82 // register for call state changes last
83 final InCallPresenter inCallPresenter = InCallPresenter.getInstance();
84 inCallPresenter.addListener(this);
85 inCallPresenter.addIncomingCallListener(this);
86 inCallPresenter.addDetailsListener(this);
87 inCallPresenter.addCanAddCallListener(this);
88 inCallPresenter.getInCallCameraManager().addCameraSelectionListener(this);
89
90 // Update the buttons state immediately for the current call
91 onStateChange(InCallState.NO_CALLS, inCallPresenter.getInCallState(), CallList.getInstance());
92 isInCallButtonUiReady = true;
93 }
94
95 @Override
96 public void onInCallButtonUiUnready() {
97 Assert.checkState(isInCallButtonUiReady);
98 mInCallButtonUi = null;
99 InCallPresenter.getInstance().removeListener(this);
100 AudioModeProvider.getInstance().removeListener(this);
101 InCallPresenter.getInstance().removeIncomingCallListener(this);
102 InCallPresenter.getInstance().removeDetailsListener(this);
103 InCallPresenter.getInstance().getInCallCameraManager().removeCameraSelectionListener(this);
104 InCallPresenter.getInstance().removeCanAddCallListener(this);
105 isInCallButtonUiReady = false;
106 }
107
108 @Override
109 public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700110 Trace.beginSection("CallButtonPresenter.onStateChange");
Eric Erfanianccca3152017-02-22 16:32:36 -0800111 if (newState == InCallState.OUTGOING) {
112 mCall = callList.getOutgoingCall();
113 } else if (newState == InCallState.INCALL) {
114 mCall = callList.getActiveOrBackgroundCall();
115
116 // When connected to voice mail, automatically shows the dialpad.
117 // (On previous releases we showed it when in-call shows up, before waiting for
118 // OUTGOING. We may want to do that once we start showing "Voice mail" label on
119 // the dialpad too.)
120 if (oldState == InCallState.OUTGOING && mCall != null) {
121 if (CallerInfoUtils.isVoiceMailNumber(mContext, mCall) && getActivity() != null) {
122 getActivity().showDialpadFragment(true /* show */, true /* animate */);
123 }
124 }
125 } else if (newState == InCallState.INCOMING) {
126 if (getActivity() != null) {
127 getActivity().showDialpadFragment(false /* show */, true /* animate */);
128 }
129 mCall = callList.getIncomingCall();
130 } else {
131 mCall = null;
132 }
133 updateUi(newState, mCall);
Eric Erfanian2ca43182017-08-31 06:57:16 -0700134 Trace.endSection();
Eric Erfanianccca3152017-02-22 16:32:36 -0800135 }
136
137 /**
138 * Updates the user interface in response to a change in the details of a call. Currently handles
139 * changes to the call buttons in response to a change in the details for a call. This is
140 * important to ensure changes to the active call are reflected in the available buttons.
141 *
142 * @param call The active call.
143 * @param details The call details.
144 */
145 @Override
146 public void onDetailsChanged(DialerCall call, android.telecom.Call.Details details) {
147 // Only update if the changes are for the currently active call
148 if (mInCallButtonUi != null && call != null && call.equals(mCall)) {
149 updateButtonsState(call);
150 }
151 }
152
153 @Override
154 public void onIncomingCall(InCallState oldState, InCallState newState, DialerCall call) {
155 onStateChange(oldState, newState, CallList.getInstance());
156 }
157
158 @Override
159 public void onCanAddCallChanged(boolean canAddCall) {
160 if (mInCallButtonUi != null && mCall != null) {
161 updateButtonsState(mCall);
162 }
163 }
164
165 @Override
166 public void onAudioStateChanged(CallAudioState audioState) {
167 if (mInCallButtonUi != null) {
168 mInCallButtonUi.setAudioState(audioState);
169 }
170 }
171
172 @Override
173 public CallAudioState getCurrentAudioState() {
174 return AudioModeProvider.getInstance().getAudioState();
175 }
176
177 @Override
178 public void setAudioRoute(int route) {
179 LogUtil.i(
180 "CallButtonPresenter.setAudioRoute",
181 "sending new audio route: " + CallAudioState.audioRouteToString(route));
182 TelecomAdapter.getInstance().setAudioRoute(route);
183 }
184
185 /** Function assumes that bluetooth is not supported. */
186 @Override
187 public void toggleSpeakerphone() {
188 // This function should not be called if bluetooth is available.
189 CallAudioState audioState = getCurrentAudioState();
190 if (0 != (CallAudioState.ROUTE_BLUETOOTH & audioState.getSupportedRouteMask())) {
191 // It's clear the UI is wrong, so update the supported mode once again.
192 LogUtil.e(
193 "CallButtonPresenter", "toggling speakerphone not allowed when bluetooth supported.");
194 mInCallButtonUi.setAudioState(audioState);
195 return;
196 }
197
198 int newRoute;
199 if (audioState.getRoute() == CallAudioState.ROUTE_SPEAKER) {
200 newRoute = CallAudioState.ROUTE_WIRED_OR_EARPIECE;
201 Logger.get(mContext)
202 .logCallImpression(
203 DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_WIRED_OR_EARPIECE,
204 mCall.getUniqueCallId(),
205 mCall.getTimeAddedMs());
206 } else {
207 newRoute = CallAudioState.ROUTE_SPEAKER;
208 Logger.get(mContext)
209 .logCallImpression(
210 DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_SPEAKERPHONE,
211 mCall.getUniqueCallId(),
212 mCall.getTimeAddedMs());
213 }
214
215 setAudioRoute(newRoute);
216 }
217
218 @Override
Eric Erfanian9a090c82017-03-16 19:22:24 -0700219 public void muteClicked(boolean checked, boolean clickedByUser) {
220 LogUtil.i(
221 "CallButtonPresenter", "turning on mute: %s, clicked by user: %s", checked, clickedByUser);
222 if (clickedByUser) {
223 Logger.get(mContext)
224 .logCallImpression(
225 checked
226 ? DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_MUTE
227 : DialerImpression.Type.IN_CALL_SCREEN_TURN_OFF_MUTE,
228 mCall.getUniqueCallId(),
229 mCall.getTimeAddedMs());
230 }
Eric Erfanianccca3152017-02-22 16:32:36 -0800231 TelecomAdapter.getInstance().mute(checked);
232 }
233
234 @Override
235 public void holdClicked(boolean checked) {
236 if (mCall == null) {
237 return;
238 }
239 if (checked) {
240 LogUtil.i("CallButtonPresenter", "putting the call on hold: " + mCall);
241 mCall.hold();
242 } else {
243 LogUtil.i("CallButtonPresenter", "removing the call from hold: " + mCall);
244 mCall.unhold();
245 }
246 }
247
248 @Override
249 public void swapClicked() {
250 if (mCall == null) {
251 return;
252 }
253
254 LogUtil.i("CallButtonPresenter", "swapping the call: " + mCall);
255 TelecomAdapter.getInstance().swap(mCall.getId());
256 }
257
258 @Override
259 public void mergeClicked() {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700260 Logger.get(mContext)
261 .logCallImpression(
262 DialerImpression.Type.IN_CALL_MERGE_BUTTON_PRESSED,
263 mCall.getUniqueCallId(),
264 mCall.getTimeAddedMs());
Eric Erfanianccca3152017-02-22 16:32:36 -0800265 TelecomAdapter.getInstance().merge(mCall.getId());
266 }
267
268 @Override
269 public void addCallClicked() {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700270 Logger.get(mContext)
271 .logCallImpression(
272 DialerImpression.Type.IN_CALL_ADD_CALL_BUTTON_PRESSED,
273 mCall.getUniqueCallId(),
274 mCall.getTimeAddedMs());
Eric Erfanianccca3152017-02-22 16:32:36 -0800275 // Automatically mute the current call
276 mAutomaticallyMuted = true;
277 mPreviousMuteState = AudioModeProvider.getInstance().getAudioState().isMuted();
278 // Simulate a click on the mute button
Eric Erfanian9a090c82017-03-16 19:22:24 -0700279 muteClicked(true /* checked */, false /* clickedByUser */);
Eric Erfanianccca3152017-02-22 16:32:36 -0800280 TelecomAdapter.getInstance().addCall();
281 }
282
283 @Override
284 public void showDialpadClicked(boolean checked) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700285 Logger.get(mContext)
286 .logCallImpression(
287 DialerImpression.Type.IN_CALL_SHOW_DIALPAD_BUTTON_PRESSED,
288 mCall.getUniqueCallId(),
289 mCall.getTimeAddedMs());
Eric Erfanianccca3152017-02-22 16:32:36 -0800290 LogUtil.v("CallButtonPresenter", "show dialpad " + String.valueOf(checked));
291 getActivity().showDialpadFragment(checked /* show */, true /* animate */);
292 }
293
294 @Override
295 public void changeToVideoClicked() {
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700296 LogUtil.enterBlock("CallButtonPresenter.changeToVideoClicked");
Eric Erfanian8369df02017-05-03 10:27:13 -0700297 Logger.get(mContext)
298 .logCallImpression(
299 DialerImpression.Type.VIDEO_CALL_UPGRADE_REQUESTED,
300 mCall.getUniqueCallId(),
301 mCall.getTimeAddedMs());
twyen59209802017-09-13 10:37:01 -0700302 mCall.getVideoTech().upgradeToVideo(mContext);
Eric Erfanianccca3152017-02-22 16:32:36 -0800303 }
304
305 @Override
306 public void onEndCallClicked() {
307 LogUtil.i("CallButtonPresenter.onEndCallClicked", "call: " + mCall);
308 if (mCall != null) {
309 mCall.disconnect();
310 }
311 }
312
313 @Override
314 public void showAudioRouteSelector() {
315 mInCallButtonUi.showAudioRouteSelector();
316 }
317
twyen00623aa2017-10-10 12:15:08 -0700318 @Override
319 public void swapSimClicked() {
320 LogUtil.enterBlock("CallButtonPresenter.swapSimClicked");
321 SwapSimWorker worker =
322 new SwapSimWorker(
323 getContext(),
324 mCall,
325 InCallPresenter.getInstance().getCallList(),
326 mOtherAccount,
327 InCallPresenter.getInstance().acquireInCallUiLock("swapSim"));
328 DialerExecutorComponent.get(getContext())
329 .dialerExecutorFactory()
330 .createNonUiTaskBuilder(worker)
331 .build()
332 .executeParallel(null);
333 }
334
Eric Erfanianccca3152017-02-22 16:32:36 -0800335 /**
336 * Switches the camera between the front-facing and back-facing camera.
337 *
338 * @param useFrontFacingCamera True if we should switch to using the front-facing camera, or false
339 * if we should switch to using the back-facing camera.
340 */
341 @Override
342 public void switchCameraClicked(boolean useFrontFacingCamera) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700343 updateCamera(useFrontFacingCamera);
Eric Erfanianccca3152017-02-22 16:32:36 -0800344 }
345
346 @Override
347 public void toggleCameraClicked() {
348 LogUtil.i("CallButtonPresenter.toggleCameraClicked", "");
Eric Erfanian2ca43182017-08-31 06:57:16 -0700349 if (mCall == null) {
350 return;
351 }
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700352 Logger.get(mContext)
353 .logCallImpression(
354 DialerImpression.Type.IN_CALL_SCREEN_SWAP_CAMERA,
355 mCall.getUniqueCallId(),
356 mCall.getTimeAddedMs());
Eric Erfanianccca3152017-02-22 16:32:36 -0800357 switchCameraClicked(
358 !InCallPresenter.getInstance().getInCallCameraManager().isUsingFrontFacingCamera());
359 }
360
361 /**
362 * Stop or start client's video transmission.
363 *
364 * @param pause True if pausing the local user's video, or false if starting the local user's
365 * video.
366 */
367 @Override
368 public void pauseVideoClicked(boolean pause) {
369 LogUtil.i("CallButtonPresenter.pauseVideoClicked", "%s", pause ? "pause" : "unpause");
Eric Erfanianccca3152017-02-22 16:32:36 -0800370
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700371 Logger.get(mContext)
372 .logCallImpression(
373 pause
374 ? DialerImpression.Type.IN_CALL_SCREEN_TURN_OFF_VIDEO
375 : DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_VIDEO,
376 mCall.getUniqueCallId(),
377 mCall.getTimeAddedMs());
378
Eric Erfanianccca3152017-02-22 16:32:36 -0800379 if (pause) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700380 mCall.getVideoTech().setCamera(null);
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700381 mCall.getVideoTech().stopTransmission();
Eric Erfanianccca3152017-02-22 16:32:36 -0800382 } else {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700383 updateCamera(
384 InCallPresenter.getInstance().getInCallCameraManager().isUsingFrontFacingCamera());
twyen59209802017-09-13 10:37:01 -0700385 mCall.getVideoTech().resumeTransmission(mContext);
Eric Erfanianccca3152017-02-22 16:32:36 -0800386 }
387
388 mInCallButtonUi.setVideoPaused(pause);
389 mInCallButtonUi.enableButton(InCallButtonIds.BUTTON_PAUSE_VIDEO, false);
390 }
391
Eric Erfanian2ca43182017-08-31 06:57:16 -0700392 private void updateCamera(boolean useFrontFacingCamera) {
393 InCallCameraManager cameraManager = InCallPresenter.getInstance().getInCallCameraManager();
394 cameraManager.setUseFrontFacingCamera(useFrontFacingCamera);
395
396 String cameraId = cameraManager.getActiveCameraId();
397 if (cameraId != null) {
398 final int cameraDir =
399 cameraManager.isUsingFrontFacingCamera()
400 ? CameraDirection.CAMERA_DIRECTION_FRONT_FACING
401 : CameraDirection.CAMERA_DIRECTION_BACK_FACING;
402 mCall.setCameraDir(cameraDir);
403 mCall.getVideoTech().setCamera(cameraId);
404 }
405 }
406
Eric Erfanianccca3152017-02-22 16:32:36 -0800407 private void updateUi(InCallState state, DialerCall call) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700408 LogUtil.v("CallButtonPresenter", "updating call UI for call: %s", call);
Eric Erfanianccca3152017-02-22 16:32:36 -0800409
410 if (mInCallButtonUi == null) {
411 return;
412 }
413
414 if (call != null) {
415 mInCallButtonUi.updateInCallButtonUiColors();
416 }
417
418 final boolean isEnabled =
419 state.isConnectingOrConnected() && !state.isIncoming() && call != null;
420 mInCallButtonUi.setEnabled(isEnabled);
421
422 if (call == null) {
423 return;
424 }
425
426 updateButtonsState(call);
427 }
428
429 /**
430 * Updates the buttons applicable for the UI.
431 *
432 * @param call The active call.
433 */
twyen00623aa2017-10-10 12:15:08 -0700434 @SuppressWarnings("MissingPermission")
Eric Erfanianccca3152017-02-22 16:32:36 -0800435 private void updateButtonsState(DialerCall call) {
436 LogUtil.v("CallButtonPresenter.updateButtonsState", "");
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700437 final boolean isVideo = call.isVideoCall();
Eric Erfanianccca3152017-02-22 16:32:36 -0800438
439 // Common functionality (audio, hold, etc).
440 // Show either HOLD or SWAP, but not both. If neither HOLD or SWAP is available:
441 // (1) If the device normally can hold, show HOLD in a disabled state.
442 // (2) If the device doesn't have the concept of hold/swap, remove the button.
443 final boolean showSwap = call.can(android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE);
444 final boolean showHold =
445 !showSwap
446 && call.can(android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD)
447 && call.can(android.telecom.Call.Details.CAPABILITY_HOLD);
448 final boolean isCallOnHold = call.getState() == DialerCall.State.ONHOLD;
449
450 final boolean showAddCall =
451 TelecomAdapter.getInstance().canAddCall() && UserManagerCompat.isUserUnlocked(mContext);
452 final boolean showMerge = call.can(android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE);
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700453 final boolean showUpgradeToVideo = !isVideo && (hasVideoCallCapabilities(call));
Eric Erfanianccca3152017-02-22 16:32:36 -0800454 final boolean showDowngradeToAudio = isVideo && isDowngradeToAudioSupported(call);
455 final boolean showMute = call.can(android.telecom.Call.Details.CAPABILITY_MUTE);
456
457 final boolean hasCameraPermission =
Eric Erfanian2ca43182017-08-31 06:57:16 -0700458 isVideo && VideoUtils.hasCameraPermissionAndShownPrivacyToast(mContext);
Eric Erfanianccca3152017-02-22 16:32:36 -0800459 // Disabling local video doesn't seem to work when dialing. See b/30256571.
460 final boolean showPauseVideo =
461 isVideo
462 && call.getState() != DialerCall.State.DIALING
463 && call.getState() != DialerCall.State.CONNECTING;
464
twyen00623aa2017-10-10 12:15:08 -0700465 mOtherAccount = TelecomUtil.getOtherAccount(getContext(), call.getAccountHandle());
466 boolean showSwapSim = mOtherAccount != null && DialerCall.State.isDialing(call.getState());
467
Eric Erfanianccca3152017-02-22 16:32:36 -0800468 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_AUDIO, true);
469 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_SWAP, showSwap);
470 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_HOLD, showHold);
471 mInCallButtonUi.setHold(isCallOnHold);
472 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_MUTE, showMute);
twyen00623aa2017-10-10 12:15:08 -0700473 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_SWAP_SIM, showSwapSim);
Eric Erfanianccca3152017-02-22 16:32:36 -0800474 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_ADD_CALL, true);
475 mInCallButtonUi.enableButton(InCallButtonIds.BUTTON_ADD_CALL, showAddCall);
476 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO, showUpgradeToVideo);
477 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_DOWNGRADE_TO_AUDIO, showDowngradeToAudio);
478 mInCallButtonUi.showButton(
479 InCallButtonIds.BUTTON_SWITCH_CAMERA, isVideo && hasCameraPermission);
480 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_PAUSE_VIDEO, showPauseVideo);
481 if (isVideo) {
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700482 mInCallButtonUi.setVideoPaused(!call.getVideoTech().isTransmitting() || !hasCameraPermission);
Eric Erfanianccca3152017-02-22 16:32:36 -0800483 }
484 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_DIALPAD, true);
485 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_MERGE, showMerge);
486
487 mInCallButtonUi.updateButtonStates();
488 }
489
490 private boolean hasVideoCallCapabilities(DialerCall call) {
Eric Erfaniand8046e52017-04-06 09:41:50 -0700491 return call.getVideoTech().isAvailable(mContext);
Eric Erfanianccca3152017-02-22 16:32:36 -0800492 }
493
494 /**
495 * Determines if downgrading from a video call to an audio-only call is supported. In order to
496 * support downgrade to audio, the SDK version must be >= N and the call should NOT have the
497 * {@link android.telecom.Call.Details#CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO}.
498 *
499 * @param call The call.
500 * @return {@code true} if downgrading to an audio-only call from a video call is supported.
501 */
502 private boolean isDowngradeToAudioSupported(DialerCall call) {
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700503 // TODO(b/33676907): If there is an RCS video share session, return true here
Eric Erfanianccca3152017-02-22 16:32:36 -0800504 return !call.can(CallCompat.Details.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO);
505 }
506
507 @Override
508 public void refreshMuteState() {
509 // Restore the previous mute state
510 if (mAutomaticallyMuted
511 && AudioModeProvider.getInstance().getAudioState().isMuted() != mPreviousMuteState) {
512 if (mInCallButtonUi == null) {
513 return;
514 }
Eric Erfanian9a090c82017-03-16 19:22:24 -0700515 muteClicked(mPreviousMuteState, false /* clickedByUser */);
Eric Erfanianccca3152017-02-22 16:32:36 -0800516 }
517 mAutomaticallyMuted = false;
518 }
519
520 @Override
521 public void onSaveInstanceState(Bundle outState) {
522 outState.putBoolean(KEY_AUTOMATICALLY_MUTED, mAutomaticallyMuted);
523 outState.putBoolean(KEY_PREVIOUS_MUTE_STATE, mPreviousMuteState);
524 }
525
526 @Override
527 public void onRestoreInstanceState(Bundle savedInstanceState) {
528 mAutomaticallyMuted =
529 savedInstanceState.getBoolean(KEY_AUTOMATICALLY_MUTED, mAutomaticallyMuted);
530 mPreviousMuteState = savedInstanceState.getBoolean(KEY_PREVIOUS_MUTE_STATE, mPreviousMuteState);
531 }
532
533 @Override
534 public void onCameraPermissionGranted() {
535 if (mCall != null) {
536 updateButtonsState(mCall);
537 }
538 }
539
540 @Override
541 public void onActiveCameraSelectionChanged(boolean isUsingFrontFacingCamera) {
542 if (mInCallButtonUi == null) {
543 return;
544 }
545 mInCallButtonUi.setCameraSwitched(!isUsingFrontFacingCamera);
546 }
547
548 @Override
549 public Context getContext() {
550 return mContext;
551 }
552
553 private InCallActivity getActivity() {
554 if (mInCallButtonUi != null) {
555 Fragment fragment = mInCallButtonUi.getInCallButtonUiFragment();
556 if (fragment != null) {
557 return (InCallActivity) fragment.getActivity();
558 }
559 }
560 return null;
561 }
twyen00623aa2017-10-10 12:15:08 -0700562
Eric Erfanianccca3152017-02-22 16:32:36 -0800563}