/* * 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. *

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).

*/ 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"). *

Many of these events are also received by {@link SipAudioCall.Listener}.

*/ 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); } }