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