blob: 5adc99e11478f3999652ffb6bf3ef2581c47a620 [file] [log] [blame]
Brad Ebinger21013dc2017-02-02 16:21:22 -08001/*
Brad Ebingerf8c3cd82018-01-22 13:51:52 -08002 * Copyright (C) 2018 The Android Open Source Project
Brad Ebinger21013dc2017-02-02 16:21:22 -08003 *
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
Brad Ebingerf8c3cd82018-01-22 13:51:52 -080014 * limitations under the License
Brad Ebinger21013dc2017-02-02 16:21:22 -080015 */
16
Brad Ebingerf8c3cd82018-01-22 13:51:52 -080017package android.telephony.ims;
Brad Ebinger21013dc2017-02-02 16:21:22 -080018
19import android.os.Message;
20import android.os.RemoteException;
Jordan Liu8218ddd2018-11-28 11:22:39 -080021import android.telephony.CallQuality;
Brad Ebinger26462542018-01-11 10:27:43 -080022import android.telephony.ims.aidl.IImsCallSessionListener;
Brad Ebinger21013dc2017-02-02 16:21:22 -080023import android.util.Log;
Brad Ebingerf8c3cd82018-01-22 13:51:52 -080024
25import com.android.ims.internal.IImsCallSession;
26import com.android.ims.internal.IImsVideoCallProvider;
Brad Ebinger21013dc2017-02-02 16:21:22 -080027
Hall Liu137d35f2018-09-26 17:38:18 -070028import java.util.Objects;
29
Brad Ebinger21013dc2017-02-02 16:21:22 -080030/**
31 * Provides the call initiation/termination, and media exchange between two IMS endpoints.
32 * It directly communicates with IMS service which implements the IMS protocol behavior.
33 *
34 * @hide
35 */
36public class ImsCallSession {
37 private static final String TAG = "ImsCallSession";
38
39 /**
Hall Liu137d35f2018-09-26 17:38:18 -070040 * Defines IMS call session state. Please use
41 * {@link android.telephony.ims.stub.ImsCallSessionImplBase.State} definition.
Brad Ebingerf8c3cd82018-01-22 13:51:52 -080042 * This is kept around for capability reasons.
Brad Ebinger21013dc2017-02-02 16:21:22 -080043 */
44 public static class State {
45 public static final int IDLE = 0;
46 public static final int INITIATED = 1;
47 public static final int NEGOTIATING = 2;
48 public static final int ESTABLISHING = 3;
49 public static final int ESTABLISHED = 4;
50
51 public static final int RENEGOTIATING = 5;
52 public static final int REESTABLISHING = 6;
53
54 public static final int TERMINATING = 7;
55 public static final int TERMINATED = 8;
56
57 public static final int INVALID = (-1);
58
59 /**
60 * Converts the state to string.
61 */
62 public static String toString(int state) {
63 switch (state) {
64 case IDLE:
65 return "IDLE";
66 case INITIATED:
67 return "INITIATED";
68 case NEGOTIATING:
69 return "NEGOTIATING";
70 case ESTABLISHING:
71 return "ESTABLISHING";
72 case ESTABLISHED:
73 return "ESTABLISHED";
74 case RENEGOTIATING:
75 return "RENEGOTIATING";
76 case REESTABLISHING:
77 return "REESTABLISHING";
78 case TERMINATING:
79 return "TERMINATING";
80 case TERMINATED:
81 return "TERMINATED";
82 default:
83 return "UNKNOWN";
84 }
85 }
86
87 private State() {
88 }
89 }
90
91 /**
92 * Listener for events relating to an IMS session, such as when a session is being
93 * recieved ("on ringing") or a call is outgoing ("on calling").
94 * <p>Many of these events are also received by {@link ImsCall.Listener}.</p>
Brad Ebingerf8c3cd82018-01-22 13:51:52 -080095 * @hide
Brad Ebinger21013dc2017-02-02 16:21:22 -080096 */
97 public static class Listener {
98 /**
99 * Called when a request is sent out to initiate a new session
100 * and 1xx response is received from the network.
101 *
102 * @param session the session object that carries out the IMS session
103 */
104 public void callSessionProgressing(ImsCallSession session,
105 ImsStreamMediaProfile profile) {
106 // no-op
107 }
108
109 /**
110 * Called when the session is established.
111 *
112 * @param session the session object that carries out the IMS session
113 */
114 public void callSessionStarted(ImsCallSession session,
115 ImsCallProfile profile) {
116 // no-op
117 }
118
119 /**
120 * Called when the session establishment is failed.
121 *
122 * @param session the session object that carries out the IMS session
123 * @param reasonInfo detailed reason of the session establishment failure
124 */
125 public void callSessionStartFailed(ImsCallSession session,
126 ImsReasonInfo reasonInfo) {
127 }
128
129 /**
130 * Called when the session is terminated.
131 *
132 * @param session the session object that carries out the IMS session
133 * @param reasonInfo detailed reason of the session termination
134 */
135 public void callSessionTerminated(ImsCallSession session,
136 ImsReasonInfo reasonInfo) {
137 }
138
139 /**
140 * Called when the session is in hold.
141 *
142 * @param session the session object that carries out the IMS session
143 */
144 public void callSessionHeld(ImsCallSession session,
145 ImsCallProfile profile) {
146 }
147
148 /**
149 * Called when the session hold is failed.
150 *
151 * @param session the session object that carries out the IMS session
152 * @param reasonInfo detailed reason of the session hold failure
153 */
154 public void callSessionHoldFailed(ImsCallSession session,
155 ImsReasonInfo reasonInfo) {
156 }
157
158 /**
159 * Called when the session hold is received from the remote user.
160 *
161 * @param session the session object that carries out the IMS session
162 */
163 public void callSessionHoldReceived(ImsCallSession session,
164 ImsCallProfile profile) {
165 }
166
167 /**
168 * Called when the session resume is done.
169 *
170 * @param session the session object that carries out the IMS session
171 */
172 public void callSessionResumed(ImsCallSession session,
173 ImsCallProfile profile) {
174 }
175
176 /**
177 * Called when the session resume is failed.
178 *
179 * @param session the session object that carries out the IMS session
180 * @param reasonInfo detailed reason of the session resume failure
181 */
182 public void callSessionResumeFailed(ImsCallSession session,
183 ImsReasonInfo reasonInfo) {
184 }
185
186 /**
187 * Called when the session resume is received from the remote user.
188 *
189 * @param session the session object that carries out the IMS session
190 */
191 public void callSessionResumeReceived(ImsCallSession session,
192 ImsCallProfile profile) {
193 }
194
195 /**
196 * Called when the session merge has been started. At this point, the {@code newSession}
197 * represents the session which has been initiated to the IMS conference server for the
198 * new merged conference.
199 *
200 * @param session the session object that carries out the IMS session
201 * @param newSession the session object that is merged with an active & hold session
202 */
203 public void callSessionMergeStarted(ImsCallSession session,
204 ImsCallSession newSession, ImsCallProfile profile) {
205 }
206
207 /**
208 * Called when the session merge is successful and the merged session is active.
209 *
210 * @param session the session object that carries out the IMS session
211 */
212 public void callSessionMergeComplete(ImsCallSession session) {
213 }
214
215 /**
216 * Called when the session merge has failed.
217 *
218 * @param session the session object that carries out the IMS session
219 * @param reasonInfo detailed reason of the call merge failure
220 */
221 public void callSessionMergeFailed(ImsCallSession session,
222 ImsReasonInfo reasonInfo) {
223 }
224
225 /**
226 * Called when the session is updated (except for hold/unhold).
227 *
228 * @param session the session object that carries out the IMS session
229 */
230 public void callSessionUpdated(ImsCallSession session,
231 ImsCallProfile profile) {
232 }
233
234 /**
235 * Called when the session update is failed.
236 *
237 * @param session the session object that carries out the IMS session
238 * @param reasonInfo detailed reason of the session update failure
239 */
240 public void callSessionUpdateFailed(ImsCallSession session,
241 ImsReasonInfo reasonInfo) {
242 }
243
244 /**
245 * Called when the session update is received from the remote user.
246 *
247 * @param session the session object that carries out the IMS session
248 */
249 public void callSessionUpdateReceived(ImsCallSession session,
250 ImsCallProfile profile) {
251 // no-op
252 }
253
254 /**
255 * Called when the session is extended to the conference session.
256 *
257 * @param session the session object that carries out the IMS session
258 * @param newSession the session object that is extended to the conference
259 * from the active session
260 */
261 public void callSessionConferenceExtended(ImsCallSession session,
262 ImsCallSession newSession, ImsCallProfile profile) {
263 }
264
265 /**
266 * Called when the conference extension is failed.
267 *
268 * @param session the session object that carries out the IMS session
269 * @param reasonInfo detailed reason of the conference extension failure
270 */
271 public void callSessionConferenceExtendFailed(ImsCallSession session,
272 ImsReasonInfo reasonInfo) {
273 }
274
275 /**
276 * Called when the conference extension is received from the remote user.
277 *
278 * @param session the session object that carries out the IMS session
279 */
280 public void callSessionConferenceExtendReceived(ImsCallSession session,
281 ImsCallSession newSession, ImsCallProfile profile) {
282 // no-op
283 }
284
285 /**
286 * Called when the invitation request of the participants is delivered to the conference
287 * server.
288 *
289 * @param session the session object that carries out the IMS session
290 */
291 public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) {
292 // no-op
293 }
294
295 /**
296 * Called when the invitation request of the participants is failed.
297 *
298 * @param session the session object that carries out the IMS session
299 * @param reasonInfo detailed reason of the conference invitation failure
300 */
301 public void callSessionInviteParticipantsRequestFailed(ImsCallSession session,
302 ImsReasonInfo reasonInfo) {
303 // no-op
304 }
305
306 /**
307 * Called when the removal request of the participants is delivered to the conference
308 * server.
309 *
310 * @param session the session object that carries out the IMS session
311 */
312 public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) {
313 // no-op
314 }
315
316 /**
317 * Called when the removal request of the participants is failed.
318 *
319 * @param session the session object that carries out the IMS session
320 * @param reasonInfo detailed reason of the conference removal failure
321 */
322 public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session,
323 ImsReasonInfo reasonInfo) {
324 // no-op
325 }
326
327 /**
328 * Called when the conference state is updated.
329 *
330 * @param session the session object that carries out the IMS session
331 */
332 public void callSessionConferenceStateUpdated(ImsCallSession session,
333 ImsConferenceState state) {
334 // no-op
335 }
336
337 /**
338 * Called when the USSD message is received from the network.
339 *
340 * @param mode mode of the USSD message (REQUEST / NOTIFY)
341 * @param ussdMessage USSD message
342 */
343 public void callSessionUssdMessageReceived(ImsCallSession session,
344 int mode, String ussdMessage) {
345 // no-op
346 }
347
348 /**
Tyler Gunn3a5130c2017-06-09 13:16:06 -0700349 * Called when an {@link ImsCallSession} may handover from one radio technology to another.
350 * For example, the session may handover from WIFI to LTE if conditions are right.
351 * <p>
352 * If handover is attempted,
353 * {@link #callSessionHandover(ImsCallSession, int, int, ImsReasonInfo)} or
354 * {@link #callSessionHandoverFailed(ImsCallSession, int, int, ImsReasonInfo)} will be
355 * called to indicate the success or failure of the handover.
356 *
357 * @param session IMS session object
358 * @param srcAccessTech original access technology
359 * @param targetAccessTech new access technology
360 */
361 public void callSessionMayHandover(ImsCallSession session, int srcAccessTech,
362 int targetAccessTech) {
363 // no-op
364 }
365
366 /**
Brad Ebinger21013dc2017-02-02 16:21:22 -0800367 * Called when session access technology changes
368 *
369 * @param session IMS session object
370 * @param srcAccessTech original access technology
371 * @param targetAccessTech new access technology
372 * @param reasonInfo
373 */
374 public void callSessionHandover(ImsCallSession session,
375 int srcAccessTech, int targetAccessTech,
376 ImsReasonInfo reasonInfo) {
377 // no-op
378 }
379
380 /**
381 * Called when session access technology change fails
382 *
383 * @param session IMS session object
384 * @param srcAccessTech original access technology
385 * @param targetAccessTech new access technology
386 * @param reasonInfo handover failure reason
387 */
388 public void callSessionHandoverFailed(ImsCallSession session,
389 int srcAccessTech, int targetAccessTech,
390 ImsReasonInfo reasonInfo) {
391 // no-op
392 }
393
394 /**
395 * Called when TTY mode of remote party changed
396 *
397 * @param session IMS session object
398 * @param mode TTY mode of remote party
399 */
400 public void callSessionTtyModeReceived(ImsCallSession session,
401 int mode) {
402 // no-op
403 }
404
405 /**
406 * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
407 *
408 * @param session The call session.
409 * @param isMultiParty {@code true} if the session became multiparty, {@code false}
410 * otherwise.
411 */
412 public void callSessionMultipartyStateChanged(ImsCallSession session,
413 boolean isMultiParty) {
414 // no-op
415 }
416
417 /**
418 * Called when the session supplementary service is received
419 *
420 * @param session the session object that carries out the IMS session
421 */
422 public void callSessionSuppServiceReceived(ImsCallSession session,
423 ImsSuppServiceNotification suppServiceInfo) {
424 }
Anju Mathapati7e177da2017-01-24 11:58:28 -0800425
426 /**
427 * Received RTT modify request from Remote Party
428 */
429 public void callSessionRttModifyRequestReceived(ImsCallSession session,
430 ImsCallProfile callProfile) {
431 // no-op
432 }
433
434 /**
435 * Received response for RTT modify request
436 */
437 public void callSessionRttModifyResponseReceived(int status) {
438 // no -op
439 }
440
441 /**
442 * Device received RTT message from Remote UE
443 */
444 public void callSessionRttMessageReceived(String rttMessage) {
445 // no-op
446 }
Wileen Chiuf2ec2982018-07-01 14:21:50 -0700447
448 /**
449 * While in call, there has been a change in RTT audio indicator.
450 */
451 public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
452 // no-op
453 }
Jordan Liu8218ddd2018-11-28 11:22:39 -0800454
455 /**
456 * Called when the IMS service reports a change to the call quality.
457 */
458 public void callQualityChanged(CallQuality callQuality) {
459 // no-op
460 }
Brad Ebinger21013dc2017-02-02 16:21:22 -0800461 }
462
463 private final IImsCallSession miSession;
464 private boolean mClosed = false;
465 private Listener mListener;
466
Brad Ebingerf8c3cd82018-01-22 13:51:52 -0800467 /** @hide */
Brad Ebinger21013dc2017-02-02 16:21:22 -0800468 public ImsCallSession(IImsCallSession iSession) {
469 miSession = iSession;
470
471 if (iSession != null) {
472 try {
473 iSession.setListener(new IImsCallSessionListenerProxy());
474 } catch (RemoteException e) {
475 }
476 } else {
477 mClosed = true;
478 }
479 }
480
Brad Ebingerf8c3cd82018-01-22 13:51:52 -0800481 /** @hide */
Brad Ebinger21013dc2017-02-02 16:21:22 -0800482 public ImsCallSession(IImsCallSession iSession, Listener listener) {
483 this(iSession);
484 setListener(listener);
485 }
486
487 /**
488 * Closes this object. This object is not usable after being closed.
489 */
Brad Ebingerf8c3cd82018-01-22 13:51:52 -0800490 public void close() {
491 synchronized (this) {
492 if (mClosed) {
493 return;
494 }
Brad Ebinger21013dc2017-02-02 16:21:22 -0800495
Brad Ebingerf8c3cd82018-01-22 13:51:52 -0800496 try {
497 miSession.close();
498 mClosed = true;
499 } catch (RemoteException e) {
500 }
Brad Ebinger21013dc2017-02-02 16:21:22 -0800501 }
502 }
503
504 /**
505 * Gets the call ID of the session.
506 *
507 * @return the call ID
508 */
509 public String getCallId() {
510 if (mClosed) {
511 return null;
512 }
513
514 try {
515 return miSession.getCallId();
516 } catch (RemoteException e) {
517 return null;
518 }
519 }
520
521 /**
522 * Gets the call profile that this session is associated with
523 *
524 * @return the call profile that this session is associated with
525 */
526 public ImsCallProfile getCallProfile() {
527 if (mClosed) {
528 return null;
529 }
530
531 try {
532 return miSession.getCallProfile();
533 } catch (RemoteException e) {
534 return null;
535 }
536 }
537
538 /**
539 * Gets the local call profile that this session is associated with
540 *
541 * @return the local call profile that this session is associated with
542 */
543 public ImsCallProfile getLocalCallProfile() {
544 if (mClosed) {
545 return null;
546 }
547
548 try {
549 return miSession.getLocalCallProfile();
550 } catch (RemoteException e) {
551 return null;
552 }
553 }
554
555 /**
556 * Gets the remote call profile that this session is associated with
557 *
558 * @return the remote call profile that this session is associated with
559 */
560 public ImsCallProfile getRemoteCallProfile() {
561 if (mClosed) {
562 return null;
563 }
564
565 try {
566 return miSession.getRemoteCallProfile();
567 } catch (RemoteException e) {
568 return null;
569 }
570 }
571
572 /**
573 * Gets the video call provider for the session.
574 *
575 * @return The video call provider.
Brad Ebingerf8c3cd82018-01-22 13:51:52 -0800576 * @hide
Brad Ebinger21013dc2017-02-02 16:21:22 -0800577 */
578 public IImsVideoCallProvider getVideoCallProvider() {
579 if (mClosed) {
580 return null;
581 }
582
583 try {
584 return miSession.getVideoCallProvider();
585 } catch (RemoteException e) {
586 return null;
587 }
588 }
589
590 /**
591 * Gets the value associated with the specified property of this session.
592 *
593 * @return the string value associated with the specified property
594 */
595 public String getProperty(String name) {
596 if (mClosed) {
597 return null;
598 }
599
600 try {
601 return miSession.getProperty(name);
602 } catch (RemoteException e) {
603 return null;
604 }
605 }
606
607 /**
608 * Gets the session state.
609 * The value returned must be one of the states in {@link State}.
610 *
611 * @return the session state
612 */
613 public int getState() {
614 if (mClosed) {
615 return State.INVALID;
616 }
617
618 try {
619 return miSession.getState();
620 } catch (RemoteException e) {
621 return State.INVALID;
622 }
623 }
624
625 /**
626 * Determines if the {@link ImsCallSession} is currently alive (e.g. not in a terminated or
627 * closed state).
628 *
629 * @return {@code True} if the session is alive.
630 */
631 public boolean isAlive() {
632 if (mClosed) {
633 return false;
634 }
635
636 int state = getState();
637 switch (state) {
638 case State.IDLE:
639 case State.INITIATED:
640 case State.NEGOTIATING:
641 case State.ESTABLISHING:
642 case State.ESTABLISHED:
643 case State.RENEGOTIATING:
644 case State.REESTABLISHING:
645 return true;
646 default:
647 return false;
648 }
649 }
650
651 /**
652 * Gets the native IMS call session.
653 * @hide
654 */
655 public IImsCallSession getSession() {
656 return miSession;
657 }
658
659 /**
660 * Checks if the session is in call.
661 *
662 * @return true if the session is in call
663 */
664 public boolean isInCall() {
665 if (mClosed) {
666 return false;
667 }
668
669 try {
670 return miSession.isInCall();
671 } catch (RemoteException e) {
672 return false;
673 }
674 }
675
676 /**
677 * Sets the listener to listen to the session events. A {@link ImsCallSession}
678 * can only hold one listener at a time. Subsequent calls to this method
679 * override the previous listener.
680 *
681 * @param listener to listen to the session events of this object
Brad Ebingerf8c3cd82018-01-22 13:51:52 -0800682 * @hide
Brad Ebinger21013dc2017-02-02 16:21:22 -0800683 */
684 public void setListener(Listener listener) {
685 mListener = listener;
686 }
687
688 /**
689 * Mutes or unmutes the mic for the active call.
690 *
691 * @param muted true if the call is muted, false otherwise
692 */
693 public void setMute(boolean muted) {
694 if (mClosed) {
695 return;
696 }
697
698 try {
699 miSession.setMute(muted);
700 } catch (RemoteException e) {
701 }
702 }
703
704 /**
705 * Initiates an IMS call with the specified target and call profile.
706 * The session listener is called back upon defined session events.
707 * The method is only valid to call when the session state is in
708 * {@link ImsCallSession.State#IDLE}.
709 *
710 * @param callee dialed string to make the call to
711 * @param profile call profile to make the call with the specified service type,
712 * call type and media information
713 * @see Listener#callSessionStarted, Listener#callSessionStartFailed
714 */
715 public void start(String callee, ImsCallProfile profile) {
716 if (mClosed) {
717 return;
718 }
719
720 try {
721 miSession.start(callee, profile);
722 } catch (RemoteException e) {
723 }
724 }
725
726 /**
727 * Initiates an IMS conference call with the specified target and call profile.
728 * The session listener is called back upon defined session events.
729 * The method is only valid to call when the session state is in
730 * {@link ImsCallSession.State#IDLE}.
731 *
732 * @param participants participant list to initiate an IMS conference call
733 * @param profile call profile to make the call with the specified service type,
734 * call type and media information
735 * @see Listener#callSessionStarted, Listener#callSessionStartFailed
736 */
737 public void start(String[] participants, ImsCallProfile profile) {
738 if (mClosed) {
739 return;
740 }
741
742 try {
743 miSession.startConference(participants, profile);
744 } catch (RemoteException e) {
745 }
746 }
747
748 /**
749 * Accepts an incoming call or session update.
750 *
751 * @param callType call type specified in {@link ImsCallProfile} to be answered
752 * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
753 * @see Listener#callSessionStarted
754 */
755 public void accept(int callType, ImsStreamMediaProfile profile) {
756 if (mClosed) {
757 return;
758 }
759
760 try {
761 miSession.accept(callType, profile);
762 } catch (RemoteException e) {
763 }
764 }
765
766 /**
Pooja Jaind34698d2017-12-28 14:15:31 +0530767 * Deflects an incoming call.
768 *
769 * @param number number to be deflected to
770 */
771 public void deflect(String number) {
772 if (mClosed) {
773 return;
774 }
775
776 try {
777 miSession.deflect(number);
778 } catch (RemoteException e) {
779 }
780 }
781
782 /**
Brad Ebinger21013dc2017-02-02 16:21:22 -0800783 * Rejects an incoming call or session update.
784 *
785 * @param reason reason code to reject an incoming call
786 * @see Listener#callSessionStartFailed
787 */
788 public void reject(int reason) {
789 if (mClosed) {
790 return;
791 }
792
793 try {
794 miSession.reject(reason);
795 } catch (RemoteException e) {
796 }
797 }
798
799 /**
800 * Terminates a call.
801 *
802 * @see Listener#callSessionTerminated
803 */
804 public void terminate(int reason) {
805 if (mClosed) {
806 return;
807 }
808
809 try {
810 miSession.terminate(reason);
811 } catch (RemoteException e) {
812 }
813 }
814
815 /**
816 * Puts a call on hold. When it succeeds, {@link Listener#callSessionHeld} is called.
817 *
818 * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call
819 * @see Listener#callSessionHeld, Listener#callSessionHoldFailed
820 */
821 public void hold(ImsStreamMediaProfile profile) {
822 if (mClosed) {
823 return;
824 }
825
826 try {
827 miSession.hold(profile);
828 } catch (RemoteException e) {
829 }
830 }
831
832 /**
833 * Continues a call that's on hold. When it succeeds,
834 * {@link Listener#callSessionResumed} is called.
835 *
836 * @param profile stream media profile {@link ImsStreamMediaProfile} to resume the call
837 * @see Listener#callSessionResumed, Listener#callSessionResumeFailed
838 */
839 public void resume(ImsStreamMediaProfile profile) {
840 if (mClosed) {
841 return;
842 }
843
844 try {
845 miSession.resume(profile);
846 } catch (RemoteException e) {
847 }
848 }
849
850 /**
851 * Merges the active & hold call. When it succeeds,
852 * {@link Listener#callSessionMergeStarted} is called.
853 *
854 * @see Listener#callSessionMergeStarted , Listener#callSessionMergeFailed
855 */
856 public void merge() {
857 if (mClosed) {
858 return;
859 }
860
861 try {
862 miSession.merge();
863 } catch (RemoteException e) {
864 }
865 }
866
867 /**
868 * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
869 *
870 * @param callType call type specified in {@link ImsCallProfile} to be updated
871 * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated
872 * @see Listener#callSessionUpdated, Listener#callSessionUpdateFailed
873 */
874 public void update(int callType, ImsStreamMediaProfile profile) {
875 if (mClosed) {
876 return;
877 }
878
879 try {
880 miSession.update(callType, profile);
881 } catch (RemoteException e) {
882 }
883 }
884
885 /**
886 * Extends this call to the conference call with the specified recipients.
887 *
888 * @param participants list to be invited to the conference call after extending the call
889 * @see Listener#callSessionConferenceExtended
890 * @see Listener#callSessionConferenceExtendFailed
891 */
892 public void extendToConference(String[] participants) {
893 if (mClosed) {
894 return;
895 }
896
897 try {
898 miSession.extendToConference(participants);
899 } catch (RemoteException e) {
900 }
901 }
902
903 /**
904 * Requests the conference server to invite an additional participants to the conference.
905 *
906 * @param participants list to be invited to the conference call
907 * @see Listener#callSessionInviteParticipantsRequestDelivered
908 * @see Listener#callSessionInviteParticipantsRequestFailed
909 */
910 public void inviteParticipants(String[] participants) {
911 if (mClosed) {
912 return;
913 }
914
915 try {
916 miSession.inviteParticipants(participants);
917 } catch (RemoteException e) {
918 }
919 }
920
921 /**
922 * Requests the conference server to remove the specified participants from the conference.
923 *
924 * @param participants participant list to be removed from the conference call
925 * @see Listener#callSessionRemoveParticipantsRequestDelivered
926 * @see Listener#callSessionRemoveParticipantsRequestFailed
927 */
928 public void removeParticipants(String[] participants) {
929 if (mClosed) {
930 return;
931 }
932
933 try {
934 miSession.removeParticipants(participants);
935 } catch (RemoteException e) {
936 }
937 }
938
939
940 /**
941 * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
942 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
943 * and event flash to 16. Currently, event flash is not supported.
944 *
945 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
946 */
947 public void sendDtmf(char c, Message result) {
948 if (mClosed) {
949 return;
950 }
951
952 try {
953 miSession.sendDtmf(c, result);
954 } catch (RemoteException e) {
955 }
956 }
957
958 /**
959 * Starts a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
960 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
961 * and event flash to 16. Currently, event flash is not supported.
962 *
963 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
964 */
965 public void startDtmf(char c) {
966 if (mClosed) {
967 return;
968 }
969
970 try {
971 miSession.startDtmf(c);
972 } catch (RemoteException e) {
973 }
974 }
975
976 /**
977 * Stops a DTMF code.
978 */
979 public void stopDtmf() {
980 if (mClosed) {
981 return;
982 }
983
984 try {
985 miSession.stopDtmf();
986 } catch (RemoteException e) {
987 }
988 }
989
990 /**
991 * Sends an USSD message.
992 *
993 * @param ussdMessage USSD message to send
994 */
995 public void sendUssd(String ussdMessage) {
996 if (mClosed) {
997 return;
998 }
999
1000 try {
1001 miSession.sendUssd(ussdMessage);
1002 } catch (RemoteException e) {
1003 }
1004 }
1005
1006 /**
1007 * Determines if the session is multiparty.
1008 *
1009 * @return {@code True} if the session is multiparty.
1010 */
1011 public boolean isMultiparty() {
1012 if (mClosed) {
1013 return false;
1014 }
1015
1016 try {
1017 return miSession.isMultiparty();
1018 } catch (RemoteException e) {
1019 return false;
1020 }
1021 }
1022
1023 /**
Anju Mathapati7e177da2017-01-24 11:58:28 -08001024 * Sends Rtt Message
1025 *
1026 * @param rttMessage rtt text to be sent
Anju Mathapati7e177da2017-01-24 11:58:28 -08001027 */
1028 public void sendRttMessage(String rttMessage) {
1029 if (mClosed) {
1030 return;
1031 }
1032
1033 try {
1034 miSession.sendRttMessage(rttMessage);
1035 } catch (RemoteException e) {
1036 }
1037 }
1038
1039 /**
Hall Liu137d35f2018-09-26 17:38:18 -07001040 * Sends RTT Upgrade or downgrade request
Anju Mathapati7e177da2017-01-24 11:58:28 -08001041 *
Hall Liu137d35f2018-09-26 17:38:18 -07001042 * @param to Profile with the RTT flag set to the desired value
Anju Mathapati7e177da2017-01-24 11:58:28 -08001043 */
1044 public void sendRttModifyRequest(ImsCallProfile to) {
1045 if (mClosed) {
1046 return;
1047 }
1048
1049 try {
1050 miSession.sendRttModifyRequest(to);
1051 } catch (RemoteException e) {
1052 }
1053 }
1054
1055 /**
1056 * Sends RTT Upgrade response
1057 *
1058 * @param response : response for upgrade
Anju Mathapati7e177da2017-01-24 11:58:28 -08001059 */
1060 public void sendRttModifyResponse(boolean response) {
1061 if (mClosed) {
1062 return;
1063 }
1064
1065 try {
1066 miSession.sendRttModifyResponse(response);
1067 } catch (RemoteException e) {
1068 }
1069 }
1070
1071 /**
Brad Ebinger21013dc2017-02-02 16:21:22 -08001072 * A listener type for receiving notification on IMS call session events.
1073 * When an event is generated for an {@link IImsCallSession},
1074 * the application is notified by having one of the methods called on
1075 * the {@link IImsCallSessionListener}.
1076 */
Brad Ebinger26462542018-01-11 10:27:43 -08001077 private class IImsCallSessionListenerProxy extends IImsCallSessionListener.Stub {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001078 /**
1079 * Notifies the result of the basic session operation (setup / terminate).
1080 */
1081 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001082 public void callSessionProgressing(ImsStreamMediaProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001083 if (mListener != null) {
1084 mListener.callSessionProgressing(ImsCallSession.this, profile);
1085 }
1086 }
1087
1088 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001089 public void callSessionInitiated(ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001090 if (mListener != null) {
1091 mListener.callSessionStarted(ImsCallSession.this, profile);
1092 }
1093 }
1094
1095 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001096 public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001097 if (mListener != null) {
1098 mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
1099 }
1100 }
1101
1102 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001103 public void callSessionTerminated(ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001104 if (mListener != null) {
1105 mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
1106 }
1107 }
1108
1109 /**
1110 * Notifies the result of the call hold/resume operation.
1111 */
1112 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001113 public void callSessionHeld(ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001114 if (mListener != null) {
1115 mListener.callSessionHeld(ImsCallSession.this, profile);
1116 }
1117 }
1118
1119 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001120 public void callSessionHoldFailed(ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001121 if (mListener != null) {
1122 mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
1123 }
1124 }
1125
1126 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001127 public void callSessionHoldReceived(ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001128 if (mListener != null) {
1129 mListener.callSessionHoldReceived(ImsCallSession.this, profile);
1130 }
1131 }
1132
1133 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001134 public void callSessionResumed(ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001135 if (mListener != null) {
1136 mListener.callSessionResumed(ImsCallSession.this, profile);
1137 }
1138 }
1139
1140 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001141 public void callSessionResumeFailed(ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001142 if (mListener != null) {
1143 mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
1144 }
1145 }
1146
1147 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001148 public void callSessionResumeReceived(ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001149 if (mListener != null) {
1150 mListener.callSessionResumeReceived(ImsCallSession.this, profile);
1151 }
1152 }
1153
1154 /**
1155 * Notifies the start of a call merge operation.
1156 *
Brad Ebinger21013dc2017-02-02 16:21:22 -08001157 * @param newSession The merged call session.
1158 * @param profile The call profile.
1159 */
1160 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001161 public void callSessionMergeStarted(IImsCallSession newSession, ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001162 // This callback can be used for future use to add additional
1163 // functionality that may be needed between conference start and complete
1164 Log.d(TAG, "callSessionMergeStarted");
1165 }
1166
1167 /**
1168 * Notifies the successful completion of a call merge operation.
1169 *
1170 * @param newSession The call session.
1171 */
1172 @Override
1173 public void callSessionMergeComplete(IImsCallSession newSession) {
1174 if (mListener != null) {
1175 if (newSession != null) {
Ravi Palurice4be272019-11-14 16:50:24 +05301176 // New session created after conference
1177 mListener.callSessionMergeComplete(new ImsCallSession(newSession));
Brad Ebinger21013dc2017-02-02 16:21:22 -08001178 } else {
1179 // Session already exists. Hence no need to pass
1180 mListener.callSessionMergeComplete(null);
1181 }
1182 }
1183 }
1184
1185 /**
1186 * Notifies of a failure to perform a call merge operation.
1187 *
Brad Ebinger21013dc2017-02-02 16:21:22 -08001188 * @param reasonInfo The merge failure reason.
1189 */
1190 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001191 public void callSessionMergeFailed(ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001192 if (mListener != null) {
1193 mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
1194 }
1195 }
1196
1197 /**
1198 * Notifies the result of call upgrade / downgrade or any other call updates.
1199 */
1200 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001201 public void callSessionUpdated(ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001202 if (mListener != null) {
1203 mListener.callSessionUpdated(ImsCallSession.this, profile);
1204 }
1205 }
1206
1207 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001208 public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001209 if (mListener != null) {
1210 mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
1211 }
1212 }
1213
1214 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001215 public void callSessionUpdateReceived(ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001216 if (mListener != null) {
1217 mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
1218 }
1219 }
1220
1221 /**
1222 * Notifies the result of conference extension.
1223 */
1224 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001225 public void callSessionConferenceExtended(IImsCallSession newSession,
1226 ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001227 if (mListener != null) {
1228 mListener.callSessionConferenceExtended(ImsCallSession.this,
1229 new ImsCallSession(newSession), profile);
1230 }
1231 }
1232
1233 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001234 public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001235 if (mListener != null) {
1236 mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo);
1237 }
1238 }
1239
1240 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001241 public void callSessionConferenceExtendReceived(IImsCallSession newSession,
1242 ImsCallProfile profile) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001243 if (mListener != null) {
1244 mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
1245 new ImsCallSession(newSession), profile);
1246 }
1247 }
1248
1249 /**
1250 * Notifies the result of the participant invitation / removal to/from
1251 * the conference session.
1252 */
1253 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001254 public void callSessionInviteParticipantsRequestDelivered() {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001255 if (mListener != null) {
1256 mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this);
1257 }
1258 }
1259
1260 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001261 public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001262 if (mListener != null) {
1263 mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
1264 reasonInfo);
1265 }
1266 }
1267
1268 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001269 public void callSessionRemoveParticipantsRequestDelivered() {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001270 if (mListener != null) {
1271 mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
1272 }
1273 }
1274
1275 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001276 public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001277 if (mListener != null) {
1278 mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
1279 reasonInfo);
1280 }
1281 }
1282
1283 /**
1284 * Notifies the changes of the conference info. in the conference session.
1285 */
1286 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001287 public void callSessionConferenceStateUpdated(ImsConferenceState state) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001288 if (mListener != null) {
1289 mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
1290 }
1291 }
1292
1293 /**
1294 * Notifies the incoming USSD message.
1295 */
1296 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001297 public void callSessionUssdMessageReceived(int mode, String ussdMessage) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001298 if (mListener != null) {
1299 mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage);
1300 }
1301 }
1302
1303 /**
Brad Ebingerf8c3cd82018-01-22 13:51:52 -08001304 * Notifies of a case where a {@link ImsCallSession} may
Tyler Gunn3a5130c2017-06-09 13:16:06 -07001305 * potentially handover from one radio technology to another.
Tyler Gunn3a5130c2017-06-09 13:16:06 -07001306 * @param srcAccessTech The source radio access technology; one of the access technology
1307 * constants defined in {@link android.telephony.ServiceState}. For
1308 * example
1309 * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
1310 * @param targetAccessTech The target radio access technology; one of the access technology
1311 * constants defined in {@link android.telephony.ServiceState}. For
1312 * example
1313 * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
1314 */
1315 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001316 public void callSessionMayHandover(int srcAccessTech, int targetAccessTech) {
Tyler Gunn3a5130c2017-06-09 13:16:06 -07001317 if (mListener != null) {
1318 mListener.callSessionMayHandover(ImsCallSession.this, srcAccessTech,
1319 targetAccessTech);
1320 }
1321 }
1322
1323 /**
Brad Ebinger21013dc2017-02-02 16:21:22 -08001324 * Notifies of handover information for this call
1325 */
1326 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001327 public void callSessionHandover(int srcAccessTech, int targetAccessTech,
1328 ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001329 if (mListener != null) {
1330 mListener.callSessionHandover(ImsCallSession.this, srcAccessTech,
1331 targetAccessTech, reasonInfo);
1332 }
1333 }
1334
1335 /**
1336 * Notifies of handover failure info for this call
1337 */
1338 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001339 public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
1340 ImsReasonInfo reasonInfo) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001341 if (mListener != null) {
1342 mListener.callSessionHandoverFailed(ImsCallSession.this, srcAccessTech,
1343 targetAccessTech, reasonInfo);
1344 }
1345 }
1346
1347 /**
1348 * Notifies the TTY mode received from remote party.
1349 */
1350 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001351 public void callSessionTtyModeReceived(int mode) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001352 if (mListener != null) {
1353 mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
1354 }
1355 }
1356
1357 /**
1358 * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
1359 *
Brad Ebinger21013dc2017-02-02 16:21:22 -08001360 * @param isMultiParty {@code true} if the session became multiparty, {@code false}
1361 * otherwise.
1362 */
Brad Ebinger26462542018-01-11 10:27:43 -08001363 public void callSessionMultipartyStateChanged(boolean isMultiParty) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001364 if (mListener != null) {
1365 mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty);
1366 }
1367 }
1368
1369 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001370 public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppServiceInfo ) {
Brad Ebinger21013dc2017-02-02 16:21:22 -08001371 if (mListener != null) {
1372 mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo);
1373 }
1374 }
1375
Anju Mathapati7e177da2017-01-24 11:58:28 -08001376 /**
1377 * Received RTT modify request from remote party
1378 */
1379 @Override
Brad Ebinger26462542018-01-11 10:27:43 -08001380 public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile) {
Anju Mathapati7e177da2017-01-24 11:58:28 -08001381 if (mListener != null) {
1382 mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, callProfile);
1383 }
1384 }
1385
1386 /**
1387 * Received response for RTT modify request
1388 */
1389 @Override
1390 public void callSessionRttModifyResponseReceived(int status) {
1391 if (mListener != null) {
1392 mListener.callSessionRttModifyResponseReceived(status);
1393 }
1394 }
1395
1396 /**
1397 * RTT Message received
1398 */
1399 @Override
1400 public void callSessionRttMessageReceived(String rttMessage) {
1401 if (mListener != null) {
1402 mListener.callSessionRttMessageReceived(rttMessage);
1403 }
1404 }
Wileen Chiuf2ec2982018-07-01 14:21:50 -07001405
1406 /**
1407 * While in call, there has been a change in RTT audio indicator.
1408 */
1409 @Override
1410 public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
1411 if (mListener != null) {
1412 mListener.callSessionRttAudioIndicatorChanged(profile);
1413 }
1414 }
Jordan Liu8218ddd2018-11-28 11:22:39 -08001415
1416 /**
1417 * Call quality updated
1418 */
1419 @Override
1420 public void callQualityChanged(CallQuality callQuality) {
1421 if (mListener != null) {
1422 mListener.callQualityChanged(callQuality);
1423 }
1424 }
Brad Ebinger21013dc2017-02-02 16:21:22 -08001425 }
1426
1427 /**
1428 * Provides a string representation of the {@link ImsCallSession}. Primarily intended for
1429 * use in log statements.
1430 *
1431 * @return String representation of session.
1432 */
1433 @Override
1434 public String toString() {
1435 StringBuilder sb = new StringBuilder();
1436 sb.append("[ImsCallSession objId:");
1437 sb.append(System.identityHashCode(this));
1438 sb.append(" state:");
1439 sb.append(State.toString(getState()));
1440 sb.append(" callId:");
1441 sb.append(getCallId());
1442 sb.append("]");
1443 return sb.toString();
1444 }
1445}