| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.net.sip; |
| |
| import android.os.RemoteException; |
| import android.telephony.Rlog; |
| |
| /** |
| * Represents a SIP session that is associated with a SIP dialog or a standalone |
| * transaction not within a dialog. |
| * <p>You can get a {@link SipSession} from {@link SipManager} with {@link |
| * SipManager#createSipSession createSipSession()} (when initiating calls) or {@link |
| * SipManager#getSessionFor getSessionFor()} (when receiving calls).</p> |
| */ |
| public final class SipSession { |
| private static final String TAG = "SipSession"; |
| |
| /** |
| * Defines SIP session states, such as "registering", "outgoing call", and "in call". |
| */ |
| public static class State { |
| /** When session is ready to initiate a call or transaction. */ |
| public static final int READY_TO_CALL = 0; |
| |
| /** When the registration request is sent out. */ |
| public static final int REGISTERING = 1; |
| |
| /** When the unregistration request is sent out. */ |
| public static final int DEREGISTERING = 2; |
| |
| /** When an INVITE request is received. */ |
| public static final int INCOMING_CALL = 3; |
| |
| /** When an OK response is sent for the INVITE request received. */ |
| public static final int INCOMING_CALL_ANSWERING = 4; |
| |
| /** When an INVITE request is sent. */ |
| public static final int OUTGOING_CALL = 5; |
| |
| /** When a RINGING response is received for the INVITE request sent. */ |
| public static final int OUTGOING_CALL_RING_BACK = 6; |
| |
| /** When a CANCEL request is sent for the INVITE request sent. */ |
| public static final int OUTGOING_CALL_CANCELING = 7; |
| |
| /** When a call is established. */ |
| public static final int IN_CALL = 8; |
| |
| /** When an OPTIONS request is sent. */ |
| public static final int PINGING = 9; |
| |
| /** When ending a call. @hide */ |
| public static final int ENDING_CALL = 10; |
| |
| /** Not defined. */ |
| public static final int NOT_DEFINED = 101; |
| |
| /** |
| * Converts the state to string. |
| */ |
| public static String toString(int state) { |
| switch (state) { |
| case READY_TO_CALL: |
| return "READY_TO_CALL"; |
| case REGISTERING: |
| return "REGISTERING"; |
| case DEREGISTERING: |
| return "DEREGISTERING"; |
| case INCOMING_CALL: |
| return "INCOMING_CALL"; |
| case INCOMING_CALL_ANSWERING: |
| return "INCOMING_CALL_ANSWERING"; |
| case OUTGOING_CALL: |
| return "OUTGOING_CALL"; |
| case OUTGOING_CALL_RING_BACK: |
| return "OUTGOING_CALL_RING_BACK"; |
| case OUTGOING_CALL_CANCELING: |
| return "OUTGOING_CALL_CANCELING"; |
| case IN_CALL: |
| return "IN_CALL"; |
| case PINGING: |
| return "PINGING"; |
| default: |
| return "NOT_DEFINED"; |
| } |
| } |
| |
| private State() { |
| } |
| } |
| |
| /** |
| * Listener for events relating to a SIP session, such as when a session is being registered |
| * ("on registering") or a call is outgoing ("on calling"). |
| * <p>Many of these events are also received by {@link SipAudioCall.Listener}.</p> |
| */ |
| public static class Listener { |
| /** |
| * Called when an INVITE request is sent to initiate a new call. |
| * |
| * @param session the session object that carries out the transaction |
| */ |
| public void onCalling(SipSession session) { |
| } |
| |
| /** |
| * Called when an INVITE request is received. |
| * |
| * @param session the session object that carries out the transaction |
| * @param caller the SIP profile of the caller |
| * @param sessionDescription the caller's session description |
| */ |
| public void onRinging(SipSession session, SipProfile caller, |
| String sessionDescription) { |
| } |
| |
| /** |
| * Called when a RINGING response is received for the INVITE request sent |
| * |
| * @param session the session object that carries out the transaction |
| */ |
| public void onRingingBack(SipSession session) { |
| } |
| |
| /** |
| * Called when the session is established. |
| * |
| * @param session the session object that is associated with the dialog |
| * @param sessionDescription the peer's session description |
| */ |
| public void onCallEstablished(SipSession session, |
| String sessionDescription) { |
| } |
| |
| /** |
| * Called when the session is terminated. |
| * |
| * @param session the session object that is associated with the dialog |
| */ |
| public void onCallEnded(SipSession session) { |
| } |
| |
| /** |
| * Called when the peer is busy during session initialization. |
| * |
| * @param session the session object that carries out the transaction |
| */ |
| public void onCallBusy(SipSession session) { |
| } |
| |
| /** |
| * Called when the call is being transferred to a new one. |
| * |
| * @hide |
| * @param newSession the new session that the call will be transferred to |
| * @param sessionDescription the new peer's session description |
| */ |
| public void onCallTransferring(SipSession newSession, |
| String sessionDescription) { |
| } |
| |
| /** |
| * Called when an error occurs during session initialization and |
| * termination. |
| * |
| * @param session the session object that carries out the transaction |
| * @param errorCode error code defined in {@link SipErrorCode} |
| * @param errorMessage error message |
| */ |
| public void onError(SipSession session, int errorCode, |
| String errorMessage) { |
| } |
| |
| /** |
| * Called when an error occurs during session modification negotiation. |
| * |
| * @param session the session object that carries out the transaction |
| * @param errorCode error code defined in {@link SipErrorCode} |
| * @param errorMessage error message |
| */ |
| public void onCallChangeFailed(SipSession session, int errorCode, |
| String errorMessage) { |
| } |
| |
| /** |
| * Called when a registration request is sent. |
| * |
| * @param session the session object that carries out the transaction |
| */ |
| public void onRegistering(SipSession session) { |
| } |
| |
| /** |
| * Called when registration is successfully done. |
| * |
| * @param session the session object that carries out the transaction |
| * @param duration duration in second before the registration expires |
| */ |
| public void onRegistrationDone(SipSession session, int duration) { |
| } |
| |
| /** |
| * Called when the registration fails. |
| * |
| * @param session the session object that carries out the transaction |
| * @param errorCode error code defined in {@link SipErrorCode} |
| * @param errorMessage error message |
| */ |
| public void onRegistrationFailed(SipSession session, int errorCode, |
| String errorMessage) { |
| } |
| |
| /** |
| * Called when the registration gets timed out. |
| * |
| * @param session the session object that carries out the transaction |
| */ |
| public void onRegistrationTimeout(SipSession session) { |
| } |
| } |
| |
| private final ISipSession mSession; |
| private Listener mListener; |
| |
| SipSession(ISipSession realSession) { |
| mSession = realSession; |
| if (realSession != null) { |
| try { |
| realSession.setListener(createListener()); |
| } catch (RemoteException e) { |
| loge("SipSession.setListener:", e); |
| } |
| } |
| } |
| |
| SipSession(ISipSession realSession, Listener listener) { |
| this(realSession); |
| setListener(listener); |
| } |
| |
| /** |
| * Gets the IP address of the local host on which this SIP session runs. |
| * |
| * @return the IP address of the local host |
| */ |
| public String getLocalIp() { |
| try { |
| return mSession.getLocalIp(); |
| } catch (RemoteException e) { |
| loge("getLocalIp:", e); |
| return "127.0.0.1"; |
| } |
| } |
| |
| /** |
| * Gets the SIP profile that this session is associated with. |
| * |
| * @return the SIP profile that this session is associated with |
| */ |
| public SipProfile getLocalProfile() { |
| try { |
| return mSession.getLocalProfile(); |
| } catch (RemoteException e) { |
| loge("getLocalProfile:", e); |
| return null; |
| } |
| } |
| |
| /** |
| * Gets the SIP profile that this session is connected to. Only available |
| * when the session is associated with a SIP dialog. |
| * |
| * @return the SIP profile that this session is connected to |
| */ |
| public SipProfile getPeerProfile() { |
| try { |
| return mSession.getPeerProfile(); |
| } catch (RemoteException e) { |
| loge("getPeerProfile:", e); |
| return null; |
| } |
| } |
| |
| /** |
| * Gets the session state. The value returned must be one of the states in |
| * {@link State}. |
| * |
| * @return the session state |
| */ |
| public int getState() { |
| try { |
| return mSession.getState(); |
| } catch (RemoteException e) { |
| loge("getState:", e); |
| return State.NOT_DEFINED; |
| } |
| } |
| |
| /** |
| * Checks if the session is in a call. |
| * |
| * @return true if the session is in a call |
| */ |
| public boolean isInCall() { |
| try { |
| return mSession.isInCall(); |
| } catch (RemoteException e) { |
| loge("isInCall:", e); |
| return false; |
| } |
| } |
| |
| /** |
| * Gets the call ID of the session. |
| * |
| * @return the call ID |
| */ |
| public String getCallId() { |
| try { |
| return mSession.getCallId(); |
| } catch (RemoteException e) { |
| loge("getCallId:", e); |
| return null; |
| } |
| } |
| |
| |
| /** |
| * Sets the listener to listen to the session events. A {@code SipSession} |
| * can only hold one listener at a time. Subsequent calls to this method |
| * override the previous listener. |
| * |
| * @param listener to listen to the session events of this object |
| */ |
| public void setListener(Listener listener) { |
| mListener = listener; |
| } |
| |
| |
| /** |
| * Performs registration to the server specified by the associated local |
| * profile. The session listener is called back upon success or failure of |
| * registration. The method is only valid to call when the session state is |
| * in {@link State#READY_TO_CALL}. |
| * |
| * @param duration duration in second before the registration expires |
| * @see Listener |
| */ |
| public void register(int duration) { |
| try { |
| mSession.register(duration); |
| } catch (RemoteException e) { |
| loge("register:", e); |
| } |
| } |
| |
| /** |
| * Performs unregistration to the server specified by the associated local |
| * profile. Unregistration is technically the same as registration with zero |
| * expiration duration. The session listener is called back upon success or |
| * failure of unregistration. The method is only valid to call when the |
| * session state is in {@link State#READY_TO_CALL}. |
| * |
| * @see Listener |
| */ |
| public void unregister() { |
| try { |
| mSession.unregister(); |
| } catch (RemoteException e) { |
| loge("unregister:", e); |
| } |
| } |
| |
| /** |
| * Initiates a call to the specified profile. The session listener is called |
| * back upon defined session events. The method is only valid to call when |
| * the session state is in {@link State#READY_TO_CALL}. |
| * |
| * @param callee the SIP profile to make the call to |
| * @param sessionDescription the session description of this call |
| * @param timeout the session will be timed out if the call is not |
| * established within {@code timeout} seconds. Default value (defined |
| * by SIP protocol) is used if {@code timeout} is zero or negative. |
| * @see Listener |
| */ |
| public void makeCall(SipProfile callee, String sessionDescription, |
| int timeout) { |
| try { |
| mSession.makeCall(callee, sessionDescription, timeout); |
| } catch (RemoteException e) { |
| loge("makeCall:", e); |
| } |
| } |
| |
| /** |
| * Answers an incoming call with the specified session description. The |
| * method is only valid to call when the session state is in |
| * {@link State#INCOMING_CALL}. |
| * |
| * @param sessionDescription the session description to answer this call |
| * @param timeout the session will be timed out if the call is not |
| * established within {@code timeout} seconds. Default value (defined |
| * by SIP protocol) is used if {@code timeout} is zero or negative. |
| */ |
| public void answerCall(String sessionDescription, int timeout) { |
| try { |
| mSession.answerCall(sessionDescription, timeout); |
| } catch (RemoteException e) { |
| loge("answerCall:", e); |
| } |
| } |
| |
| /** |
| * Ends an established call, terminates an outgoing call or rejects an |
| * incoming call. The method is only valid to call when the session state is |
| * in {@link State#IN_CALL}, |
| * {@link State#INCOMING_CALL}, |
| * {@link State#OUTGOING_CALL} or |
| * {@link State#OUTGOING_CALL_RING_BACK}. |
| */ |
| public void endCall() { |
| try { |
| mSession.endCall(); |
| } catch (RemoteException e) { |
| loge("endCall:", e); |
| } |
| } |
| |
| /** |
| * Changes the session description during a call. The method is only valid |
| * to call when the session state is in {@link State#IN_CALL}. |
| * |
| * @param sessionDescription the new session description |
| * @param timeout the session will be timed out if the call is not |
| * established within {@code timeout} seconds. Default value (defined |
| * by SIP protocol) is used if {@code timeout} is zero or negative. |
| */ |
| public void changeCall(String sessionDescription, int timeout) { |
| try { |
| mSession.changeCall(sessionDescription, timeout); |
| } catch (RemoteException e) { |
| loge("changeCall:", e); |
| } |
| } |
| |
| ISipSession getRealSession() { |
| return mSession; |
| } |
| |
| private ISipSessionListener createListener() { |
| return new ISipSessionListener.Stub() { |
| @Override |
| public void onCalling(ISipSession session) { |
| if (mListener != null) { |
| mListener.onCalling(SipSession.this); |
| } |
| } |
| |
| @Override |
| public void onRinging(ISipSession session, SipProfile caller, |
| String sessionDescription) { |
| if (mListener != null) { |
| mListener.onRinging(SipSession.this, caller, |
| sessionDescription); |
| } |
| } |
| |
| @Override |
| public void onRingingBack(ISipSession session) { |
| if (mListener != null) { |
| mListener.onRingingBack(SipSession.this); |
| } |
| } |
| |
| @Override |
| public void onCallEstablished(ISipSession session, |
| String sessionDescription) { |
| if (mListener != null) { |
| mListener.onCallEstablished(SipSession.this, |
| sessionDescription); |
| } |
| } |
| |
| @Override |
| public void onCallEnded(ISipSession session) { |
| if (mListener != null) { |
| mListener.onCallEnded(SipSession.this); |
| } |
| } |
| |
| @Override |
| public void onCallBusy(ISipSession session) { |
| if (mListener != null) { |
| mListener.onCallBusy(SipSession.this); |
| } |
| } |
| |
| @Override |
| public void onCallTransferring(ISipSession session, |
| String sessionDescription) { |
| if (mListener != null) { |
| mListener.onCallTransferring( |
| new SipSession(session, SipSession.this.mListener), |
| sessionDescription); |
| |
| } |
| } |
| |
| @Override |
| public void onCallChangeFailed(ISipSession session, int errorCode, |
| String message) { |
| if (mListener != null) { |
| mListener.onCallChangeFailed(SipSession.this, errorCode, |
| message); |
| } |
| } |
| |
| @Override |
| public void onError(ISipSession session, int errorCode, String message) { |
| if (mListener != null) { |
| mListener.onError(SipSession.this, errorCode, message); |
| } |
| } |
| |
| @Override |
| public void onRegistering(ISipSession session) { |
| if (mListener != null) { |
| mListener.onRegistering(SipSession.this); |
| } |
| } |
| |
| @Override |
| public void onRegistrationDone(ISipSession session, int duration) { |
| if (mListener != null) { |
| mListener.onRegistrationDone(SipSession.this, duration); |
| } |
| } |
| |
| @Override |
| public void onRegistrationFailed(ISipSession session, int errorCode, |
| String message) { |
| if (mListener != null) { |
| mListener.onRegistrationFailed(SipSession.this, errorCode, |
| message); |
| } |
| } |
| |
| @Override |
| public void onRegistrationTimeout(ISipSession session) { |
| if (mListener != null) { |
| mListener.onRegistrationTimeout(SipSession.this); |
| } |
| } |
| }; |
| } |
| |
| private void loge(String s, Throwable t) { |
| Rlog.e(TAG, s, t); |
| } |
| } |