blob: 658ae649b5ed91f8f473dcd45a556af68a716b3f [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;
Eric Erfanianccca3152017-02-22 16:32:36 -080025import com.android.contacts.common.compat.CallCompat;
26import com.android.dialer.common.Assert;
27import com.android.dialer.common.LogUtil;
Eric Erfanian8369df02017-05-03 10:27:13 -070028import com.android.dialer.logging.DialerImpression;
Eric Erfanianccca3152017-02-22 16:32:36 -080029import com.android.dialer.logging.Logger;
Eric Erfanianccca3152017-02-22 16:32:36 -080030import com.android.incallui.InCallCameraManager.Listener;
31import com.android.incallui.InCallPresenter.CanAddCallListener;
32import com.android.incallui.InCallPresenter.InCallDetailsListener;
33import com.android.incallui.InCallPresenter.InCallState;
34import com.android.incallui.InCallPresenter.InCallStateListener;
35import com.android.incallui.InCallPresenter.IncomingCallListener;
Eric Erfanian8369df02017-05-03 10:27:13 -070036import com.android.incallui.audiomode.AudioModeProvider;
37import com.android.incallui.audiomode.AudioModeProvider.AudioModeListener;
Eric Erfanianccca3152017-02-22 16:32:36 -080038import com.android.incallui.call.CallList;
39import com.android.incallui.call.DialerCall;
Eric Erfaniand5e47f62017-03-15 14:41:07 -070040import com.android.incallui.call.DialerCall.CameraDirection;
Eric Erfanianccca3152017-02-22 16:32:36 -080041import com.android.incallui.call.TelecomAdapter;
Eric Erfanianccca3152017-02-22 16:32:36 -080042import com.android.incallui.incall.protocol.InCallButtonIds;
43import com.android.incallui.incall.protocol.InCallButtonUi;
44import com.android.incallui.incall.protocol.InCallButtonUiDelegate;
Eric Erfanian90508232017-03-24 09:31:16 -070045import com.android.incallui.videotech.utils.VideoUtils;
Eric Erfanianccca3152017-02-22 16:32:36 -080046
47/** Logic for call buttons. */
48public class CallButtonPresenter
49 implements InCallStateListener,
50 AudioModeListener,
51 IncomingCallListener,
52 InCallDetailsListener,
53 CanAddCallListener,
54 Listener,
55 InCallButtonUiDelegate {
56
57 private static final String KEY_AUTOMATICALLY_MUTED = "incall_key_automatically_muted";
58 private static final String KEY_PREVIOUS_MUTE_STATE = "incall_key_previous_mute_state";
59
60 private final Context mContext;
61 private InCallButtonUi mInCallButtonUi;
62 private DialerCall mCall;
63 private boolean mAutomaticallyMuted = false;
64 private boolean mPreviousMuteState = false;
65 private boolean isInCallButtonUiReady;
66
67 public CallButtonPresenter(Context context) {
68 mContext = context.getApplicationContext();
69 }
70
71 @Override
72 public void onInCallButtonUiReady(InCallButtonUi ui) {
73 Assert.checkState(!isInCallButtonUiReady);
74 mInCallButtonUi = ui;
75 AudioModeProvider.getInstance().addListener(this);
76
77 // register for call state changes last
78 final InCallPresenter inCallPresenter = InCallPresenter.getInstance();
79 inCallPresenter.addListener(this);
80 inCallPresenter.addIncomingCallListener(this);
81 inCallPresenter.addDetailsListener(this);
82 inCallPresenter.addCanAddCallListener(this);
83 inCallPresenter.getInCallCameraManager().addCameraSelectionListener(this);
84
85 // Update the buttons state immediately for the current call
86 onStateChange(InCallState.NO_CALLS, inCallPresenter.getInCallState(), CallList.getInstance());
87 isInCallButtonUiReady = true;
88 }
89
90 @Override
91 public void onInCallButtonUiUnready() {
92 Assert.checkState(isInCallButtonUiReady);
93 mInCallButtonUi = null;
94 InCallPresenter.getInstance().removeListener(this);
95 AudioModeProvider.getInstance().removeListener(this);
96 InCallPresenter.getInstance().removeIncomingCallListener(this);
97 InCallPresenter.getInstance().removeDetailsListener(this);
98 InCallPresenter.getInstance().getInCallCameraManager().removeCameraSelectionListener(this);
99 InCallPresenter.getInstance().removeCanAddCallListener(this);
100 isInCallButtonUiReady = false;
101 }
102
103 @Override
104 public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700105 Trace.beginSection("CallButtonPresenter.onStateChange");
Eric Erfanianccca3152017-02-22 16:32:36 -0800106 if (newState == InCallState.OUTGOING) {
107 mCall = callList.getOutgoingCall();
108 } else if (newState == InCallState.INCALL) {
109 mCall = callList.getActiveOrBackgroundCall();
110
111 // When connected to voice mail, automatically shows the dialpad.
112 // (On previous releases we showed it when in-call shows up, before waiting for
113 // OUTGOING. We may want to do that once we start showing "Voice mail" label on
114 // the dialpad too.)
115 if (oldState == InCallState.OUTGOING && mCall != null) {
116 if (CallerInfoUtils.isVoiceMailNumber(mContext, mCall) && getActivity() != null) {
117 getActivity().showDialpadFragment(true /* show */, true /* animate */);
118 }
119 }
120 } else if (newState == InCallState.INCOMING) {
121 if (getActivity() != null) {
122 getActivity().showDialpadFragment(false /* show */, true /* animate */);
123 }
124 mCall = callList.getIncomingCall();
125 } else {
126 mCall = null;
127 }
128 updateUi(newState, mCall);
Eric Erfanian2ca43182017-08-31 06:57:16 -0700129 Trace.endSection();
Eric Erfanianccca3152017-02-22 16:32:36 -0800130 }
131
132 /**
133 * Updates the user interface in response to a change in the details of a call. Currently handles
134 * changes to the call buttons in response to a change in the details for a call. This is
135 * important to ensure changes to the active call are reflected in the available buttons.
136 *
137 * @param call The active call.
138 * @param details The call details.
139 */
140 @Override
141 public void onDetailsChanged(DialerCall call, android.telecom.Call.Details details) {
142 // Only update if the changes are for the currently active call
143 if (mInCallButtonUi != null && call != null && call.equals(mCall)) {
144 updateButtonsState(call);
145 }
146 }
147
148 @Override
149 public void onIncomingCall(InCallState oldState, InCallState newState, DialerCall call) {
150 onStateChange(oldState, newState, CallList.getInstance());
151 }
152
153 @Override
154 public void onCanAddCallChanged(boolean canAddCall) {
155 if (mInCallButtonUi != null && mCall != null) {
156 updateButtonsState(mCall);
157 }
158 }
159
160 @Override
161 public void onAudioStateChanged(CallAudioState audioState) {
162 if (mInCallButtonUi != null) {
163 mInCallButtonUi.setAudioState(audioState);
164 }
165 }
166
167 @Override
168 public CallAudioState getCurrentAudioState() {
169 return AudioModeProvider.getInstance().getAudioState();
170 }
171
172 @Override
173 public void setAudioRoute(int route) {
174 LogUtil.i(
175 "CallButtonPresenter.setAudioRoute",
176 "sending new audio route: " + CallAudioState.audioRouteToString(route));
177 TelecomAdapter.getInstance().setAudioRoute(route);
178 }
179
180 /** Function assumes that bluetooth is not supported. */
181 @Override
182 public void toggleSpeakerphone() {
183 // This function should not be called if bluetooth is available.
184 CallAudioState audioState = getCurrentAudioState();
185 if (0 != (CallAudioState.ROUTE_BLUETOOTH & audioState.getSupportedRouteMask())) {
186 // It's clear the UI is wrong, so update the supported mode once again.
187 LogUtil.e(
188 "CallButtonPresenter", "toggling speakerphone not allowed when bluetooth supported.");
189 mInCallButtonUi.setAudioState(audioState);
190 return;
191 }
192
193 int newRoute;
194 if (audioState.getRoute() == CallAudioState.ROUTE_SPEAKER) {
195 newRoute = CallAudioState.ROUTE_WIRED_OR_EARPIECE;
196 Logger.get(mContext)
197 .logCallImpression(
198 DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_WIRED_OR_EARPIECE,
199 mCall.getUniqueCallId(),
200 mCall.getTimeAddedMs());
201 } else {
202 newRoute = CallAudioState.ROUTE_SPEAKER;
203 Logger.get(mContext)
204 .logCallImpression(
205 DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_SPEAKERPHONE,
206 mCall.getUniqueCallId(),
207 mCall.getTimeAddedMs());
208 }
209
210 setAudioRoute(newRoute);
211 }
212
213 @Override
Eric Erfanian9a090c82017-03-16 19:22:24 -0700214 public void muteClicked(boolean checked, boolean clickedByUser) {
215 LogUtil.i(
216 "CallButtonPresenter", "turning on mute: %s, clicked by user: %s", checked, clickedByUser);
217 if (clickedByUser) {
218 Logger.get(mContext)
219 .logCallImpression(
220 checked
221 ? DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_MUTE
222 : DialerImpression.Type.IN_CALL_SCREEN_TURN_OFF_MUTE,
223 mCall.getUniqueCallId(),
224 mCall.getTimeAddedMs());
225 }
Eric Erfanianccca3152017-02-22 16:32:36 -0800226 TelecomAdapter.getInstance().mute(checked);
227 }
228
229 @Override
230 public void holdClicked(boolean checked) {
231 if (mCall == null) {
232 return;
233 }
234 if (checked) {
235 LogUtil.i("CallButtonPresenter", "putting the call on hold: " + mCall);
236 mCall.hold();
237 } else {
238 LogUtil.i("CallButtonPresenter", "removing the call from hold: " + mCall);
239 mCall.unhold();
240 }
241 }
242
243 @Override
244 public void swapClicked() {
245 if (mCall == null) {
246 return;
247 }
248
249 LogUtil.i("CallButtonPresenter", "swapping the call: " + mCall);
250 TelecomAdapter.getInstance().swap(mCall.getId());
251 }
252
253 @Override
254 public void mergeClicked() {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700255 Logger.get(mContext)
256 .logCallImpression(
257 DialerImpression.Type.IN_CALL_MERGE_BUTTON_PRESSED,
258 mCall.getUniqueCallId(),
259 mCall.getTimeAddedMs());
Eric Erfanianccca3152017-02-22 16:32:36 -0800260 TelecomAdapter.getInstance().merge(mCall.getId());
261 }
262
263 @Override
264 public void addCallClicked() {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700265 Logger.get(mContext)
266 .logCallImpression(
267 DialerImpression.Type.IN_CALL_ADD_CALL_BUTTON_PRESSED,
268 mCall.getUniqueCallId(),
269 mCall.getTimeAddedMs());
Eric Erfanianccca3152017-02-22 16:32:36 -0800270 // Automatically mute the current call
271 mAutomaticallyMuted = true;
272 mPreviousMuteState = AudioModeProvider.getInstance().getAudioState().isMuted();
273 // Simulate a click on the mute button
Eric Erfanian9a090c82017-03-16 19:22:24 -0700274 muteClicked(true /* checked */, false /* clickedByUser */);
Eric Erfanianccca3152017-02-22 16:32:36 -0800275 TelecomAdapter.getInstance().addCall();
276 }
277
278 @Override
279 public void showDialpadClicked(boolean checked) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700280 Logger.get(mContext)
281 .logCallImpression(
282 DialerImpression.Type.IN_CALL_SHOW_DIALPAD_BUTTON_PRESSED,
283 mCall.getUniqueCallId(),
284 mCall.getTimeAddedMs());
Eric Erfanianccca3152017-02-22 16:32:36 -0800285 LogUtil.v("CallButtonPresenter", "show dialpad " + String.valueOf(checked));
286 getActivity().showDialpadFragment(checked /* show */, true /* animate */);
287 }
288
289 @Override
290 public void changeToVideoClicked() {
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700291 LogUtil.enterBlock("CallButtonPresenter.changeToVideoClicked");
Eric Erfanian8369df02017-05-03 10:27:13 -0700292 Logger.get(mContext)
293 .logCallImpression(
294 DialerImpression.Type.VIDEO_CALL_UPGRADE_REQUESTED,
295 mCall.getUniqueCallId(),
296 mCall.getTimeAddedMs());
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700297 mCall.getVideoTech().upgradeToVideo();
Eric Erfanianccca3152017-02-22 16:32:36 -0800298 }
299
300 @Override
301 public void onEndCallClicked() {
302 LogUtil.i("CallButtonPresenter.onEndCallClicked", "call: " + mCall);
303 if (mCall != null) {
304 mCall.disconnect();
305 }
306 }
307
308 @Override
309 public void showAudioRouteSelector() {
310 mInCallButtonUi.showAudioRouteSelector();
311 }
312
313 /**
314 * Switches the camera between the front-facing and back-facing camera.
315 *
316 * @param useFrontFacingCamera True if we should switch to using the front-facing camera, or false
317 * if we should switch to using the back-facing camera.
318 */
319 @Override
320 public void switchCameraClicked(boolean useFrontFacingCamera) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700321 updateCamera(useFrontFacingCamera);
Eric Erfanianccca3152017-02-22 16:32:36 -0800322 }
323
324 @Override
325 public void toggleCameraClicked() {
326 LogUtil.i("CallButtonPresenter.toggleCameraClicked", "");
Eric Erfanian2ca43182017-08-31 06:57:16 -0700327 if (mCall == null) {
328 return;
329 }
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700330 Logger.get(mContext)
331 .logCallImpression(
332 DialerImpression.Type.IN_CALL_SCREEN_SWAP_CAMERA,
333 mCall.getUniqueCallId(),
334 mCall.getTimeAddedMs());
Eric Erfanianccca3152017-02-22 16:32:36 -0800335 switchCameraClicked(
336 !InCallPresenter.getInstance().getInCallCameraManager().isUsingFrontFacingCamera());
337 }
338
339 /**
340 * Stop or start client's video transmission.
341 *
342 * @param pause True if pausing the local user's video, or false if starting the local user's
343 * video.
344 */
345 @Override
346 public void pauseVideoClicked(boolean pause) {
347 LogUtil.i("CallButtonPresenter.pauseVideoClicked", "%s", pause ? "pause" : "unpause");
Eric Erfanianccca3152017-02-22 16:32:36 -0800348
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700349 Logger.get(mContext)
350 .logCallImpression(
351 pause
352 ? DialerImpression.Type.IN_CALL_SCREEN_TURN_OFF_VIDEO
353 : DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_VIDEO,
354 mCall.getUniqueCallId(),
355 mCall.getTimeAddedMs());
356
Eric Erfanianccca3152017-02-22 16:32:36 -0800357 if (pause) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700358 mCall.getVideoTech().setCamera(null);
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700359 mCall.getVideoTech().stopTransmission();
Eric Erfanianccca3152017-02-22 16:32:36 -0800360 } else {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700361 updateCamera(
362 InCallPresenter.getInstance().getInCallCameraManager().isUsingFrontFacingCamera());
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700363 mCall.getVideoTech().resumeTransmission();
Eric Erfanianccca3152017-02-22 16:32:36 -0800364 }
365
366 mInCallButtonUi.setVideoPaused(pause);
367 mInCallButtonUi.enableButton(InCallButtonIds.BUTTON_PAUSE_VIDEO, false);
368 }
369
Eric Erfanian2ca43182017-08-31 06:57:16 -0700370 private void updateCamera(boolean useFrontFacingCamera) {
371 InCallCameraManager cameraManager = InCallPresenter.getInstance().getInCallCameraManager();
372 cameraManager.setUseFrontFacingCamera(useFrontFacingCamera);
373
374 String cameraId = cameraManager.getActiveCameraId();
375 if (cameraId != null) {
376 final int cameraDir =
377 cameraManager.isUsingFrontFacingCamera()
378 ? CameraDirection.CAMERA_DIRECTION_FRONT_FACING
379 : CameraDirection.CAMERA_DIRECTION_BACK_FACING;
380 mCall.setCameraDir(cameraDir);
381 mCall.getVideoTech().setCamera(cameraId);
382 }
383 }
384
Eric Erfanianccca3152017-02-22 16:32:36 -0800385 private void updateUi(InCallState state, DialerCall call) {
Eric Erfanian2ca43182017-08-31 06:57:16 -0700386 LogUtil.v("CallButtonPresenter", "updating call UI for call: %s", call);
Eric Erfanianccca3152017-02-22 16:32:36 -0800387
388 if (mInCallButtonUi == null) {
389 return;
390 }
391
392 if (call != null) {
393 mInCallButtonUi.updateInCallButtonUiColors();
394 }
395
396 final boolean isEnabled =
397 state.isConnectingOrConnected() && !state.isIncoming() && call != null;
398 mInCallButtonUi.setEnabled(isEnabled);
399
400 if (call == null) {
401 return;
402 }
403
404 updateButtonsState(call);
405 }
406
407 /**
408 * Updates the buttons applicable for the UI.
409 *
410 * @param call The active call.
411 */
412 private void updateButtonsState(DialerCall call) {
413 LogUtil.v("CallButtonPresenter.updateButtonsState", "");
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700414 final boolean isVideo = call.isVideoCall();
Eric Erfanianccca3152017-02-22 16:32:36 -0800415
416 // Common functionality (audio, hold, etc).
417 // Show either HOLD or SWAP, but not both. If neither HOLD or SWAP is available:
418 // (1) If the device normally can hold, show HOLD in a disabled state.
419 // (2) If the device doesn't have the concept of hold/swap, remove the button.
420 final boolean showSwap = call.can(android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE);
421 final boolean showHold =
422 !showSwap
423 && call.can(android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD)
424 && call.can(android.telecom.Call.Details.CAPABILITY_HOLD);
425 final boolean isCallOnHold = call.getState() == DialerCall.State.ONHOLD;
426
427 final boolean showAddCall =
428 TelecomAdapter.getInstance().canAddCall() && UserManagerCompat.isUserUnlocked(mContext);
429 final boolean showMerge = call.can(android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE);
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700430 final boolean showUpgradeToVideo = !isVideo && (hasVideoCallCapabilities(call));
Eric Erfanianccca3152017-02-22 16:32:36 -0800431 final boolean showDowngradeToAudio = isVideo && isDowngradeToAudioSupported(call);
432 final boolean showMute = call.can(android.telecom.Call.Details.CAPABILITY_MUTE);
433
434 final boolean hasCameraPermission =
Eric Erfanian2ca43182017-08-31 06:57:16 -0700435 isVideo && VideoUtils.hasCameraPermissionAndShownPrivacyToast(mContext);
Eric Erfanianccca3152017-02-22 16:32:36 -0800436 // Disabling local video doesn't seem to work when dialing. See b/30256571.
437 final boolean showPauseVideo =
438 isVideo
439 && call.getState() != DialerCall.State.DIALING
440 && call.getState() != DialerCall.State.CONNECTING;
441
442 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_AUDIO, true);
443 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_SWAP, showSwap);
444 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_HOLD, showHold);
445 mInCallButtonUi.setHold(isCallOnHold);
446 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_MUTE, showMute);
447 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_ADD_CALL, true);
448 mInCallButtonUi.enableButton(InCallButtonIds.BUTTON_ADD_CALL, showAddCall);
449 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO, showUpgradeToVideo);
450 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_DOWNGRADE_TO_AUDIO, showDowngradeToAudio);
451 mInCallButtonUi.showButton(
452 InCallButtonIds.BUTTON_SWITCH_CAMERA, isVideo && hasCameraPermission);
453 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_PAUSE_VIDEO, showPauseVideo);
454 if (isVideo) {
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700455 mInCallButtonUi.setVideoPaused(!call.getVideoTech().isTransmitting() || !hasCameraPermission);
Eric Erfanianccca3152017-02-22 16:32:36 -0800456 }
457 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_DIALPAD, true);
458 mInCallButtonUi.showButton(InCallButtonIds.BUTTON_MERGE, showMerge);
459
460 mInCallButtonUi.updateButtonStates();
461 }
462
463 private boolean hasVideoCallCapabilities(DialerCall call) {
Eric Erfaniand8046e52017-04-06 09:41:50 -0700464 return call.getVideoTech().isAvailable(mContext);
Eric Erfanianccca3152017-02-22 16:32:36 -0800465 }
466
467 /**
468 * Determines if downgrading from a video call to an audio-only call is supported. In order to
469 * support downgrade to audio, the SDK version must be >= N and the call should NOT have the
470 * {@link android.telecom.Call.Details#CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO}.
471 *
472 * @param call The call.
473 * @return {@code true} if downgrading to an audio-only call from a video call is supported.
474 */
475 private boolean isDowngradeToAudioSupported(DialerCall call) {
Eric Erfaniand5e47f62017-03-15 14:41:07 -0700476 // TODO(b/33676907): If there is an RCS video share session, return true here
Eric Erfanianccca3152017-02-22 16:32:36 -0800477 return !call.can(CallCompat.Details.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO);
478 }
479
480 @Override
481 public void refreshMuteState() {
482 // Restore the previous mute state
483 if (mAutomaticallyMuted
484 && AudioModeProvider.getInstance().getAudioState().isMuted() != mPreviousMuteState) {
485 if (mInCallButtonUi == null) {
486 return;
487 }
Eric Erfanian9a090c82017-03-16 19:22:24 -0700488 muteClicked(mPreviousMuteState, false /* clickedByUser */);
Eric Erfanianccca3152017-02-22 16:32:36 -0800489 }
490 mAutomaticallyMuted = false;
491 }
492
493 @Override
494 public void onSaveInstanceState(Bundle outState) {
495 outState.putBoolean(KEY_AUTOMATICALLY_MUTED, mAutomaticallyMuted);
496 outState.putBoolean(KEY_PREVIOUS_MUTE_STATE, mPreviousMuteState);
497 }
498
499 @Override
500 public void onRestoreInstanceState(Bundle savedInstanceState) {
501 mAutomaticallyMuted =
502 savedInstanceState.getBoolean(KEY_AUTOMATICALLY_MUTED, mAutomaticallyMuted);
503 mPreviousMuteState = savedInstanceState.getBoolean(KEY_PREVIOUS_MUTE_STATE, mPreviousMuteState);
504 }
505
506 @Override
507 public void onCameraPermissionGranted() {
508 if (mCall != null) {
509 updateButtonsState(mCall);
510 }
511 }
512
513 @Override
514 public void onActiveCameraSelectionChanged(boolean isUsingFrontFacingCamera) {
515 if (mInCallButtonUi == null) {
516 return;
517 }
518 mInCallButtonUi.setCameraSwitched(!isUsingFrontFacingCamera);
519 }
520
521 @Override
522 public Context getContext() {
523 return mContext;
524 }
525
526 private InCallActivity getActivity() {
527 if (mInCallButtonUi != null) {
528 Fragment fragment = mInCallButtonUi.getInCallButtonUiFragment();
529 if (fragment != null) {
530 return (InCallActivity) fragment.getActivity();
531 }
532 }
533 return null;
534 }
535}