blob: f20f7c8819582e3afdfa7191b4ea5f7283862367 [file] [log] [blame]
Brad Ebinger21013dc2017-02-02 16:21:22 -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.ims.internal;
18
19import android.os.Message;
20import android.os.RemoteException;
21
22import java.util.Objects;
23
24import android.telephony.ims.stub.ImsCallSessionListenerImplBase;
25import android.util.Log;
26import com.android.ims.ImsCallProfile;
27import com.android.ims.ImsConferenceState;
28import com.android.ims.ImsReasonInfo;
29import com.android.ims.ImsStreamMediaProfile;
30import com.android.ims.ImsSuppServiceNotification;
31
32/**
33 * Provides the call initiation/termination, and media exchange between two IMS endpoints.
34 * It directly communicates with IMS service which implements the IMS protocol behavior.
35 *
36 * @hide
37 */
38public class ImsCallSession {
39 private static final String TAG = "ImsCallSession";
40
41 /**
42 * Defines IMS call session state.
43 */
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>
95 */
96 public static class Listener {
97 /**
98 * Called when a request is sent out to initiate a new session
99 * and 1xx response is received from the network.
100 *
101 * @param session the session object that carries out the IMS session
102 */
103 public void callSessionProgressing(ImsCallSession session,
104 ImsStreamMediaProfile profile) {
105 // no-op
106 }
107
108 /**
109 * Called when the session is established.
110 *
111 * @param session the session object that carries out the IMS session
112 */
113 public void callSessionStarted(ImsCallSession session,
114 ImsCallProfile profile) {
115 // no-op
116 }
117
118 /**
119 * Called when the session establishment is failed.
120 *
121 * @param session the session object that carries out the IMS session
122 * @param reasonInfo detailed reason of the session establishment failure
123 */
124 public void callSessionStartFailed(ImsCallSession session,
125 ImsReasonInfo reasonInfo) {
126 }
127
128 /**
129 * Called when the session is terminated.
130 *
131 * @param session the session object that carries out the IMS session
132 * @param reasonInfo detailed reason of the session termination
133 */
134 public void callSessionTerminated(ImsCallSession session,
135 ImsReasonInfo reasonInfo) {
136 }
137
138 /**
139 * Called when the session is in hold.
140 *
141 * @param session the session object that carries out the IMS session
142 */
143 public void callSessionHeld(ImsCallSession session,
144 ImsCallProfile profile) {
145 }
146
147 /**
148 * Called when the session hold is failed.
149 *
150 * @param session the session object that carries out the IMS session
151 * @param reasonInfo detailed reason of the session hold failure
152 */
153 public void callSessionHoldFailed(ImsCallSession session,
154 ImsReasonInfo reasonInfo) {
155 }
156
157 /**
158 * Called when the session hold is received from the remote user.
159 *
160 * @param session the session object that carries out the IMS session
161 */
162 public void callSessionHoldReceived(ImsCallSession session,
163 ImsCallProfile profile) {
164 }
165
166 /**
167 * Called when the session resume is done.
168 *
169 * @param session the session object that carries out the IMS session
170 */
171 public void callSessionResumed(ImsCallSession session,
172 ImsCallProfile profile) {
173 }
174
175 /**
176 * Called when the session resume is failed.
177 *
178 * @param session the session object that carries out the IMS session
179 * @param reasonInfo detailed reason of the session resume failure
180 */
181 public void callSessionResumeFailed(ImsCallSession session,
182 ImsReasonInfo reasonInfo) {
183 }
184
185 /**
186 * Called when the session resume is received from the remote user.
187 *
188 * @param session the session object that carries out the IMS session
189 */
190 public void callSessionResumeReceived(ImsCallSession session,
191 ImsCallProfile profile) {
192 }
193
194 /**
195 * Called when the session merge has been started. At this point, the {@code newSession}
196 * represents the session which has been initiated to the IMS conference server for the
197 * new merged conference.
198 *
199 * @param session the session object that carries out the IMS session
200 * @param newSession the session object that is merged with an active & hold session
201 */
202 public void callSessionMergeStarted(ImsCallSession session,
203 ImsCallSession newSession, ImsCallProfile profile) {
204 }
205
206 /**
207 * Called when the session merge is successful and the merged session is active.
208 *
209 * @param session the session object that carries out the IMS session
210 */
211 public void callSessionMergeComplete(ImsCallSession session) {
212 }
213
214 /**
215 * Called when the session merge has failed.
216 *
217 * @param session the session object that carries out the IMS session
218 * @param reasonInfo detailed reason of the call merge failure
219 */
220 public void callSessionMergeFailed(ImsCallSession session,
221 ImsReasonInfo reasonInfo) {
222 }
223
224 /**
225 * Called when the session is updated (except for hold/unhold).
226 *
227 * @param session the session object that carries out the IMS session
228 */
229 public void callSessionUpdated(ImsCallSession session,
230 ImsCallProfile profile) {
231 }
232
233 /**
234 * Called when the session update is failed.
235 *
236 * @param session the session object that carries out the IMS session
237 * @param reasonInfo detailed reason of the session update failure
238 */
239 public void callSessionUpdateFailed(ImsCallSession session,
240 ImsReasonInfo reasonInfo) {
241 }
242
243 /**
244 * Called when the session update is received from the remote user.
245 *
246 * @param session the session object that carries out the IMS session
247 */
248 public void callSessionUpdateReceived(ImsCallSession session,
249 ImsCallProfile profile) {
250 // no-op
251 }
252
253 /**
254 * Called when the session is extended to the conference session.
255 *
256 * @param session the session object that carries out the IMS session
257 * @param newSession the session object that is extended to the conference
258 * from the active session
259 */
260 public void callSessionConferenceExtended(ImsCallSession session,
261 ImsCallSession newSession, ImsCallProfile profile) {
262 }
263
264 /**
265 * Called when the conference extension is failed.
266 *
267 * @param session the session object that carries out the IMS session
268 * @param reasonInfo detailed reason of the conference extension failure
269 */
270 public void callSessionConferenceExtendFailed(ImsCallSession session,
271 ImsReasonInfo reasonInfo) {
272 }
273
274 /**
275 * Called when the conference extension is received from the remote user.
276 *
277 * @param session the session object that carries out the IMS session
278 */
279 public void callSessionConferenceExtendReceived(ImsCallSession session,
280 ImsCallSession newSession, ImsCallProfile profile) {
281 // no-op
282 }
283
284 /**
285 * Called when the invitation request of the participants is delivered to the conference
286 * server.
287 *
288 * @param session the session object that carries out the IMS session
289 */
290 public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) {
291 // no-op
292 }
293
294 /**
295 * Called when the invitation request of the participants is failed.
296 *
297 * @param session the session object that carries out the IMS session
298 * @param reasonInfo detailed reason of the conference invitation failure
299 */
300 public void callSessionInviteParticipantsRequestFailed(ImsCallSession session,
301 ImsReasonInfo reasonInfo) {
302 // no-op
303 }
304
305 /**
306 * Called when the removal request of the participants is delivered to the conference
307 * server.
308 *
309 * @param session the session object that carries out the IMS session
310 */
311 public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) {
312 // no-op
313 }
314
315 /**
316 * Called when the removal request of the participants is failed.
317 *
318 * @param session the session object that carries out the IMS session
319 * @param reasonInfo detailed reason of the conference removal failure
320 */
321 public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session,
322 ImsReasonInfo reasonInfo) {
323 // no-op
324 }
325
326 /**
327 * Called when the conference state is updated.
328 *
329 * @param session the session object that carries out the IMS session
330 */
331 public void callSessionConferenceStateUpdated(ImsCallSession session,
332 ImsConferenceState state) {
333 // no-op
334 }
335
336 /**
337 * Called when the USSD message is received from the network.
338 *
339 * @param mode mode of the USSD message (REQUEST / NOTIFY)
340 * @param ussdMessage USSD message
341 */
342 public void callSessionUssdMessageReceived(ImsCallSession session,
343 int mode, String ussdMessage) {
344 // no-op
345 }
346
347 /**
348 * Called when session access technology changes
349 *
350 * @param session IMS session object
351 * @param srcAccessTech original access technology
352 * @param targetAccessTech new access technology
353 * @param reasonInfo
354 */
355 public void callSessionHandover(ImsCallSession session,
356 int srcAccessTech, int targetAccessTech,
357 ImsReasonInfo reasonInfo) {
358 // no-op
359 }
360
361 /**
362 * Called when session access technology change fails
363 *
364 * @param session IMS session object
365 * @param srcAccessTech original access technology
366 * @param targetAccessTech new access technology
367 * @param reasonInfo handover failure reason
368 */
369 public void callSessionHandoverFailed(ImsCallSession session,
370 int srcAccessTech, int targetAccessTech,
371 ImsReasonInfo reasonInfo) {
372 // no-op
373 }
374
375 /**
376 * Called when TTY mode of remote party changed
377 *
378 * @param session IMS session object
379 * @param mode TTY mode of remote party
380 */
381 public void callSessionTtyModeReceived(ImsCallSession session,
382 int mode) {
383 // no-op
384 }
385
386 /**
387 * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
388 *
389 * @param session The call session.
390 * @param isMultiParty {@code true} if the session became multiparty, {@code false}
391 * otherwise.
392 */
393 public void callSessionMultipartyStateChanged(ImsCallSession session,
394 boolean isMultiParty) {
395 // no-op
396 }
397
398 /**
399 * Called when the session supplementary service is received
400 *
401 * @param session the session object that carries out the IMS session
402 */
403 public void callSessionSuppServiceReceived(ImsCallSession session,
404 ImsSuppServiceNotification suppServiceInfo) {
405 }
Anju Mathapati7e177da2017-01-24 11:58:28 -0800406
407 /**
408 * Received RTT modify request from Remote Party
409 */
410 public void callSessionRttModifyRequestReceived(ImsCallSession session,
411 ImsCallProfile callProfile) {
412 // no-op
413 }
414
415 /**
416 * Received response for RTT modify request
417 */
418 public void callSessionRttModifyResponseReceived(int status) {
419 // no -op
420 }
421
422 /**
423 * Device received RTT message from Remote UE
424 */
425 public void callSessionRttMessageReceived(String rttMessage) {
426 // no-op
427 }
Brad Ebinger21013dc2017-02-02 16:21:22 -0800428 }
429
430 private final IImsCallSession miSession;
431 private boolean mClosed = false;
432 private Listener mListener;
433
434 public ImsCallSession(IImsCallSession iSession) {
435 miSession = iSession;
436
437 if (iSession != null) {
438 try {
439 iSession.setListener(new IImsCallSessionListenerProxy());
440 } catch (RemoteException e) {
441 }
442 } else {
443 mClosed = true;
444 }
445 }
446
447 public ImsCallSession(IImsCallSession iSession, Listener listener) {
448 this(iSession);
449 setListener(listener);
450 }
451
452 /**
453 * Closes this object. This object is not usable after being closed.
454 */
455 public synchronized void close() {
456 if (mClosed) {
457 return;
458 }
459
460 try {
461 miSession.close();
462 mClosed = true;
463 } catch (RemoteException e) {
464 }
465 }
466
467 /**
468 * Gets the call ID of the session.
469 *
470 * @return the call ID
471 */
472 public String getCallId() {
473 if (mClosed) {
474 return null;
475 }
476
477 try {
478 return miSession.getCallId();
479 } catch (RemoteException e) {
480 return null;
481 }
482 }
483
484 /**
485 * Gets the call profile that this session is associated with
486 *
487 * @return the call profile that this session is associated with
488 */
489 public ImsCallProfile getCallProfile() {
490 if (mClosed) {
491 return null;
492 }
493
494 try {
495 return miSession.getCallProfile();
496 } catch (RemoteException e) {
497 return null;
498 }
499 }
500
501 /**
502 * Gets the local call profile that this session is associated with
503 *
504 * @return the local call profile that this session is associated with
505 */
506 public ImsCallProfile getLocalCallProfile() {
507 if (mClosed) {
508 return null;
509 }
510
511 try {
512 return miSession.getLocalCallProfile();
513 } catch (RemoteException e) {
514 return null;
515 }
516 }
517
518 /**
519 * Gets the remote call profile that this session is associated with
520 *
521 * @return the remote call profile that this session is associated with
522 */
523 public ImsCallProfile getRemoteCallProfile() {
524 if (mClosed) {
525 return null;
526 }
527
528 try {
529 return miSession.getRemoteCallProfile();
530 } catch (RemoteException e) {
531 return null;
532 }
533 }
534
535 /**
536 * Gets the video call provider for the session.
537 *
538 * @return The video call provider.
539 */
540 public IImsVideoCallProvider getVideoCallProvider() {
541 if (mClosed) {
542 return null;
543 }
544
545 try {
546 return miSession.getVideoCallProvider();
547 } catch (RemoteException e) {
548 return null;
549 }
550 }
551
552 /**
553 * Gets the value associated with the specified property of this session.
554 *
555 * @return the string value associated with the specified property
556 */
557 public String getProperty(String name) {
558 if (mClosed) {
559 return null;
560 }
561
562 try {
563 return miSession.getProperty(name);
564 } catch (RemoteException e) {
565 return null;
566 }
567 }
568
569 /**
570 * Gets the session state.
571 * The value returned must be one of the states in {@link State}.
572 *
573 * @return the session state
574 */
575 public int getState() {
576 if (mClosed) {
577 return State.INVALID;
578 }
579
580 try {
581 return miSession.getState();
582 } catch (RemoteException e) {
583 return State.INVALID;
584 }
585 }
586
587 /**
588 * Determines if the {@link ImsCallSession} is currently alive (e.g. not in a terminated or
589 * closed state).
590 *
591 * @return {@code True} if the session is alive.
592 */
593 public boolean isAlive() {
594 if (mClosed) {
595 return false;
596 }
597
598 int state = getState();
599 switch (state) {
600 case State.IDLE:
601 case State.INITIATED:
602 case State.NEGOTIATING:
603 case State.ESTABLISHING:
604 case State.ESTABLISHED:
605 case State.RENEGOTIATING:
606 case State.REESTABLISHING:
607 return true;
608 default:
609 return false;
610 }
611 }
612
613 /**
614 * Gets the native IMS call session.
615 * @hide
616 */
617 public IImsCallSession getSession() {
618 return miSession;
619 }
620
621 /**
622 * Checks if the session is in call.
623 *
624 * @return true if the session is in call
625 */
626 public boolean isInCall() {
627 if (mClosed) {
628 return false;
629 }
630
631 try {
632 return miSession.isInCall();
633 } catch (RemoteException e) {
634 return false;
635 }
636 }
637
638 /**
639 * Sets the listener to listen to the session events. A {@link ImsCallSession}
640 * can only hold one listener at a time. Subsequent calls to this method
641 * override the previous listener.
642 *
643 * @param listener to listen to the session events of this object
644 */
645 public void setListener(Listener listener) {
646 mListener = listener;
647 }
648
649 /**
650 * Mutes or unmutes the mic for the active call.
651 *
652 * @param muted true if the call is muted, false otherwise
653 */
654 public void setMute(boolean muted) {
655 if (mClosed) {
656 return;
657 }
658
659 try {
660 miSession.setMute(muted);
661 } catch (RemoteException e) {
662 }
663 }
664
665 /**
666 * Initiates an IMS call with the specified target and call profile.
667 * The session listener is called back upon defined session events.
668 * The method is only valid to call when the session state is in
669 * {@link ImsCallSession.State#IDLE}.
670 *
671 * @param callee dialed string to make the call to
672 * @param profile call profile to make the call with the specified service type,
673 * call type and media information
674 * @see Listener#callSessionStarted, Listener#callSessionStartFailed
675 */
676 public void start(String callee, ImsCallProfile profile) {
677 if (mClosed) {
678 return;
679 }
680
681 try {
682 miSession.start(callee, profile);
683 } catch (RemoteException e) {
684 }
685 }
686
687 /**
688 * Initiates an IMS conference call with the specified target and call profile.
689 * The session listener is called back upon defined session events.
690 * The method is only valid to call when the session state is in
691 * {@link ImsCallSession.State#IDLE}.
692 *
693 * @param participants participant list to initiate an IMS conference call
694 * @param profile call profile to make the call with the specified service type,
695 * call type and media information
696 * @see Listener#callSessionStarted, Listener#callSessionStartFailed
697 */
698 public void start(String[] participants, ImsCallProfile profile) {
699 if (mClosed) {
700 return;
701 }
702
703 try {
704 miSession.startConference(participants, profile);
705 } catch (RemoteException e) {
706 }
707 }
708
709 /**
710 * Accepts an incoming call or session update.
711 *
712 * @param callType call type specified in {@link ImsCallProfile} to be answered
713 * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
714 * @see Listener#callSessionStarted
715 */
716 public void accept(int callType, ImsStreamMediaProfile profile) {
717 if (mClosed) {
718 return;
719 }
720
721 try {
722 miSession.accept(callType, profile);
723 } catch (RemoteException e) {
724 }
725 }
726
727 /**
728 * Rejects an incoming call or session update.
729 *
730 * @param reason reason code to reject an incoming call
731 * @see Listener#callSessionStartFailed
732 */
733 public void reject(int reason) {
734 if (mClosed) {
735 return;
736 }
737
738 try {
739 miSession.reject(reason);
740 } catch (RemoteException e) {
741 }
742 }
743
744 /**
745 * Terminates a call.
746 *
747 * @see Listener#callSessionTerminated
748 */
749 public void terminate(int reason) {
750 if (mClosed) {
751 return;
752 }
753
754 try {
755 miSession.terminate(reason);
756 } catch (RemoteException e) {
757 }
758 }
759
760 /**
761 * Puts a call on hold. When it succeeds, {@link Listener#callSessionHeld} is called.
762 *
763 * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call
764 * @see Listener#callSessionHeld, Listener#callSessionHoldFailed
765 */
766 public void hold(ImsStreamMediaProfile profile) {
767 if (mClosed) {
768 return;
769 }
770
771 try {
772 miSession.hold(profile);
773 } catch (RemoteException e) {
774 }
775 }
776
777 /**
778 * Continues a call that's on hold. When it succeeds,
779 * {@link Listener#callSessionResumed} is called.
780 *
781 * @param profile stream media profile {@link ImsStreamMediaProfile} to resume the call
782 * @see Listener#callSessionResumed, Listener#callSessionResumeFailed
783 */
784 public void resume(ImsStreamMediaProfile profile) {
785 if (mClosed) {
786 return;
787 }
788
789 try {
790 miSession.resume(profile);
791 } catch (RemoteException e) {
792 }
793 }
794
795 /**
796 * Merges the active & hold call. When it succeeds,
797 * {@link Listener#callSessionMergeStarted} is called.
798 *
799 * @see Listener#callSessionMergeStarted , Listener#callSessionMergeFailed
800 */
801 public void merge() {
802 if (mClosed) {
803 return;
804 }
805
806 try {
807 miSession.merge();
808 } catch (RemoteException e) {
809 }
810 }
811
812 /**
813 * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
814 *
815 * @param callType call type specified in {@link ImsCallProfile} to be updated
816 * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated
817 * @see Listener#callSessionUpdated, Listener#callSessionUpdateFailed
818 */
819 public void update(int callType, ImsStreamMediaProfile profile) {
820 if (mClosed) {
821 return;
822 }
823
824 try {
825 miSession.update(callType, profile);
826 } catch (RemoteException e) {
827 }
828 }
829
830 /**
831 * Extends this call to the conference call with the specified recipients.
832 *
833 * @param participants list to be invited to the conference call after extending the call
834 * @see Listener#callSessionConferenceExtended
835 * @see Listener#callSessionConferenceExtendFailed
836 */
837 public void extendToConference(String[] participants) {
838 if (mClosed) {
839 return;
840 }
841
842 try {
843 miSession.extendToConference(participants);
844 } catch (RemoteException e) {
845 }
846 }
847
848 /**
849 * Requests the conference server to invite an additional participants to the conference.
850 *
851 * @param participants list to be invited to the conference call
852 * @see Listener#callSessionInviteParticipantsRequestDelivered
853 * @see Listener#callSessionInviteParticipantsRequestFailed
854 */
855 public void inviteParticipants(String[] participants) {
856 if (mClosed) {
857 return;
858 }
859
860 try {
861 miSession.inviteParticipants(participants);
862 } catch (RemoteException e) {
863 }
864 }
865
866 /**
867 * Requests the conference server to remove the specified participants from the conference.
868 *
869 * @param participants participant list to be removed from the conference call
870 * @see Listener#callSessionRemoveParticipantsRequestDelivered
871 * @see Listener#callSessionRemoveParticipantsRequestFailed
872 */
873 public void removeParticipants(String[] participants) {
874 if (mClosed) {
875 return;
876 }
877
878 try {
879 miSession.removeParticipants(participants);
880 } catch (RemoteException e) {
881 }
882 }
883
884
885 /**
886 * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
887 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
888 * and event flash to 16. Currently, event flash is not supported.
889 *
890 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
891 */
892 public void sendDtmf(char c, Message result) {
893 if (mClosed) {
894 return;
895 }
896
897 try {
898 miSession.sendDtmf(c, result);
899 } catch (RemoteException e) {
900 }
901 }
902
903 /**
904 * Starts a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
905 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
906 * and event flash to 16. Currently, event flash is not supported.
907 *
908 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
909 */
910 public void startDtmf(char c) {
911 if (mClosed) {
912 return;
913 }
914
915 try {
916 miSession.startDtmf(c);
917 } catch (RemoteException e) {
918 }
919 }
920
921 /**
922 * Stops a DTMF code.
923 */
924 public void stopDtmf() {
925 if (mClosed) {
926 return;
927 }
928
929 try {
930 miSession.stopDtmf();
931 } catch (RemoteException e) {
932 }
933 }
934
935 /**
936 * Sends an USSD message.
937 *
938 * @param ussdMessage USSD message to send
939 */
940 public void sendUssd(String ussdMessage) {
941 if (mClosed) {
942 return;
943 }
944
945 try {
946 miSession.sendUssd(ussdMessage);
947 } catch (RemoteException e) {
948 }
949 }
950
951 /**
952 * Determines if the session is multiparty.
953 *
954 * @return {@code True} if the session is multiparty.
955 */
956 public boolean isMultiparty() {
957 if (mClosed) {
958 return false;
959 }
960
961 try {
962 return miSession.isMultiparty();
963 } catch (RemoteException e) {
964 return false;
965 }
966 }
967
968 /**
Anju Mathapati7e177da2017-01-24 11:58:28 -0800969 * Sends Rtt Message
970 *
971 * @param rttMessage rtt text to be sent
972 * @throws ImsException if call is absent
973 */
974 public void sendRttMessage(String rttMessage) {
975 if (mClosed) {
976 return;
977 }
978
979 try {
980 miSession.sendRttMessage(rttMessage);
981 } catch (RemoteException e) {
982 }
983 }
984
985 /**
986 * Sends RTT Upgrade request
987 *
988 * @param to : expected profile
989 * @throws CallStateException
990 */
991 public void sendRttModifyRequest(ImsCallProfile to) {
992 if (mClosed) {
993 return;
994 }
995
996 try {
997 miSession.sendRttModifyRequest(to);
998 } catch (RemoteException e) {
999 }
1000 }
1001
1002 /**
1003 * Sends RTT Upgrade response
1004 *
1005 * @param response : response for upgrade
1006 * @throws CallStateException
1007 */
1008 public void sendRttModifyResponse(boolean response) {
1009 if (mClosed) {
1010 return;
1011 }
1012
1013 try {
1014 miSession.sendRttModifyResponse(response);
1015 } catch (RemoteException e) {
1016 }
1017 }
1018
1019 /**
Brad Ebinger21013dc2017-02-02 16:21:22 -08001020 * A listener type for receiving notification on IMS call session events.
1021 * When an event is generated for an {@link IImsCallSession},
1022 * the application is notified by having one of the methods called on
1023 * the {@link IImsCallSessionListener}.
1024 */
1025 private class IImsCallSessionListenerProxy extends ImsCallSessionListenerImplBase {
1026 /**
1027 * Notifies the result of the basic session operation (setup / terminate).
1028 */
1029 @Override
1030 public void callSessionProgressing(IImsCallSession session,
1031 ImsStreamMediaProfile profile) {
1032 if (mListener != null) {
1033 mListener.callSessionProgressing(ImsCallSession.this, profile);
1034 }
1035 }
1036
1037 @Override
1038 public void callSessionStarted(IImsCallSession session,
1039 ImsCallProfile profile) {
1040 if (mListener != null) {
1041 mListener.callSessionStarted(ImsCallSession.this, profile);
1042 }
1043 }
1044
1045 @Override
1046 public void callSessionStartFailed(IImsCallSession session,
1047 ImsReasonInfo reasonInfo) {
1048 if (mListener != null) {
1049 mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
1050 }
1051 }
1052
1053 @Override
1054 public void callSessionTerminated(IImsCallSession session,
1055 ImsReasonInfo reasonInfo) {
1056 if (mListener != null) {
1057 mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
1058 }
1059 }
1060
1061 /**
1062 * Notifies the result of the call hold/resume operation.
1063 */
1064 @Override
1065 public void callSessionHeld(IImsCallSession session,
1066 ImsCallProfile profile) {
1067 if (mListener != null) {
1068 mListener.callSessionHeld(ImsCallSession.this, profile);
1069 }
1070 }
1071
1072 @Override
1073 public void callSessionHoldFailed(IImsCallSession session,
1074 ImsReasonInfo reasonInfo) {
1075 if (mListener != null) {
1076 mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
1077 }
1078 }
1079
1080 @Override
1081 public void callSessionHoldReceived(IImsCallSession session,
1082 ImsCallProfile profile) {
1083 if (mListener != null) {
1084 mListener.callSessionHoldReceived(ImsCallSession.this, profile);
1085 }
1086 }
1087
1088 @Override
1089 public void callSessionResumed(IImsCallSession session,
1090 ImsCallProfile profile) {
1091 if (mListener != null) {
1092 mListener.callSessionResumed(ImsCallSession.this, profile);
1093 }
1094 }
1095
1096 @Override
1097 public void callSessionResumeFailed(IImsCallSession session,
1098 ImsReasonInfo reasonInfo) {
1099 if (mListener != null) {
1100 mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
1101 }
1102 }
1103
1104 @Override
1105 public void callSessionResumeReceived(IImsCallSession session,
1106 ImsCallProfile profile) {
1107 if (mListener != null) {
1108 mListener.callSessionResumeReceived(ImsCallSession.this, profile);
1109 }
1110 }
1111
1112 /**
1113 * Notifies the start of a call merge operation.
1114 *
1115 * @param session The call session.
1116 * @param newSession The merged call session.
1117 * @param profile The call profile.
1118 */
1119 @Override
1120 public void callSessionMergeStarted(IImsCallSession session,
1121 IImsCallSession newSession, ImsCallProfile profile) {
1122 // This callback can be used for future use to add additional
1123 // functionality that may be needed between conference start and complete
1124 Log.d(TAG, "callSessionMergeStarted");
1125 }
1126
1127 /**
1128 * Notifies the successful completion of a call merge operation.
1129 *
1130 * @param newSession The call session.
1131 */
1132 @Override
1133 public void callSessionMergeComplete(IImsCallSession newSession) {
1134 if (mListener != null) {
1135 if (newSession != null) {
1136 // Check if the active session is the same session that was
1137 // active before the merge request was sent.
1138 ImsCallSession validActiveSession = ImsCallSession.this;
1139 try {
1140 if (!Objects.equals(miSession.getCallId(), newSession.getCallId())) {
1141 // New session created after conference
1142 validActiveSession = new ImsCallSession(newSession);
1143 }
1144 } catch (RemoteException rex) {
1145 Log.e(TAG, "callSessionMergeComplete: exception for getCallId!");
1146 }
1147 mListener.callSessionMergeComplete(validActiveSession);
1148 } else {
1149 // Session already exists. Hence no need to pass
1150 mListener.callSessionMergeComplete(null);
1151 }
1152 }
1153 }
1154
1155 /**
1156 * Notifies of a failure to perform a call merge operation.
1157 *
1158 * @param session The call session.
1159 * @param reasonInfo The merge failure reason.
1160 */
1161 @Override
1162 public void callSessionMergeFailed(IImsCallSession session,
1163 ImsReasonInfo reasonInfo) {
1164 if (mListener != null) {
1165 mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
1166 }
1167 }
1168
1169 /**
1170 * Notifies the result of call upgrade / downgrade or any other call updates.
1171 */
1172 @Override
1173 public void callSessionUpdated(IImsCallSession session,
1174 ImsCallProfile profile) {
1175 if (mListener != null) {
1176 mListener.callSessionUpdated(ImsCallSession.this, profile);
1177 }
1178 }
1179
1180 @Override
1181 public void callSessionUpdateFailed(IImsCallSession session,
1182 ImsReasonInfo reasonInfo) {
1183 if (mListener != null) {
1184 mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
1185 }
1186 }
1187
1188 @Override
1189 public void callSessionUpdateReceived(IImsCallSession session,
1190 ImsCallProfile profile) {
1191 if (mListener != null) {
1192 mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
1193 }
1194 }
1195
1196 /**
1197 * Notifies the result of conference extension.
1198 */
1199 @Override
1200 public void callSessionConferenceExtended(IImsCallSession session,
1201 IImsCallSession newSession, ImsCallProfile profile) {
1202 if (mListener != null) {
1203 mListener.callSessionConferenceExtended(ImsCallSession.this,
1204 new ImsCallSession(newSession), profile);
1205 }
1206 }
1207
1208 @Override
1209 public void callSessionConferenceExtendFailed(IImsCallSession session,
1210 ImsReasonInfo reasonInfo) {
1211 if (mListener != null) {
1212 mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo);
1213 }
1214 }
1215
1216 @Override
1217 public void callSessionConferenceExtendReceived(IImsCallSession session,
1218 IImsCallSession newSession, ImsCallProfile profile) {
1219 if (mListener != null) {
1220 mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
1221 new ImsCallSession(newSession), profile);
1222 }
1223 }
1224
1225 /**
1226 * Notifies the result of the participant invitation / removal to/from
1227 * the conference session.
1228 */
1229 @Override
1230 public void callSessionInviteParticipantsRequestDelivered(IImsCallSession session) {
1231 if (mListener != null) {
1232 mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this);
1233 }
1234 }
1235
1236 @Override
1237 public void callSessionInviteParticipantsRequestFailed(IImsCallSession session,
1238 ImsReasonInfo reasonInfo) {
1239 if (mListener != null) {
1240 mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
1241 reasonInfo);
1242 }
1243 }
1244
1245 @Override
1246 public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession session) {
1247 if (mListener != null) {
1248 mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
1249 }
1250 }
1251
1252 @Override
1253 public void callSessionRemoveParticipantsRequestFailed(IImsCallSession session,
1254 ImsReasonInfo reasonInfo) {
1255 if (mListener != null) {
1256 mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
1257 reasonInfo);
1258 }
1259 }
1260
1261 /**
1262 * Notifies the changes of the conference info. in the conference session.
1263 */
1264 @Override
1265 public void callSessionConferenceStateUpdated(IImsCallSession session,
1266 ImsConferenceState state) {
1267 if (mListener != null) {
1268 mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
1269 }
1270 }
1271
1272 /**
1273 * Notifies the incoming USSD message.
1274 */
1275 @Override
1276 public void callSessionUssdMessageReceived(IImsCallSession session,
1277 int mode, String ussdMessage) {
1278 if (mListener != null) {
1279 mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage);
1280 }
1281 }
1282
1283 /**
1284 * Notifies of handover information for this call
1285 */
1286 @Override
1287 public void callSessionHandover(IImsCallSession session,
1288 int srcAccessTech, int targetAccessTech,
1289 ImsReasonInfo reasonInfo) {
1290 if (mListener != null) {
1291 mListener.callSessionHandover(ImsCallSession.this, srcAccessTech,
1292 targetAccessTech, reasonInfo);
1293 }
1294 }
1295
1296 /**
1297 * Notifies of handover failure info for this call
1298 */
1299 @Override
1300 public void callSessionHandoverFailed(IImsCallSession session,
1301 int srcAccessTech, int targetAccessTech,
1302 ImsReasonInfo reasonInfo) {
1303 if (mListener != null) {
1304 mListener.callSessionHandoverFailed(ImsCallSession.this, srcAccessTech,
1305 targetAccessTech, reasonInfo);
1306 }
1307 }
1308
1309 /**
1310 * Notifies the TTY mode received from remote party.
1311 */
1312 @Override
1313 public void callSessionTtyModeReceived(IImsCallSession session,
1314 int mode) {
1315 if (mListener != null) {
1316 mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
1317 }
1318 }
1319
1320 /**
1321 * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
1322 *
1323 * @param session The call session.
1324 * @param isMultiParty {@code true} if the session became multiparty, {@code false}
1325 * otherwise.
1326 */
1327 public void callSessionMultipartyStateChanged(IImsCallSession session,
1328 boolean isMultiParty) {
1329
1330 if (mListener != null) {
1331 mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty);
1332 }
1333 }
1334
1335 @Override
1336 public void callSessionSuppServiceReceived(IImsCallSession session,
1337 ImsSuppServiceNotification suppServiceInfo ) {
1338 if (mListener != null) {
1339 mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo);
1340 }
1341 }
1342
Anju Mathapati7e177da2017-01-24 11:58:28 -08001343 /**
1344 * Received RTT modify request from remote party
1345 */
1346 @Override
1347 public void callSessionRttModifyRequestReceived(IImsCallSession session,
1348 ImsCallProfile callProfile) {
1349 if (mListener != null) {
1350 mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, callProfile);
1351 }
1352 }
1353
1354 /**
1355 * Received response for RTT modify request
1356 */
1357 @Override
1358 public void callSessionRttModifyResponseReceived(int status) {
1359 if (mListener != null) {
1360 mListener.callSessionRttModifyResponseReceived(status);
1361 }
1362 }
1363
1364 /**
1365 * RTT Message received
1366 */
1367 @Override
1368 public void callSessionRttMessageReceived(String rttMessage) {
1369 if (mListener != null) {
1370 mListener.callSessionRttMessageReceived(rttMessage);
1371 }
1372 }
Brad Ebinger21013dc2017-02-02 16:21:22 -08001373 }
1374
1375 /**
1376 * Provides a string representation of the {@link ImsCallSession}. Primarily intended for
1377 * use in log statements.
1378 *
1379 * @return String representation of session.
1380 */
1381 @Override
1382 public String toString() {
1383 StringBuilder sb = new StringBuilder();
1384 sb.append("[ImsCallSession objId:");
1385 sb.append(System.identityHashCode(this));
1386 sb.append(" state:");
1387 sb.append(State.toString(getState()));
1388 sb.append(" callId:");
1389 sb.append(getCallId());
1390 sb.append("]");
1391 return sb.toString();
1392 }
1393}