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.telephony.Rlog; 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 */ toString(int state)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 State()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 */ onCalling(SipSession session)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 */ onRinging(SipSession session, SipProfile caller, String sessionDescription)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 */ onRingingBack(SipSession session)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 */ onCallEstablished(SipSession session, String sessionDescription)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 */ onCallEnded(SipSession session)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 */ onCallBusy(SipSession session)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 */ onCallTransferring(SipSession newSession, String sessionDescription)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 */ onError(SipSession session, int errorCode, String errorMessage)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 */ onCallChangeFailed(SipSession session, int errorCode, String errorMessage)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 */ onRegistering(SipSession session)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 */ onRegistrationDone(SipSession session, int duration)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 */ onRegistrationFailed(SipSession session, int errorCode, String errorMessage)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 */ onRegistrationTimeout(SipSession session)232 public void onRegistrationTimeout(SipSession session) { 233 } 234 } 235 236 private final ISipSession mSession; 237 private Listener mListener; 238 SipSession(ISipSession realSession)239 SipSession(ISipSession realSession) { 240 mSession = realSession; 241 if (realSession != null) { 242 try { 243 realSession.setListener(createListener()); 244 } catch (RemoteException e) { 245 loge("SipSession.setListener:", e); 246 } 247 } 248 } 249 SipSession(ISipSession realSession, Listener listener)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 */ getLocalIp()260 public String getLocalIp() { 261 try { 262 return mSession.getLocalIp(); 263 } catch (RemoteException e) { 264 loge("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 */ getLocalProfile()274 public SipProfile getLocalProfile() { 275 try { 276 return mSession.getLocalProfile(); 277 } catch (RemoteException e) { 278 loge("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 */ getPeerProfile()289 public SipProfile getPeerProfile() { 290 try { 291 return mSession.getPeerProfile(); 292 } catch (RemoteException e) { 293 loge("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 */ getState()304 public int getState() { 305 try { 306 return mSession.getState(); 307 } catch (RemoteException e) { 308 loge("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 */ isInCall()318 public boolean isInCall() { 319 try { 320 return mSession.isInCall(); 321 } catch (RemoteException e) { 322 loge("isInCall:", e); 323 return false; 324 } 325 } 326 327 /** 328 * Gets the call ID of the session. 329 * 330 * @return the call ID 331 */ getCallId()332 public String getCallId() { 333 try { 334 return mSession.getCallId(); 335 } catch (RemoteException e) { 336 loge("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 */ setListener(Listener listener)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 */ register(int duration)363 public void register(int duration) { 364 try { 365 mSession.register(duration); 366 } catch (RemoteException e) { 367 loge("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 */ unregister()380 public void unregister() { 381 try { 382 mSession.unregister(); 383 } catch (RemoteException e) { 384 loge("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 */ makeCall(SipProfile callee, String sessionDescription, int timeout)400 public void makeCall(SipProfile callee, String sessionDescription, 401 int timeout) { 402 try { 403 mSession.makeCall(callee, sessionDescription, timeout); 404 } catch (RemoteException e) { 405 loge("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 */ answerCall(String sessionDescription, int timeout)419 public void answerCall(String sessionDescription, int timeout) { 420 try { 421 mSession.answerCall(sessionDescription, timeout); 422 } catch (RemoteException e) { 423 loge("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 */ endCall()435 public void endCall() { 436 try { 437 mSession.endCall(); 438 } catch (RemoteException e) { 439 loge("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 */ changeCall(String sessionDescription, int timeout)452 public void changeCall(String sessionDescription, int timeout) { 453 try { 454 mSession.changeCall(sessionDescription, timeout); 455 } catch (RemoteException e) { 456 loge("changeCall:", e); 457 } 458 } 459 getRealSession()460 ISipSession getRealSession() { 461 return mSession; 462 } 463 createListener()464 private ISipSessionListener createListener() { 465 return new ISipSessionListener.Stub() { 466 @Override 467 public void onCalling(ISipSession session) { 468 if (mListener != null) { 469 mListener.onCalling(SipSession.this); 470 } 471 } 472 473 @Override 474 public void onRinging(ISipSession session, SipProfile caller, 475 String sessionDescription) { 476 if (mListener != null) { 477 mListener.onRinging(SipSession.this, caller, 478 sessionDescription); 479 } 480 } 481 482 @Override 483 public void onRingingBack(ISipSession session) { 484 if (mListener != null) { 485 mListener.onRingingBack(SipSession.this); 486 } 487 } 488 489 @Override 490 public void onCallEstablished(ISipSession session, 491 String sessionDescription) { 492 if (mListener != null) { 493 mListener.onCallEstablished(SipSession.this, 494 sessionDescription); 495 } 496 } 497 498 @Override 499 public void onCallEnded(ISipSession session) { 500 if (mListener != null) { 501 mListener.onCallEnded(SipSession.this); 502 } 503 } 504 505 @Override 506 public void onCallBusy(ISipSession session) { 507 if (mListener != null) { 508 mListener.onCallBusy(SipSession.this); 509 } 510 } 511 512 @Override 513 public void onCallTransferring(ISipSession session, 514 String sessionDescription) { 515 if (mListener != null) { 516 mListener.onCallTransferring( 517 new SipSession(session, SipSession.this.mListener), 518 sessionDescription); 519 520 } 521 } 522 523 @Override 524 public void onCallChangeFailed(ISipSession session, int errorCode, 525 String message) { 526 if (mListener != null) { 527 mListener.onCallChangeFailed(SipSession.this, errorCode, 528 message); 529 } 530 } 531 532 @Override 533 public void onError(ISipSession session, int errorCode, String message) { 534 if (mListener != null) { 535 mListener.onError(SipSession.this, errorCode, message); 536 } 537 } 538 539 @Override 540 public void onRegistering(ISipSession session) { 541 if (mListener != null) { 542 mListener.onRegistering(SipSession.this); 543 } 544 } 545 546 @Override 547 public void onRegistrationDone(ISipSession session, int duration) { 548 if (mListener != null) { 549 mListener.onRegistrationDone(SipSession.this, duration); 550 } 551 } 552 553 @Override 554 public void onRegistrationFailed(ISipSession session, int errorCode, 555 String message) { 556 if (mListener != null) { 557 mListener.onRegistrationFailed(SipSession.this, errorCode, 558 message); 559 } 560 } 561 562 @Override 563 public void onRegistrationTimeout(ISipSession session) { 564 if (mListener != null) { 565 mListener.onRegistrationTimeout(SipSession.this); 566 } 567 } 568 }; 569 } 570 571 private void loge(String s, Throwable t) { 572 Rlog.e(TAG, s, t); 573 } 574 } 575