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