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