• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.incallui;
18 
19 import android.content.Context;
20 import android.os.Bundle;
21 import android.os.Trace;
22 import android.support.v4.app.Fragment;
23 import android.support.v4.os.UserManagerCompat;
24 import android.telecom.CallAudioState;
25 import android.telecom.PhoneAccountHandle;
26 import com.android.contacts.common.compat.CallCompat;
27 import com.android.dialer.common.Assert;
28 import com.android.dialer.common.LogUtil;
29 import com.android.dialer.common.concurrent.DialerExecutorComponent;
30 import com.android.dialer.logging.DialerImpression;
31 import com.android.dialer.logging.DialerImpression.Type;
32 import com.android.dialer.logging.Logger;
33 import com.android.dialer.telecom.TelecomUtil;
34 import com.android.incallui.InCallCameraManager.Listener;
35 import com.android.incallui.InCallPresenter.CanAddCallListener;
36 import com.android.incallui.InCallPresenter.InCallDetailsListener;
37 import com.android.incallui.InCallPresenter.InCallState;
38 import com.android.incallui.InCallPresenter.InCallStateListener;
39 import com.android.incallui.InCallPresenter.IncomingCallListener;
40 import com.android.incallui.audiomode.AudioModeProvider;
41 import com.android.incallui.audiomode.AudioModeProvider.AudioModeListener;
42 import com.android.incallui.call.CallList;
43 import com.android.incallui.call.DialerCall;
44 import com.android.incallui.call.DialerCall.CameraDirection;
45 import com.android.incallui.call.DialerCallListener;
46 import com.android.incallui.call.TelecomAdapter;
47 import com.android.incallui.call.state.DialerCallState;
48 import com.android.incallui.incall.protocol.InCallButtonIds;
49 import com.android.incallui.incall.protocol.InCallButtonUi;
50 import com.android.incallui.incall.protocol.InCallButtonUiDelegate;
51 import com.android.incallui.multisim.SwapSimWorker;
52 import com.android.incallui.videotech.utils.VideoUtils;
53 
54 /** Logic for call buttons. */
55 public class CallButtonPresenter
56     implements InCallStateListener,
57         AudioModeListener,
58         IncomingCallListener,
59         InCallDetailsListener,
60         CanAddCallListener,
61         Listener,
62         InCallButtonUiDelegate,
63         DialerCallListener {
64 
65   private final Context context;
66   private InCallButtonUi inCallButtonUi;
67   private DialerCall call;
68   private boolean isInCallButtonUiReady;
69   private PhoneAccountHandle otherAccount;
70 
CallButtonPresenter(Context context)71   public CallButtonPresenter(Context context) {
72     this.context = context.getApplicationContext();
73   }
74 
75   @Override
onInCallButtonUiReady(InCallButtonUi ui)76   public void onInCallButtonUiReady(InCallButtonUi ui) {
77     Assert.checkState(!isInCallButtonUiReady);
78     inCallButtonUi = ui;
79     AudioModeProvider.getInstance().addListener(this);
80 
81     // register for call state changes last
82     final InCallPresenter inCallPresenter = InCallPresenter.getInstance();
83     inCallPresenter.addListener(this);
84     inCallPresenter.addIncomingCallListener(this);
85     inCallPresenter.addDetailsListener(this);
86     inCallPresenter.addCanAddCallListener(this);
87     inCallPresenter.getInCallCameraManager().addCameraSelectionListener(this);
88 
89     // Update the buttons state immediately for the current call
90     onStateChange(InCallState.NO_CALLS, inCallPresenter.getInCallState(), CallList.getInstance());
91     isInCallButtonUiReady = true;
92   }
93 
94   @Override
onInCallButtonUiUnready()95   public void onInCallButtonUiUnready() {
96     Assert.checkState(isInCallButtonUiReady);
97     inCallButtonUi = null;
98     InCallPresenter.getInstance().removeListener(this);
99     AudioModeProvider.getInstance().removeListener(this);
100     InCallPresenter.getInstance().removeIncomingCallListener(this);
101     InCallPresenter.getInstance().removeDetailsListener(this);
102     InCallPresenter.getInstance().getInCallCameraManager().removeCameraSelectionListener(this);
103     InCallPresenter.getInstance().removeCanAddCallListener(this);
104     isInCallButtonUiReady = false;
105 
106     if (call != null) {
107       call.removeListener(this);
108     }
109   }
110 
111   @Override
onStateChange(InCallState oldState, InCallState newState, CallList callList)112   public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
113     Trace.beginSection("CallButtonPresenter.onStateChange");
114     if (call != null) {
115       call.removeListener(this);
116     }
117     if (newState == InCallState.OUTGOING) {
118       call = callList.getOutgoingCall();
119     } else if (newState == InCallState.INCALL) {
120       call = callList.getActiveOrBackgroundCall();
121 
122       // When connected to voice mail, automatically shows the dialpad.
123       // (On previous releases we showed it when in-call shows up, before waiting for
124       // OUTGOING.  We may want to do that once we start showing "Voice mail" label on
125       // the dialpad too.)
126       if (oldState == InCallState.OUTGOING && call != null) {
127         if (call.isVoiceMailNumber() && getActivity() != null) {
128           getActivity().showDialpadFragment(true /* show */, true /* animate */);
129         }
130       }
131     } else if (newState == InCallState.INCOMING) {
132       if (getActivity() != null) {
133         getActivity().showDialpadFragment(false /* show */, true /* animate */);
134       }
135       call = callList.getIncomingCall();
136     } else {
137       call = null;
138     }
139 
140     if (call != null) {
141       call.addListener(this);
142     }
143     updateUi(newState, call);
144     Trace.endSection();
145   }
146 
147   /**
148    * Updates the user interface in response to a change in the details of a call. Currently handles
149    * changes to the call buttons in response to a change in the details for a call. This is
150    * important to ensure changes to the active call are reflected in the available buttons.
151    *
152    * @param call The active call.
153    * @param details The call details.
154    */
155   @Override
onDetailsChanged(DialerCall call, android.telecom.Call.Details details)156   public void onDetailsChanged(DialerCall call, android.telecom.Call.Details details) {
157     // Only update if the changes are for the currently active call
158     if (inCallButtonUi != null && call != null && call.equals(this.call)) {
159       updateButtonsState(call);
160     }
161   }
162 
163   @Override
onIncomingCall(InCallState oldState, InCallState newState, DialerCall call)164   public void onIncomingCall(InCallState oldState, InCallState newState, DialerCall call) {
165     onStateChange(oldState, newState, CallList.getInstance());
166   }
167 
168   @Override
onCanAddCallChanged(boolean canAddCall)169   public void onCanAddCallChanged(boolean canAddCall) {
170     if (inCallButtonUi != null && call != null) {
171       updateButtonsState(call);
172     }
173   }
174 
175   @Override
onAudioStateChanged(CallAudioState audioState)176   public void onAudioStateChanged(CallAudioState audioState) {
177     if (inCallButtonUi != null) {
178       inCallButtonUi.setAudioState(audioState);
179     }
180   }
181 
182   @Override
getCurrentAudioState()183   public CallAudioState getCurrentAudioState() {
184     return AudioModeProvider.getInstance().getAudioState();
185   }
186 
187   @Override
setAudioRoute(int route)188   public void setAudioRoute(int route) {
189     LogUtil.i(
190         "CallButtonPresenter.setAudioRoute",
191         "sending new audio route: " + CallAudioState.audioRouteToString(route));
192     TelecomAdapter.getInstance().setAudioRoute(route);
193   }
194 
195   /** Function assumes that bluetooth is not supported. */
196   @Override
toggleSpeakerphone()197   public void toggleSpeakerphone() {
198     // This function should not be called if bluetooth is available.
199     CallAudioState audioState = getCurrentAudioState();
200     if (0 != (CallAudioState.ROUTE_BLUETOOTH & audioState.getSupportedRouteMask())) {
201       // It's clear the UI is wrong, so update the supported mode once again.
202       LogUtil.e(
203           "CallButtonPresenter", "toggling speakerphone not allowed when bluetooth supported.");
204       inCallButtonUi.setAudioState(audioState);
205       return;
206     }
207 
208     int newRoute;
209     if (audioState.getRoute() == CallAudioState.ROUTE_SPEAKER) {
210       newRoute = CallAudioState.ROUTE_WIRED_OR_EARPIECE;
211       if (call != null) {
212         Logger.get(context)
213                 .logCallImpression(
214                         DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_WIRED_OR_EARPIECE,
215                         call.getUniqueCallId(),
216                         call.getTimeAddedMs());
217       }
218     } else {
219       newRoute = CallAudioState.ROUTE_SPEAKER;
220       if (call != null) {
221         Logger.get(context)
222                 .logCallImpression(
223                         DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_SPEAKERPHONE,
224                         call.getUniqueCallId(),
225                         call.getTimeAddedMs());
226       }
227     }
228 
229     setAudioRoute(newRoute);
230   }
231 
232   @Override
muteClicked(boolean checked, boolean clickedByUser)233   public void muteClicked(boolean checked, boolean clickedByUser) {
234     LogUtil.i(
235         "CallButtonPresenter", "turning on mute: %s, clicked by user: %s", checked, clickedByUser);
236     if (clickedByUser) {
237       Logger.get(context)
238           .logCallImpression(
239               checked
240                   ? DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_MUTE
241                   : DialerImpression.Type.IN_CALL_SCREEN_TURN_OFF_MUTE,
242               call.getUniqueCallId(),
243               call.getTimeAddedMs());
244     }
245     TelecomAdapter.getInstance().mute(checked);
246   }
247 
248   @Override
holdClicked(boolean checked)249   public void holdClicked(boolean checked) {
250     if (call == null) {
251       return;
252     }
253     if (checked) {
254       LogUtil.i("CallButtonPresenter", "putting the call on hold: " + call);
255       call.hold();
256     } else {
257       LogUtil.i("CallButtonPresenter", "removing the call from hold: " + call);
258       call.unhold();
259     }
260   }
261 
262   @Override
swapClicked()263   public void swapClicked() {
264     if (call == null) {
265       return;
266     }
267 
268     LogUtil.i("CallButtonPresenter", "swapping the call: " + call);
269     TelecomAdapter.getInstance().swap(call.getId());
270   }
271 
272   @Override
mergeClicked()273   public void mergeClicked() {
274     Logger.get(context)
275         .logCallImpression(
276             DialerImpression.Type.IN_CALL_MERGE_BUTTON_PRESSED,
277             call.getUniqueCallId(),
278             call.getTimeAddedMs());
279     TelecomAdapter.getInstance().merge(call.getId());
280   }
281 
282   @Override
addCallClicked()283   public void addCallClicked() {
284     Logger.get(context)
285         .logCallImpression(
286             DialerImpression.Type.IN_CALL_ADD_CALL_BUTTON_PRESSED,
287             call.getUniqueCallId(),
288             call.getTimeAddedMs());
289     InCallPresenter.getInstance().addCallClicked();
290   }
291 
292   @Override
showDialpadClicked(boolean checked)293   public void showDialpadClicked(boolean checked) {
294     Logger.get(context)
295         .logCallImpression(
296             DialerImpression.Type.IN_CALL_SHOW_DIALPAD_BUTTON_PRESSED,
297             call.getUniqueCallId(),
298             call.getTimeAddedMs());
299     LogUtil.v("CallButtonPresenter", "show dialpad " + String.valueOf(checked));
300     getActivity().showDialpadFragment(checked /* show */, true /* animate */);
301   }
302 
303   @Override
changeToVideoClicked()304   public void changeToVideoClicked() {
305     LogUtil.enterBlock("CallButtonPresenter.changeToVideoClicked");
306     Logger.get(context)
307         .logCallImpression(
308             DialerImpression.Type.VIDEO_CALL_UPGRADE_REQUESTED,
309             call.getUniqueCallId(),
310             call.getTimeAddedMs());
311     call.getVideoTech().upgradeToVideo(context);
312   }
313 
314   @Override
changeToRttClicked()315   public void changeToRttClicked() {
316     LogUtil.enterBlock("CallButtonPresenter.changeToRttClicked");
317     call.sendRttUpgradeRequest();
318   }
319 
320   @Override
onEndCallClicked()321   public void onEndCallClicked() {
322     LogUtil.i("CallButtonPresenter.onEndCallClicked", "call: " + call);
323     if (call != null) {
324       call.disconnect();
325     }
326   }
327 
328   @Override
showAudioRouteSelector()329   public void showAudioRouteSelector() {
330     inCallButtonUi.showAudioRouteSelector();
331   }
332 
333   @Override
swapSimClicked()334   public void swapSimClicked() {
335     LogUtil.enterBlock("CallButtonPresenter.swapSimClicked");
336     Logger.get(getContext()).logImpression(Type.DUAL_SIM_CHANGE_SIM_PRESSED);
337     SwapSimWorker worker =
338         new SwapSimWorker(
339             getContext(),
340             call,
341             InCallPresenter.getInstance().getCallList(),
342             otherAccount,
343             InCallPresenter.getInstance().acquireInCallUiLock("swapSim"));
344     DialerExecutorComponent.get(getContext())
345         .dialerExecutorFactory()
346         .createNonUiTaskBuilder(worker)
347         .build()
348         .executeParallel(null);
349   }
350 
351   /**
352    * Switches the camera between the front-facing and back-facing camera.
353    *
354    * @param useFrontFacingCamera True if we should switch to using the front-facing camera, or false
355    *     if we should switch to using the back-facing camera.
356    */
357   @Override
switchCameraClicked(boolean useFrontFacingCamera)358   public void switchCameraClicked(boolean useFrontFacingCamera) {
359     updateCamera(useFrontFacingCamera);
360   }
361 
362   @Override
toggleCameraClicked()363   public void toggleCameraClicked() {
364     LogUtil.i("CallButtonPresenter.toggleCameraClicked", "");
365     if (call == null) {
366       return;
367     }
368     Logger.get(context)
369         .logCallImpression(
370             DialerImpression.Type.IN_CALL_SCREEN_SWAP_CAMERA,
371             call.getUniqueCallId(),
372             call.getTimeAddedMs());
373     switchCameraClicked(
374         !InCallPresenter.getInstance().getInCallCameraManager().isUsingFrontFacingCamera());
375   }
376 
377   /**
378    * Stop or start client's video transmission.
379    *
380    * @param pause True if pausing the local user's video, or false if starting the local user's
381    *     video.
382    */
383   @Override
pauseVideoClicked(boolean pause)384   public void pauseVideoClicked(boolean pause) {
385     LogUtil.i("CallButtonPresenter.pauseVideoClicked", "%s", pause ? "pause" : "unpause");
386 
387     Logger.get(context)
388         .logCallImpression(
389             pause
390                 ? DialerImpression.Type.IN_CALL_SCREEN_TURN_OFF_VIDEO
391                 : DialerImpression.Type.IN_CALL_SCREEN_TURN_ON_VIDEO,
392             call.getUniqueCallId(),
393             call.getTimeAddedMs());
394 
395     if (pause) {
396       call.getVideoTech().stopTransmission();
397     } else {
398       updateCamera(
399           InCallPresenter.getInstance().getInCallCameraManager().isUsingFrontFacingCamera());
400       call.getVideoTech().resumeTransmission(context);
401     }
402 
403     inCallButtonUi.setVideoPaused(pause);
404     inCallButtonUi.enableButton(InCallButtonIds.BUTTON_PAUSE_VIDEO, false);
405   }
406 
updateCamera(boolean useFrontFacingCamera)407   private void updateCamera(boolean useFrontFacingCamera) {
408     InCallCameraManager cameraManager = InCallPresenter.getInstance().getInCallCameraManager();
409     cameraManager.setUseFrontFacingCamera(useFrontFacingCamera);
410 
411     String cameraId = cameraManager.getActiveCameraId();
412     if (cameraId != null) {
413       final int cameraDir =
414           cameraManager.isUsingFrontFacingCamera()
415               ? CameraDirection.CAMERA_DIRECTION_FRONT_FACING
416               : CameraDirection.CAMERA_DIRECTION_BACK_FACING;
417       call.setCameraDir(cameraDir);
418       call.getVideoTech().setCamera(cameraId);
419     }
420   }
421 
updateUi(InCallState state, DialerCall call)422   private void updateUi(InCallState state, DialerCall call) {
423     LogUtil.v("CallButtonPresenter", "updating call UI for call: %s", call);
424 
425     if (inCallButtonUi == null) {
426       return;
427     }
428 
429     if (call != null) {
430       inCallButtonUi.updateInCallButtonUiColors(
431           InCallPresenter.getInstance().getThemeColorManager().getSecondaryColor());
432     }
433 
434     final boolean isEnabled =
435         state.isConnectingOrConnected() && !state.isIncoming() && call != null;
436     inCallButtonUi.setEnabled(isEnabled);
437 
438     if (call == null) {
439       return;
440     }
441 
442     updateButtonsState(call);
443   }
444 
445   /**
446    * Updates the buttons applicable for the UI.
447    *
448    * @param call The active call.
449    */
450   @SuppressWarnings(value = {"MissingPermission"})
updateButtonsState(DialerCall call)451   private void updateButtonsState(DialerCall call) {
452     LogUtil.v("CallButtonPresenter.updateButtonsState", "");
453     final boolean isVideo = call.isVideoCall();
454 
455     // Common functionality (audio, hold, etc).
456     // Show either HOLD or SWAP, but not both. If neither HOLD or SWAP is available:
457     //     (1) If the device normally can hold, show HOLD in a disabled state.
458     //     (2) If the device doesn't have the concept of hold/swap, remove the button.
459     final boolean showSwap = call.can(android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE);
460     final boolean showHold =
461         !showSwap
462             && call.can(android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD)
463             && call.can(android.telecom.Call.Details.CAPABILITY_HOLD);
464     final boolean isCallOnHold = call.getState() == DialerCallState.ONHOLD;
465 
466     final boolean showAddCall =
467         TelecomAdapter.getInstance().canAddCall() && UserManagerCompat.isUserUnlocked(context);
468     // There can only be two calls so don't show the ability to merge when one of them
469     // is a speak easy call.
470     final boolean showMerge =
471         InCallPresenter.getInstance()
472                 .getCallList()
473                 .getAllCalls()
474                 .stream()
475                 .noneMatch(c -> c != null && c.isSpeakEasyCall())
476             && call.can(android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE);
477     final boolean showUpgradeToVideo = !isVideo && (hasVideoCallCapabilities(call));
478     final boolean showDowngradeToAudio = isVideo && isDowngradeToAudioSupported(call);
479     final boolean showMute = call.can(android.telecom.Call.Details.CAPABILITY_MUTE);
480 
481     final boolean hasCameraPermission =
482         isVideo && VideoUtils.hasCameraPermissionAndShownPrivacyToast(context);
483     // Disabling local video doesn't seem to work when dialing. See a bug.
484     final boolean showPauseVideo =
485         isVideo
486             && call.getState() != DialerCallState.DIALING
487             && call.getState() != DialerCallState.CONNECTING;
488 
489     otherAccount = TelecomUtil.getOtherAccount(getContext(), call.getAccountHandle());
490     boolean showSwapSim =
491         !call.isEmergencyCall()
492             && otherAccount != null
493             && !call.isVoiceMailNumber()
494             && DialerCallState.isDialing(call.getState())
495             // Most devices cannot make calls on 2 SIMs at the same time.
496             && InCallPresenter.getInstance().getCallList().getAllCalls().size() == 1;
497 
498     boolean showUpgradeToRtt = call.canUpgradeToRttCall();
499     boolean enableUpgradeToRtt = showUpgradeToRtt && call.getState() == DialerCallState.ACTIVE;
500 
501     inCallButtonUi.showButton(InCallButtonIds.BUTTON_AUDIO, true);
502     inCallButtonUi.showButton(InCallButtonIds.BUTTON_SWAP, showSwap);
503     inCallButtonUi.showButton(InCallButtonIds.BUTTON_HOLD, showHold);
504     inCallButtonUi.setHold(isCallOnHold);
505     inCallButtonUi.showButton(InCallButtonIds.BUTTON_MUTE, showMute);
506     inCallButtonUi.showButton(InCallButtonIds.BUTTON_SWAP_SIM, showSwapSim);
507     inCallButtonUi.showButton(InCallButtonIds.BUTTON_ADD_CALL, true);
508     inCallButtonUi.enableButton(InCallButtonIds.BUTTON_ADD_CALL, showAddCall);
509     inCallButtonUi.showButton(InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO, showUpgradeToVideo);
510     inCallButtonUi.showButton(InCallButtonIds.BUTTON_UPGRADE_TO_RTT, showUpgradeToRtt);
511     inCallButtonUi.enableButton(InCallButtonIds.BUTTON_UPGRADE_TO_RTT, enableUpgradeToRtt);
512     inCallButtonUi.showButton(InCallButtonIds.BUTTON_DOWNGRADE_TO_AUDIO, showDowngradeToAudio);
513     inCallButtonUi.showButton(
514         InCallButtonIds.BUTTON_SWITCH_CAMERA,
515         isVideo && hasCameraPermission && call.getVideoTech().isTransmitting());
516     inCallButtonUi.showButton(InCallButtonIds.BUTTON_PAUSE_VIDEO, showPauseVideo);
517     if (isVideo) {
518       inCallButtonUi.setVideoPaused(!call.getVideoTech().isTransmitting() || !hasCameraPermission);
519     }
520     inCallButtonUi.showButton(InCallButtonIds.BUTTON_DIALPAD, true);
521     inCallButtonUi.showButton(InCallButtonIds.BUTTON_MERGE, showMerge);
522 
523     inCallButtonUi.updateButtonStates();
524   }
525 
hasVideoCallCapabilities(DialerCall call)526   private boolean hasVideoCallCapabilities(DialerCall call) {
527     return call.getVideoTech().isAvailable(context, call.getAccountHandle());
528   }
529 
530   /**
531    * Determines if downgrading from a video call to an audio-only call is supported. In order to
532    * support downgrade to audio, the SDK version must be >= N and the call should NOT have the
533    * {@link android.telecom.Call.Details#CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO}.
534    *
535    * @param call The call.
536    * @return {@code true} if downgrading to an audio-only call from a video call is supported.
537    */
isDowngradeToAudioSupported(DialerCall call)538   private boolean isDowngradeToAudioSupported(DialerCall call) {
539     // TODO(a bug): If there is an RCS video share session, return true here
540     return !call.can(CallCompat.Details.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO);
541   }
542 
543   @Override
onSaveInstanceState(Bundle outState)544   public void onSaveInstanceState(Bundle outState) {}
545 
546   @Override
onRestoreInstanceState(Bundle savedInstanceState)547   public void onRestoreInstanceState(Bundle savedInstanceState) {}
548 
549   @Override
onCameraPermissionGranted()550   public void onCameraPermissionGranted() {
551     if (call != null) {
552       updateButtonsState(call);
553     }
554   }
555 
556   @Override
onActiveCameraSelectionChanged(boolean isUsingFrontFacingCamera)557   public void onActiveCameraSelectionChanged(boolean isUsingFrontFacingCamera) {
558     if (inCallButtonUi == null) {
559       return;
560     }
561     inCallButtonUi.setCameraSwitched(!isUsingFrontFacingCamera);
562   }
563 
564   @Override
onDialerCallSessionModificationStateChange()565   public void onDialerCallSessionModificationStateChange() {
566     if (inCallButtonUi != null && call != null) {
567       inCallButtonUi.enableButton(InCallButtonIds.BUTTON_PAUSE_VIDEO, true);
568       updateButtonsState(call);
569     }
570   }
571 
572   @Override
onDialerCallDisconnect()573   public void onDialerCallDisconnect() {}
574 
575   @Override
onDialerCallUpdate()576   public void onDialerCallUpdate() {}
577 
578   @Override
onDialerCallChildNumberChange()579   public void onDialerCallChildNumberChange() {}
580 
581   @Override
onDialerCallLastForwardedNumberChange()582   public void onDialerCallLastForwardedNumberChange() {}
583 
584   @Override
onDialerCallUpgradeToVideo()585   public void onDialerCallUpgradeToVideo() {}
586 
587   @Override
onWiFiToLteHandover()588   public void onWiFiToLteHandover() {}
589 
590   @Override
onHandoverToWifiFailure()591   public void onHandoverToWifiFailure() {}
592 
593   @Override
onInternationalCallOnWifi()594   public void onInternationalCallOnWifi() {}
595 
596   @Override
onEnrichedCallSessionUpdate()597   public void onEnrichedCallSessionUpdate() {}
598 
599   @Override
getContext()600   public Context getContext() {
601     return context;
602   }
603 
getActivity()604   private InCallActivity getActivity() {
605     if (inCallButtonUi != null) {
606       Fragment fragment = inCallButtonUi.getInCallButtonUiFragment();
607       if (fragment != null) {
608         return (InCallActivity) fragment.getActivity();
609       }
610     }
611     return null;
612   }
613 }
614