blob: 8196b2367ce9d11015ebb3ac489c88a1e5ea42ef [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 }
406 }
407
408 private final IImsCallSession miSession;
409 private boolean mClosed = false;
410 private Listener mListener;
411
412 public ImsCallSession(IImsCallSession iSession) {
413 miSession = iSession;
414
415 if (iSession != null) {
416 try {
417 iSession.setListener(new IImsCallSessionListenerProxy());
418 } catch (RemoteException e) {
419 }
420 } else {
421 mClosed = true;
422 }
423 }
424
425 public ImsCallSession(IImsCallSession iSession, Listener listener) {
426 this(iSession);
427 setListener(listener);
428 }
429
430 /**
431 * Closes this object. This object is not usable after being closed.
432 */
433 public synchronized void close() {
434 if (mClosed) {
435 return;
436 }
437
438 try {
439 miSession.close();
440 mClosed = true;
441 } catch (RemoteException e) {
442 }
443 }
444
445 /**
446 * Gets the call ID of the session.
447 *
448 * @return the call ID
449 */
450 public String getCallId() {
451 if (mClosed) {
452 return null;
453 }
454
455 try {
456 return miSession.getCallId();
457 } catch (RemoteException e) {
458 return null;
459 }
460 }
461
462 /**
463 * Gets the call profile that this session is associated with
464 *
465 * @return the call profile that this session is associated with
466 */
467 public ImsCallProfile getCallProfile() {
468 if (mClosed) {
469 return null;
470 }
471
472 try {
473 return miSession.getCallProfile();
474 } catch (RemoteException e) {
475 return null;
476 }
477 }
478
479 /**
480 * Gets the local call profile that this session is associated with
481 *
482 * @return the local call profile that this session is associated with
483 */
484 public ImsCallProfile getLocalCallProfile() {
485 if (mClosed) {
486 return null;
487 }
488
489 try {
490 return miSession.getLocalCallProfile();
491 } catch (RemoteException e) {
492 return null;
493 }
494 }
495
496 /**
497 * Gets the remote call profile that this session is associated with
498 *
499 * @return the remote call profile that this session is associated with
500 */
501 public ImsCallProfile getRemoteCallProfile() {
502 if (mClosed) {
503 return null;
504 }
505
506 try {
507 return miSession.getRemoteCallProfile();
508 } catch (RemoteException e) {
509 return null;
510 }
511 }
512
513 /**
514 * Gets the video call provider for the session.
515 *
516 * @return The video call provider.
517 */
518 public IImsVideoCallProvider getVideoCallProvider() {
519 if (mClosed) {
520 return null;
521 }
522
523 try {
524 return miSession.getVideoCallProvider();
525 } catch (RemoteException e) {
526 return null;
527 }
528 }
529
530 /**
531 * Gets the value associated with the specified property of this session.
532 *
533 * @return the string value associated with the specified property
534 */
535 public String getProperty(String name) {
536 if (mClosed) {
537 return null;
538 }
539
540 try {
541 return miSession.getProperty(name);
542 } catch (RemoteException e) {
543 return null;
544 }
545 }
546
547 /**
548 * Gets the session state.
549 * The value returned must be one of the states in {@link State}.
550 *
551 * @return the session state
552 */
553 public int getState() {
554 if (mClosed) {
555 return State.INVALID;
556 }
557
558 try {
559 return miSession.getState();
560 } catch (RemoteException e) {
561 return State.INVALID;
562 }
563 }
564
565 /**
566 * Determines if the {@link ImsCallSession} is currently alive (e.g. not in a terminated or
567 * closed state).
568 *
569 * @return {@code True} if the session is alive.
570 */
571 public boolean isAlive() {
572 if (mClosed) {
573 return false;
574 }
575
576 int state = getState();
577 switch (state) {
578 case State.IDLE:
579 case State.INITIATED:
580 case State.NEGOTIATING:
581 case State.ESTABLISHING:
582 case State.ESTABLISHED:
583 case State.RENEGOTIATING:
584 case State.REESTABLISHING:
585 return true;
586 default:
587 return false;
588 }
589 }
590
591 /**
592 * Gets the native IMS call session.
593 * @hide
594 */
595 public IImsCallSession getSession() {
596 return miSession;
597 }
598
599 /**
600 * Checks if the session is in call.
601 *
602 * @return true if the session is in call
603 */
604 public boolean isInCall() {
605 if (mClosed) {
606 return false;
607 }
608
609 try {
610 return miSession.isInCall();
611 } catch (RemoteException e) {
612 return false;
613 }
614 }
615
616 /**
617 * Sets the listener to listen to the session events. A {@link ImsCallSession}
618 * can only hold one listener at a time. Subsequent calls to this method
619 * override the previous listener.
620 *
621 * @param listener to listen to the session events of this object
622 */
623 public void setListener(Listener listener) {
624 mListener = listener;
625 }
626
627 /**
628 * Mutes or unmutes the mic for the active call.
629 *
630 * @param muted true if the call is muted, false otherwise
631 */
632 public void setMute(boolean muted) {
633 if (mClosed) {
634 return;
635 }
636
637 try {
638 miSession.setMute(muted);
639 } catch (RemoteException e) {
640 }
641 }
642
643 /**
644 * Initiates an IMS call with the specified target and call profile.
645 * The session listener is called back upon defined session events.
646 * The method is only valid to call when the session state is in
647 * {@link ImsCallSession.State#IDLE}.
648 *
649 * @param callee dialed string to make the call to
650 * @param profile call profile to make the call with the specified service type,
651 * call type and media information
652 * @see Listener#callSessionStarted, Listener#callSessionStartFailed
653 */
654 public void start(String callee, ImsCallProfile profile) {
655 if (mClosed) {
656 return;
657 }
658
659 try {
660 miSession.start(callee, profile);
661 } catch (RemoteException e) {
662 }
663 }
664
665 /**
666 * Initiates an IMS conference 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 participants participant list to initiate an IMS conference call
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[] participants, ImsCallProfile profile) {
677 if (mClosed) {
678 return;
679 }
680
681 try {
682 miSession.startConference(participants, profile);
683 } catch (RemoteException e) {
684 }
685 }
686
687 /**
688 * Accepts an incoming call or session update.
689 *
690 * @param callType call type specified in {@link ImsCallProfile} to be answered
691 * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
692 * @see Listener#callSessionStarted
693 */
694 public void accept(int callType, ImsStreamMediaProfile profile) {
695 if (mClosed) {
696 return;
697 }
698
699 try {
700 miSession.accept(callType, profile);
701 } catch (RemoteException e) {
702 }
703 }
704
705 /**
706 * Rejects an incoming call or session update.
707 *
708 * @param reason reason code to reject an incoming call
709 * @see Listener#callSessionStartFailed
710 */
711 public void reject(int reason) {
712 if (mClosed) {
713 return;
714 }
715
716 try {
717 miSession.reject(reason);
718 } catch (RemoteException e) {
719 }
720 }
721
722 /**
723 * Terminates a call.
724 *
725 * @see Listener#callSessionTerminated
726 */
727 public void terminate(int reason) {
728 if (mClosed) {
729 return;
730 }
731
732 try {
733 miSession.terminate(reason);
734 } catch (RemoteException e) {
735 }
736 }
737
738 /**
739 * Puts a call on hold. When it succeeds, {@link Listener#callSessionHeld} is called.
740 *
741 * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call
742 * @see Listener#callSessionHeld, Listener#callSessionHoldFailed
743 */
744 public void hold(ImsStreamMediaProfile profile) {
745 if (mClosed) {
746 return;
747 }
748
749 try {
750 miSession.hold(profile);
751 } catch (RemoteException e) {
752 }
753 }
754
755 /**
756 * Continues a call that's on hold. When it succeeds,
757 * {@link Listener#callSessionResumed} is called.
758 *
759 * @param profile stream media profile {@link ImsStreamMediaProfile} to resume the call
760 * @see Listener#callSessionResumed, Listener#callSessionResumeFailed
761 */
762 public void resume(ImsStreamMediaProfile profile) {
763 if (mClosed) {
764 return;
765 }
766
767 try {
768 miSession.resume(profile);
769 } catch (RemoteException e) {
770 }
771 }
772
773 /**
774 * Merges the active & hold call. When it succeeds,
775 * {@link Listener#callSessionMergeStarted} is called.
776 *
777 * @see Listener#callSessionMergeStarted , Listener#callSessionMergeFailed
778 */
779 public void merge() {
780 if (mClosed) {
781 return;
782 }
783
784 try {
785 miSession.merge();
786 } catch (RemoteException e) {
787 }
788 }
789
790 /**
791 * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
792 *
793 * @param callType call type specified in {@link ImsCallProfile} to be updated
794 * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated
795 * @see Listener#callSessionUpdated, Listener#callSessionUpdateFailed
796 */
797 public void update(int callType, ImsStreamMediaProfile profile) {
798 if (mClosed) {
799 return;
800 }
801
802 try {
803 miSession.update(callType, profile);
804 } catch (RemoteException e) {
805 }
806 }
807
808 /**
809 * Extends this call to the conference call with the specified recipients.
810 *
811 * @param participants list to be invited to the conference call after extending the call
812 * @see Listener#callSessionConferenceExtended
813 * @see Listener#callSessionConferenceExtendFailed
814 */
815 public void extendToConference(String[] participants) {
816 if (mClosed) {
817 return;
818 }
819
820 try {
821 miSession.extendToConference(participants);
822 } catch (RemoteException e) {
823 }
824 }
825
826 /**
827 * Requests the conference server to invite an additional participants to the conference.
828 *
829 * @param participants list to be invited to the conference call
830 * @see Listener#callSessionInviteParticipantsRequestDelivered
831 * @see Listener#callSessionInviteParticipantsRequestFailed
832 */
833 public void inviteParticipants(String[] participants) {
834 if (mClosed) {
835 return;
836 }
837
838 try {
839 miSession.inviteParticipants(participants);
840 } catch (RemoteException e) {
841 }
842 }
843
844 /**
845 * Requests the conference server to remove the specified participants from the conference.
846 *
847 * @param participants participant list to be removed from the conference call
848 * @see Listener#callSessionRemoveParticipantsRequestDelivered
849 * @see Listener#callSessionRemoveParticipantsRequestFailed
850 */
851 public void removeParticipants(String[] participants) {
852 if (mClosed) {
853 return;
854 }
855
856 try {
857 miSession.removeParticipants(participants);
858 } catch (RemoteException e) {
859 }
860 }
861
862
863 /**
864 * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
865 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
866 * and event flash to 16. Currently, event flash is not supported.
867 *
868 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
869 */
870 public void sendDtmf(char c, Message result) {
871 if (mClosed) {
872 return;
873 }
874
875 try {
876 miSession.sendDtmf(c, result);
877 } catch (RemoteException e) {
878 }
879 }
880
881 /**
882 * Starts a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
883 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
884 * and event flash to 16. Currently, event flash is not supported.
885 *
886 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
887 */
888 public void startDtmf(char c) {
889 if (mClosed) {
890 return;
891 }
892
893 try {
894 miSession.startDtmf(c);
895 } catch (RemoteException e) {
896 }
897 }
898
899 /**
900 * Stops a DTMF code.
901 */
902 public void stopDtmf() {
903 if (mClosed) {
904 return;
905 }
906
907 try {
908 miSession.stopDtmf();
909 } catch (RemoteException e) {
910 }
911 }
912
913 /**
914 * Sends an USSD message.
915 *
916 * @param ussdMessage USSD message to send
917 */
918 public void sendUssd(String ussdMessage) {
919 if (mClosed) {
920 return;
921 }
922
923 try {
924 miSession.sendUssd(ussdMessage);
925 } catch (RemoteException e) {
926 }
927 }
928
929 /**
930 * Determines if the session is multiparty.
931 *
932 * @return {@code True} if the session is multiparty.
933 */
934 public boolean isMultiparty() {
935 if (mClosed) {
936 return false;
937 }
938
939 try {
940 return miSession.isMultiparty();
941 } catch (RemoteException e) {
942 return false;
943 }
944 }
945
946 /**
947 * A listener type for receiving notification on IMS call session events.
948 * When an event is generated for an {@link IImsCallSession},
949 * the application is notified by having one of the methods called on
950 * the {@link IImsCallSessionListener}.
951 */
952 private class IImsCallSessionListenerProxy extends ImsCallSessionListenerImplBase {
953 /**
954 * Notifies the result of the basic session operation (setup / terminate).
955 */
956 @Override
957 public void callSessionProgressing(IImsCallSession session,
958 ImsStreamMediaProfile profile) {
959 if (mListener != null) {
960 mListener.callSessionProgressing(ImsCallSession.this, profile);
961 }
962 }
963
964 @Override
965 public void callSessionStarted(IImsCallSession session,
966 ImsCallProfile profile) {
967 if (mListener != null) {
968 mListener.callSessionStarted(ImsCallSession.this, profile);
969 }
970 }
971
972 @Override
973 public void callSessionStartFailed(IImsCallSession session,
974 ImsReasonInfo reasonInfo) {
975 if (mListener != null) {
976 mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
977 }
978 }
979
980 @Override
981 public void callSessionTerminated(IImsCallSession session,
982 ImsReasonInfo reasonInfo) {
983 if (mListener != null) {
984 mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
985 }
986 }
987
988 /**
989 * Notifies the result of the call hold/resume operation.
990 */
991 @Override
992 public void callSessionHeld(IImsCallSession session,
993 ImsCallProfile profile) {
994 if (mListener != null) {
995 mListener.callSessionHeld(ImsCallSession.this, profile);
996 }
997 }
998
999 @Override
1000 public void callSessionHoldFailed(IImsCallSession session,
1001 ImsReasonInfo reasonInfo) {
1002 if (mListener != null) {
1003 mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
1004 }
1005 }
1006
1007 @Override
1008 public void callSessionHoldReceived(IImsCallSession session,
1009 ImsCallProfile profile) {
1010 if (mListener != null) {
1011 mListener.callSessionHoldReceived(ImsCallSession.this, profile);
1012 }
1013 }
1014
1015 @Override
1016 public void callSessionResumed(IImsCallSession session,
1017 ImsCallProfile profile) {
1018 if (mListener != null) {
1019 mListener.callSessionResumed(ImsCallSession.this, profile);
1020 }
1021 }
1022
1023 @Override
1024 public void callSessionResumeFailed(IImsCallSession session,
1025 ImsReasonInfo reasonInfo) {
1026 if (mListener != null) {
1027 mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
1028 }
1029 }
1030
1031 @Override
1032 public void callSessionResumeReceived(IImsCallSession session,
1033 ImsCallProfile profile) {
1034 if (mListener != null) {
1035 mListener.callSessionResumeReceived(ImsCallSession.this, profile);
1036 }
1037 }
1038
1039 /**
1040 * Notifies the start of a call merge operation.
1041 *
1042 * @param session The call session.
1043 * @param newSession The merged call session.
1044 * @param profile The call profile.
1045 */
1046 @Override
1047 public void callSessionMergeStarted(IImsCallSession session,
1048 IImsCallSession newSession, ImsCallProfile profile) {
1049 // This callback can be used for future use to add additional
1050 // functionality that may be needed between conference start and complete
1051 Log.d(TAG, "callSessionMergeStarted");
1052 }
1053
1054 /**
1055 * Notifies the successful completion of a call merge operation.
1056 *
1057 * @param newSession The call session.
1058 */
1059 @Override
1060 public void callSessionMergeComplete(IImsCallSession newSession) {
1061 if (mListener != null) {
1062 if (newSession != null) {
1063 // Check if the active session is the same session that was
1064 // active before the merge request was sent.
1065 ImsCallSession validActiveSession = ImsCallSession.this;
1066 try {
1067 if (!Objects.equals(miSession.getCallId(), newSession.getCallId())) {
1068 // New session created after conference
1069 validActiveSession = new ImsCallSession(newSession);
1070 }
1071 } catch (RemoteException rex) {
1072 Log.e(TAG, "callSessionMergeComplete: exception for getCallId!");
1073 }
1074 mListener.callSessionMergeComplete(validActiveSession);
1075 } else {
1076 // Session already exists. Hence no need to pass
1077 mListener.callSessionMergeComplete(null);
1078 }
1079 }
1080 }
1081
1082 /**
1083 * Notifies of a failure to perform a call merge operation.
1084 *
1085 * @param session The call session.
1086 * @param reasonInfo The merge failure reason.
1087 */
1088 @Override
1089 public void callSessionMergeFailed(IImsCallSession session,
1090 ImsReasonInfo reasonInfo) {
1091 if (mListener != null) {
1092 mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
1093 }
1094 }
1095
1096 /**
1097 * Notifies the result of call upgrade / downgrade or any other call updates.
1098 */
1099 @Override
1100 public void callSessionUpdated(IImsCallSession session,
1101 ImsCallProfile profile) {
1102 if (mListener != null) {
1103 mListener.callSessionUpdated(ImsCallSession.this, profile);
1104 }
1105 }
1106
1107 @Override
1108 public void callSessionUpdateFailed(IImsCallSession session,
1109 ImsReasonInfo reasonInfo) {
1110 if (mListener != null) {
1111 mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
1112 }
1113 }
1114
1115 @Override
1116 public void callSessionUpdateReceived(IImsCallSession session,
1117 ImsCallProfile profile) {
1118 if (mListener != null) {
1119 mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
1120 }
1121 }
1122
1123 /**
1124 * Notifies the result of conference extension.
1125 */
1126 @Override
1127 public void callSessionConferenceExtended(IImsCallSession session,
1128 IImsCallSession newSession, ImsCallProfile profile) {
1129 if (mListener != null) {
1130 mListener.callSessionConferenceExtended(ImsCallSession.this,
1131 new ImsCallSession(newSession), profile);
1132 }
1133 }
1134
1135 @Override
1136 public void callSessionConferenceExtendFailed(IImsCallSession session,
1137 ImsReasonInfo reasonInfo) {
1138 if (mListener != null) {
1139 mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo);
1140 }
1141 }
1142
1143 @Override
1144 public void callSessionConferenceExtendReceived(IImsCallSession session,
1145 IImsCallSession newSession, ImsCallProfile profile) {
1146 if (mListener != null) {
1147 mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
1148 new ImsCallSession(newSession), profile);
1149 }
1150 }
1151
1152 /**
1153 * Notifies the result of the participant invitation / removal to/from
1154 * the conference session.
1155 */
1156 @Override
1157 public void callSessionInviteParticipantsRequestDelivered(IImsCallSession session) {
1158 if (mListener != null) {
1159 mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this);
1160 }
1161 }
1162
1163 @Override
1164 public void callSessionInviteParticipantsRequestFailed(IImsCallSession session,
1165 ImsReasonInfo reasonInfo) {
1166 if (mListener != null) {
1167 mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
1168 reasonInfo);
1169 }
1170 }
1171
1172 @Override
1173 public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession session) {
1174 if (mListener != null) {
1175 mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
1176 }
1177 }
1178
1179 @Override
1180 public void callSessionRemoveParticipantsRequestFailed(IImsCallSession session,
1181 ImsReasonInfo reasonInfo) {
1182 if (mListener != null) {
1183 mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
1184 reasonInfo);
1185 }
1186 }
1187
1188 /**
1189 * Notifies the changes of the conference info. in the conference session.
1190 */
1191 @Override
1192 public void callSessionConferenceStateUpdated(IImsCallSession session,
1193 ImsConferenceState state) {
1194 if (mListener != null) {
1195 mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
1196 }
1197 }
1198
1199 /**
1200 * Notifies the incoming USSD message.
1201 */
1202 @Override
1203 public void callSessionUssdMessageReceived(IImsCallSession session,
1204 int mode, String ussdMessage) {
1205 if (mListener != null) {
1206 mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage);
1207 }
1208 }
1209
1210 /**
1211 * Notifies of handover information for this call
1212 */
1213 @Override
1214 public void callSessionHandover(IImsCallSession session,
1215 int srcAccessTech, int targetAccessTech,
1216 ImsReasonInfo reasonInfo) {
1217 if (mListener != null) {
1218 mListener.callSessionHandover(ImsCallSession.this, srcAccessTech,
1219 targetAccessTech, reasonInfo);
1220 }
1221 }
1222
1223 /**
1224 * Notifies of handover failure info for this call
1225 */
1226 @Override
1227 public void callSessionHandoverFailed(IImsCallSession session,
1228 int srcAccessTech, int targetAccessTech,
1229 ImsReasonInfo reasonInfo) {
1230 if (mListener != null) {
1231 mListener.callSessionHandoverFailed(ImsCallSession.this, srcAccessTech,
1232 targetAccessTech, reasonInfo);
1233 }
1234 }
1235
1236 /**
1237 * Notifies the TTY mode received from remote party.
1238 */
1239 @Override
1240 public void callSessionTtyModeReceived(IImsCallSession session,
1241 int mode) {
1242 if (mListener != null) {
1243 mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
1244 }
1245 }
1246
1247 /**
1248 * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
1249 *
1250 * @param session The call session.
1251 * @param isMultiParty {@code true} if the session became multiparty, {@code false}
1252 * otherwise.
1253 */
1254 public void callSessionMultipartyStateChanged(IImsCallSession session,
1255 boolean isMultiParty) {
1256
1257 if (mListener != null) {
1258 mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty);
1259 }
1260 }
1261
1262 @Override
1263 public void callSessionSuppServiceReceived(IImsCallSession session,
1264 ImsSuppServiceNotification suppServiceInfo ) {
1265 if (mListener != null) {
1266 mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo);
1267 }
1268 }
1269
1270 }
1271
1272 /**
1273 * Provides a string representation of the {@link ImsCallSession}. Primarily intended for
1274 * use in log statements.
1275 *
1276 * @return String representation of session.
1277 */
1278 @Override
1279 public String toString() {
1280 StringBuilder sb = new StringBuilder();
1281 sb.append("[ImsCallSession objId:");
1282 sb.append(System.identityHashCode(this));
1283 sb.append(" state:");
1284 sb.append(State.toString(getState()));
1285 sb.append(" callId:");
1286 sb.append(getCallId());
1287 sb.append("]");
1288 return sb.toString();
1289 }
1290}