1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.sip;
18 
19 import android.os.RemoteException;
20 import android.telephony.Rlog;
21 
22 /**
23  * Represents a SIP session that is associated with a SIP dialog or a standalone
24  * transaction not within a dialog.
25  * <p>You can get a {@link SipSession} from {@link SipManager} with {@link
26  * SipManager#createSipSession createSipSession()} (when initiating calls) or {@link
27  * SipManager#getSessionFor getSessionFor()} (when receiving calls).</p>
28  */
29 public final class SipSession {
30     private static final String TAG = "SipSession";
31 
32     /**
33      * Defines SIP session states, such as "registering", "outgoing call", and "in call".
34      */
35     public static class State {
36         /** When session is ready to initiate a call or transaction. */
37         public static final int READY_TO_CALL = 0;
38 
39         /** When the registration request is sent out. */
40         public static final int REGISTERING = 1;
41 
42         /** When the unregistration request is sent out. */
43         public static final int DEREGISTERING = 2;
44 
45         /** When an INVITE request is received. */
46         public static final int INCOMING_CALL = 3;
47 
48         /** When an OK response is sent for the INVITE request received. */
49         public static final int INCOMING_CALL_ANSWERING = 4;
50 
51         /** When an INVITE request is sent. */
52         public static final int OUTGOING_CALL = 5;
53 
54         /** When a RINGING response is received for the INVITE request sent. */
55         public static final int OUTGOING_CALL_RING_BACK = 6;
56 
57         /** When a CANCEL request is sent for the INVITE request sent. */
58         public static final int OUTGOING_CALL_CANCELING = 7;
59 
60         /** When a call is established. */
61         public static final int IN_CALL = 8;
62 
63         /** When an OPTIONS request is sent. */
64         public static final int PINGING = 9;
65 
66         /** When ending a call. @hide */
67         public static final int ENDING_CALL = 10;
68 
69         /** Not defined. */
70         public static final int NOT_DEFINED = 101;
71 
72         /**
73          * Converts the state to string.
74          */
toString(int state)75         public static String toString(int state) {
76             switch (state) {
77                 case READY_TO_CALL:
78                     return "READY_TO_CALL";
79                 case REGISTERING:
80                     return "REGISTERING";
81                 case DEREGISTERING:
82                     return "DEREGISTERING";
83                 case INCOMING_CALL:
84                     return "INCOMING_CALL";
85                 case INCOMING_CALL_ANSWERING:
86                     return "INCOMING_CALL_ANSWERING";
87                 case OUTGOING_CALL:
88                     return "OUTGOING_CALL";
89                 case OUTGOING_CALL_RING_BACK:
90                     return "OUTGOING_CALL_RING_BACK";
91                 case OUTGOING_CALL_CANCELING:
92                     return "OUTGOING_CALL_CANCELING";
93                 case IN_CALL:
94                     return "IN_CALL";
95                 case PINGING:
96                     return "PINGING";
97                 default:
98                     return "NOT_DEFINED";
99             }
100         }
101 
State()102         private State() {
103         }
104     }
105 
106     /**
107      * Listener for events relating to a SIP session, such as when a session is being registered
108      * ("on registering") or a call is outgoing ("on calling").
109      * <p>Many of these events are also received by {@link SipAudioCall.Listener}.</p>
110      */
111     public static class Listener {
112         /**
113          * Called when an INVITE request is sent to initiate a new call.
114          *
115          * @param session the session object that carries out the transaction
116          */
onCalling(SipSession session)117         public void onCalling(SipSession session) {
118         }
119 
120         /**
121          * Called when an INVITE request is received.
122          *
123          * @param session the session object that carries out the transaction
124          * @param caller the SIP profile of the caller
125          * @param sessionDescription the caller's session description
126          */
onRinging(SipSession session, SipProfile caller, String sessionDescription)127         public void onRinging(SipSession session, SipProfile caller,
128                 String sessionDescription) {
129         }
130 
131         /**
132          * Called when a RINGING response is received for the INVITE request sent
133          *
134          * @param session the session object that carries out the transaction
135          */
onRingingBack(SipSession session)136         public void onRingingBack(SipSession session) {
137         }
138 
139         /**
140          * Called when the session is established.
141          *
142          * @param session the session object that is associated with the dialog
143          * @param sessionDescription the peer's session description
144          */
onCallEstablished(SipSession session, String sessionDescription)145         public void onCallEstablished(SipSession session,
146                 String sessionDescription) {
147         }
148 
149         /**
150          * Called when the session is terminated.
151          *
152          * @param session the session object that is associated with the dialog
153          */
onCallEnded(SipSession session)154         public void onCallEnded(SipSession session) {
155         }
156 
157         /**
158          * Called when the peer is busy during session initialization.
159          *
160          * @param session the session object that carries out the transaction
161          */
onCallBusy(SipSession session)162         public void onCallBusy(SipSession session) {
163         }
164 
165         /**
166          * Called when the call is being transferred to a new one.
167          *
168          * @hide
169          * @param newSession the new session that the call will be transferred to
170          * @param sessionDescription the new peer's session description
171          */
onCallTransferring(SipSession newSession, String sessionDescription)172         public void onCallTransferring(SipSession newSession,
173                 String sessionDescription) {
174         }
175 
176         /**
177          * Called when an error occurs during session initialization and
178          * termination.
179          *
180          * @param session the session object that carries out the transaction
181          * @param errorCode error code defined in {@link SipErrorCode}
182          * @param errorMessage error message
183          */
onError(SipSession session, int errorCode, String errorMessage)184         public void onError(SipSession session, int errorCode,
185                 String errorMessage) {
186         }
187 
188         /**
189          * Called when an error occurs during session modification negotiation.
190          *
191          * @param session the session object that carries out the transaction
192          * @param errorCode error code defined in {@link SipErrorCode}
193          * @param errorMessage error message
194          */
onCallChangeFailed(SipSession session, int errorCode, String errorMessage)195         public void onCallChangeFailed(SipSession session, int errorCode,
196                 String errorMessage) {
197         }
198 
199         /**
200          * Called when a registration request is sent.
201          *
202          * @param session the session object that carries out the transaction
203          */
onRegistering(SipSession session)204         public void onRegistering(SipSession session) {
205         }
206 
207         /**
208          * Called when registration is successfully done.
209          *
210          * @param session the session object that carries out the transaction
211          * @param duration duration in second before the registration expires
212          */
onRegistrationDone(SipSession session, int duration)213         public void onRegistrationDone(SipSession session, int duration) {
214         }
215 
216         /**
217          * Called when the registration fails.
218          *
219          * @param session the session object that carries out the transaction
220          * @param errorCode error code defined in {@link SipErrorCode}
221          * @param errorMessage error message
222          */
onRegistrationFailed(SipSession session, int errorCode, String errorMessage)223         public void onRegistrationFailed(SipSession session, int errorCode,
224                 String errorMessage) {
225         }
226 
227         /**
228          * Called when the registration gets timed out.
229          *
230          * @param session the session object that carries out the transaction
231          */
onRegistrationTimeout(SipSession session)232         public void onRegistrationTimeout(SipSession session) {
233         }
234     }
235 
236     private final ISipSession mSession;
237     private Listener mListener;
238 
SipSession(ISipSession realSession)239     SipSession(ISipSession realSession) {
240         mSession = realSession;
241         if (realSession != null) {
242             try {
243                 realSession.setListener(createListener());
244             } catch (RemoteException e) {
245                 loge("SipSession.setListener:", e);
246             }
247         }
248     }
249 
SipSession(ISipSession realSession, Listener listener)250     SipSession(ISipSession realSession, Listener listener) {
251         this(realSession);
252         setListener(listener);
253     }
254 
255     /**
256      * Gets the IP address of the local host on which this SIP session runs.
257      *
258      * @return the IP address of the local host
259      */
getLocalIp()260     public String getLocalIp() {
261         try {
262             return mSession.getLocalIp();
263         } catch (RemoteException e) {
264             loge("getLocalIp:", e);
265             return "127.0.0.1";
266         }
267     }
268 
269     /**
270      * Gets the SIP profile that this session is associated with.
271      *
272      * @return the SIP profile that this session is associated with
273      */
getLocalProfile()274     public SipProfile getLocalProfile() {
275         try {
276             return mSession.getLocalProfile();
277         } catch (RemoteException e) {
278             loge("getLocalProfile:", e);
279             return null;
280         }
281     }
282 
283     /**
284      * Gets the SIP profile that this session is connected to. Only available
285      * when the session is associated with a SIP dialog.
286      *
287      * @return the SIP profile that this session is connected to
288      */
getPeerProfile()289     public SipProfile getPeerProfile() {
290         try {
291             return mSession.getPeerProfile();
292         } catch (RemoteException e) {
293             loge("getPeerProfile:", e);
294             return null;
295         }
296     }
297 
298     /**
299      * Gets the session state. The value returned must be one of the states in
300      * {@link State}.
301      *
302      * @return the session state
303      */
getState()304     public int getState() {
305         try {
306             return mSession.getState();
307         } catch (RemoteException e) {
308             loge("getState:", e);
309             return State.NOT_DEFINED;
310         }
311     }
312 
313     /**
314      * Checks if the session is in a call.
315      *
316      * @return true if the session is in a call
317      */
isInCall()318     public boolean isInCall() {
319         try {
320             return mSession.isInCall();
321         } catch (RemoteException e) {
322             loge("isInCall:", e);
323             return false;
324         }
325     }
326 
327     /**
328      * Gets the call ID of the session.
329      *
330      * @return the call ID
331      */
getCallId()332     public String getCallId() {
333         try {
334             return mSession.getCallId();
335         } catch (RemoteException e) {
336             loge("getCallId:", e);
337             return null;
338         }
339     }
340 
341 
342     /**
343      * Sets the listener to listen to the session events. A {@code SipSession}
344      * can only hold one listener at a time. Subsequent calls to this method
345      * override the previous listener.
346      *
347      * @param listener to listen to the session events of this object
348      */
setListener(Listener listener)349     public void setListener(Listener listener) {
350         mListener = listener;
351     }
352 
353 
354     /**
355      * Performs registration to the server specified by the associated local
356      * profile. The session listener is called back upon success or failure of
357      * registration. The method is only valid to call when the session state is
358      * in {@link State#READY_TO_CALL}.
359      *
360      * @param duration duration in second before the registration expires
361      * @see Listener
362      */
register(int duration)363     public void register(int duration) {
364         try {
365             mSession.register(duration);
366         } catch (RemoteException e) {
367             loge("register:", e);
368         }
369     }
370 
371     /**
372      * Performs unregistration to the server specified by the associated local
373      * profile. Unregistration is technically the same as registration with zero
374      * expiration duration. The session listener is called back upon success or
375      * failure of unregistration. The method is only valid to call when the
376      * session state is in {@link State#READY_TO_CALL}.
377      *
378      * @see Listener
379      */
unregister()380     public void unregister() {
381         try {
382             mSession.unregister();
383         } catch (RemoteException e) {
384             loge("unregister:", e);
385         }
386     }
387 
388     /**
389      * Initiates a call to the specified profile. The session listener is called
390      * back upon defined session events. The method is only valid to call when
391      * the session state is in {@link State#READY_TO_CALL}.
392      *
393      * @param callee the SIP profile to make the call to
394      * @param sessionDescription the session description of this call
395      * @param timeout the session will be timed out if the call is not
396      *        established within {@code timeout} seconds. Default value (defined
397      *        by SIP protocol) is used if {@code timeout} is zero or negative.
398      * @see Listener
399      */
makeCall(SipProfile callee, String sessionDescription, int timeout)400     public void makeCall(SipProfile callee, String sessionDescription,
401             int timeout) {
402         try {
403             mSession.makeCall(callee, sessionDescription, timeout);
404         } catch (RemoteException e) {
405             loge("makeCall:", e);
406         }
407     }
408 
409     /**
410      * Answers an incoming call with the specified session description. The
411      * method is only valid to call when the session state is in
412      * {@link State#INCOMING_CALL}.
413      *
414      * @param sessionDescription the session description to answer this call
415      * @param timeout the session will be timed out if the call is not
416      *        established within {@code timeout} seconds. Default value (defined
417      *        by SIP protocol) is used if {@code timeout} is zero or negative.
418      */
answerCall(String sessionDescription, int timeout)419     public void answerCall(String sessionDescription, int timeout) {
420         try {
421             mSession.answerCall(sessionDescription, timeout);
422         } catch (RemoteException e) {
423             loge("answerCall:", e);
424         }
425     }
426 
427     /**
428      * Ends an established call, terminates an outgoing call or rejects an
429      * incoming call. The method is only valid to call when the session state is
430      * in {@link State#IN_CALL},
431      * {@link State#INCOMING_CALL},
432      * {@link State#OUTGOING_CALL} or
433      * {@link State#OUTGOING_CALL_RING_BACK}.
434      */
endCall()435     public void endCall() {
436         try {
437             mSession.endCall();
438         } catch (RemoteException e) {
439             loge("endCall:", e);
440         }
441     }
442 
443     /**
444      * Changes the session description during a call. The method is only valid
445      * to call when the session state is in {@link State#IN_CALL}.
446      *
447      * @param sessionDescription the new session description
448      * @param timeout the session will be timed out if the call is not
449      *        established within {@code timeout} seconds. Default value (defined
450      *        by SIP protocol) is used if {@code timeout} is zero or negative.
451      */
changeCall(String sessionDescription, int timeout)452     public void changeCall(String sessionDescription, int timeout) {
453         try {
454             mSession.changeCall(sessionDescription, timeout);
455         } catch (RemoteException e) {
456             loge("changeCall:", e);
457         }
458     }
459 
getRealSession()460     ISipSession getRealSession() {
461         return mSession;
462     }
463 
createListener()464     private ISipSessionListener createListener() {
465         return new ISipSessionListener.Stub() {
466             @Override
467             public void onCalling(ISipSession session) {
468                 if (mListener != null) {
469                     mListener.onCalling(SipSession.this);
470                 }
471             }
472 
473             @Override
474             public void onRinging(ISipSession session, SipProfile caller,
475                     String sessionDescription) {
476                 if (mListener != null) {
477                     mListener.onRinging(SipSession.this, caller,
478                             sessionDescription);
479                 }
480             }
481 
482             @Override
483             public void onRingingBack(ISipSession session) {
484                 if (mListener != null) {
485                     mListener.onRingingBack(SipSession.this);
486                 }
487             }
488 
489             @Override
490             public void onCallEstablished(ISipSession session,
491                     String sessionDescription) {
492                 if (mListener != null) {
493                     mListener.onCallEstablished(SipSession.this,
494                             sessionDescription);
495                 }
496             }
497 
498             @Override
499             public void onCallEnded(ISipSession session) {
500                 if (mListener != null) {
501                     mListener.onCallEnded(SipSession.this);
502                 }
503             }
504 
505             @Override
506             public void onCallBusy(ISipSession session) {
507                 if (mListener != null) {
508                     mListener.onCallBusy(SipSession.this);
509                 }
510             }
511 
512             @Override
513             public void onCallTransferring(ISipSession session,
514                     String sessionDescription) {
515                 if (mListener != null) {
516                     mListener.onCallTransferring(
517                             new SipSession(session, SipSession.this.mListener),
518                             sessionDescription);
519 
520                 }
521             }
522 
523             @Override
524             public void onCallChangeFailed(ISipSession session, int errorCode,
525                     String message) {
526                 if (mListener != null) {
527                     mListener.onCallChangeFailed(SipSession.this, errorCode,
528                             message);
529                 }
530             }
531 
532             @Override
533             public void onError(ISipSession session, int errorCode, String message) {
534                 if (mListener != null) {
535                     mListener.onError(SipSession.this, errorCode, message);
536                 }
537             }
538 
539             @Override
540             public void onRegistering(ISipSession session) {
541                 if (mListener != null) {
542                     mListener.onRegistering(SipSession.this);
543                 }
544             }
545 
546             @Override
547             public void onRegistrationDone(ISipSession session, int duration) {
548                 if (mListener != null) {
549                     mListener.onRegistrationDone(SipSession.this, duration);
550                 }
551             }
552 
553             @Override
554             public void onRegistrationFailed(ISipSession session, int errorCode,
555                     String message) {
556                 if (mListener != null) {
557                     mListener.onRegistrationFailed(SipSession.this, errorCode,
558                             message);
559                 }
560             }
561 
562             @Override
563             public void onRegistrationTimeout(ISipSession session) {
564                 if (mListener != null) {
565                     mListener.onRegistrationTimeout(SipSession.this);
566                 }
567             }
568         };
569     }
570 
571     private void loge(String s, Throwable t) {
572         Rlog.e(TAG, s, t);
573     }
574 }
575