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