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