1 /* 2 * Copyright (C) 2017 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.telephony.ims.stub; 18 19 import android.annotation.SystemApi; 20 import android.os.Message; 21 import android.os.RemoteException; 22 import android.telephony.ims.ImsCallSessionListener; 23 import android.telephony.ims.aidl.IImsCallSessionListener; 24 25 import android.telephony.ims.ImsCallProfile; 26 import android.telephony.ims.ImsReasonInfo; 27 import android.telephony.ims.ImsStreamMediaProfile; 28 import android.telephony.ims.ImsCallSession; 29 import com.android.ims.internal.IImsCallSession; 30 import com.android.ims.internal.IImsVideoCallProvider; 31 import android.telephony.ims.ImsVideoCallProvider; 32 33 /** 34 * Base implementation of IImsCallSession, which implements stub versions of the methods available. 35 * 36 * Override the methods that your implementation of ImsCallSession supports. 37 * 38 * @hide 39 */ 40 @SystemApi 41 // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you 42 // will break other implementations of ImsCallSession maintained by other ImsServices. 43 public class ImsCallSessionImplBase implements AutoCloseable { 44 /** 45 * Notify USSD Mode. 46 */ 47 public static final int USSD_MODE_NOTIFY = 0; 48 /** 49 * Request USSD Mode 50 */ 51 public static final int USSD_MODE_REQUEST = 1; 52 53 /** 54 * Defines IMS call session state. 55 */ 56 public static class State { 57 public static final int IDLE = 0; 58 public static final int INITIATED = 1; 59 public static final int NEGOTIATING = 2; 60 public static final int ESTABLISHING = 3; 61 public static final int ESTABLISHED = 4; 62 63 public static final int RENEGOTIATING = 5; 64 public static final int REESTABLISHING = 6; 65 66 public static final int TERMINATING = 7; 67 public static final int TERMINATED = 8; 68 69 public static final int INVALID = (-1); 70 71 /** 72 * Converts the state to string. 73 */ toString(int state)74 public static String toString(int state) { 75 switch (state) { 76 case IDLE: 77 return "IDLE"; 78 case INITIATED: 79 return "INITIATED"; 80 case NEGOTIATING: 81 return "NEGOTIATING"; 82 case ESTABLISHING: 83 return "ESTABLISHING"; 84 case ESTABLISHED: 85 return "ESTABLISHED"; 86 case RENEGOTIATING: 87 return "RENEGOTIATING"; 88 case REESTABLISHING: 89 return "REESTABLISHING"; 90 case TERMINATING: 91 return "TERMINATING"; 92 case TERMINATED: 93 return "TERMINATED"; 94 default: 95 return "UNKNOWN"; 96 } 97 } 98 99 /** 100 * @hide 101 */ State()102 private State() { 103 } 104 } 105 106 // Non-final for injection by tests 107 private IImsCallSession mServiceImpl = new IImsCallSession.Stub() { 108 @Override 109 public void close() { 110 ImsCallSessionImplBase.this.close(); 111 } 112 113 @Override 114 public String getCallId() { 115 return ImsCallSessionImplBase.this.getCallId(); 116 } 117 118 @Override 119 public ImsCallProfile getCallProfile() { 120 return ImsCallSessionImplBase.this.getCallProfile(); 121 } 122 123 @Override 124 public ImsCallProfile getLocalCallProfile() { 125 return ImsCallSessionImplBase.this.getLocalCallProfile(); 126 } 127 128 @Override 129 public ImsCallProfile getRemoteCallProfile() { 130 return ImsCallSessionImplBase.this.getRemoteCallProfile(); 131 } 132 133 @Override 134 public String getProperty(String name) { 135 return ImsCallSessionImplBase.this.getProperty(name); 136 } 137 138 @Override 139 public int getState() { 140 return ImsCallSessionImplBase.this.getState(); 141 } 142 143 @Override 144 public boolean isInCall() { 145 return ImsCallSessionImplBase.this.isInCall(); 146 } 147 148 @Override 149 public void setListener(IImsCallSessionListener listener) { 150 ImsCallSessionImplBase.this.setListener(new ImsCallSessionListener(listener)); 151 } 152 153 @Override 154 public void setMute(boolean muted) { 155 ImsCallSessionImplBase.this.setMute(muted); 156 } 157 158 @Override 159 public void start(String callee, ImsCallProfile profile) { 160 ImsCallSessionImplBase.this.start(callee, profile); 161 } 162 163 @Override 164 public void startConference(String[] participants, ImsCallProfile profile) throws 165 RemoteException { 166 ImsCallSessionImplBase.this.startConference(participants, profile); 167 } 168 169 @Override 170 public void accept(int callType, ImsStreamMediaProfile profile) { 171 ImsCallSessionImplBase.this.accept(callType, profile); 172 } 173 174 @Override 175 public void deflect(String deflectNumber) { 176 ImsCallSessionImplBase.this.deflect(deflectNumber); 177 } 178 179 @Override 180 public void reject(int reason) { 181 ImsCallSessionImplBase.this.reject(reason); 182 } 183 184 @Override 185 public void terminate(int reason) { 186 ImsCallSessionImplBase.this.terminate(reason); 187 } 188 189 @Override 190 public void hold(ImsStreamMediaProfile profile) { 191 ImsCallSessionImplBase.this.hold(profile); 192 } 193 194 @Override 195 public void resume(ImsStreamMediaProfile profile) { 196 ImsCallSessionImplBase.this.resume(profile); 197 } 198 199 @Override 200 public void merge() { 201 ImsCallSessionImplBase.this.merge(); 202 } 203 204 @Override 205 public void update(int callType, ImsStreamMediaProfile profile) { 206 ImsCallSessionImplBase.this.update(callType, profile); 207 } 208 209 @Override 210 public void extendToConference(String[] participants) { 211 ImsCallSessionImplBase.this.extendToConference(participants); 212 } 213 214 @Override 215 public void inviteParticipants(String[] participants) { 216 ImsCallSessionImplBase.this.inviteParticipants(participants); 217 } 218 219 @Override 220 public void removeParticipants(String[] participants) { 221 ImsCallSessionImplBase.this.removeParticipants(participants); 222 } 223 224 @Override 225 public void sendDtmf(char c, Message result) { 226 ImsCallSessionImplBase.this.sendDtmf(c, result); 227 } 228 229 @Override 230 public void startDtmf(char c) { 231 ImsCallSessionImplBase.this.startDtmf(c); 232 } 233 234 @Override 235 public void stopDtmf() { 236 ImsCallSessionImplBase.this.stopDtmf(); 237 } 238 239 @Override 240 public void sendUssd(String ussdMessage) { 241 ImsCallSessionImplBase.this.sendUssd(ussdMessage); 242 } 243 244 @Override 245 public IImsVideoCallProvider getVideoCallProvider() { 246 return ImsCallSessionImplBase.this.getVideoCallProvider(); 247 } 248 249 @Override 250 public boolean isMultiparty() { 251 return ImsCallSessionImplBase.this.isMultiparty(); 252 } 253 254 @Override 255 public void sendRttModifyRequest(ImsCallProfile toProfile) { 256 ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile); 257 } 258 259 @Override 260 public void sendRttModifyResponse(boolean status) { 261 ImsCallSessionImplBase.this.sendRttModifyResponse(status); 262 } 263 264 @Override 265 public void sendRttMessage(String rttMessage) { 266 ImsCallSessionImplBase.this.sendRttMessage(rttMessage); 267 } 268 }; 269 270 /** 271 * @hide 272 */ setListener(IImsCallSessionListener listener)273 public final void setListener(IImsCallSessionListener listener) throws RemoteException { 274 setListener(new ImsCallSessionListener(listener)); 275 } 276 277 /** 278 * Sets the listener to listen to the session events. An {@link ImsCallSession} 279 * can only hold one listener at a time. Subsequent calls to this method 280 * override the previous listener. 281 * 282 * @param listener {@link ImsCallSessionListener} used to notify the framework of updates 283 * to the ImsCallSession 284 */ setListener(ImsCallSessionListener listener)285 public void setListener(ImsCallSessionListener listener) { 286 } 287 288 /** 289 * Closes the object. This {@link ImsCallSessionImplBase} is not usable after being closed. 290 */ 291 @Override close()292 public void close() { 293 294 } 295 296 /** 297 * @return A String containing the unique call ID of this {@link ImsCallSessionImplBase}. 298 */ getCallId()299 public String getCallId() { 300 return null; 301 } 302 303 /** 304 * @return The {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is associated 305 * with. 306 */ getCallProfile()307 public ImsCallProfile getCallProfile() { 308 return null; 309 } 310 311 /** 312 * @return The local {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is 313 * associated with. 314 */ getLocalCallProfile()315 public ImsCallProfile getLocalCallProfile() { 316 return null; 317 } 318 319 /** 320 * @return The remote {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is 321 * associated with. 322 */ getRemoteCallProfile()323 public ImsCallProfile getRemoteCallProfile() { 324 return null; 325 } 326 327 /** 328 * @param name The String extra key. 329 * @return The string extra value associated with the specified property. 330 */ getProperty(String name)331 public String getProperty(String name) { 332 return null; 333 } 334 335 /** 336 * @return The {@link ImsCallSessionImplBase} state, defined in 337 * {@link ImsCallSessionImplBase.State}. 338 */ getState()339 public int getState() { 340 return ImsCallSessionImplBase.State.INVALID; 341 } 342 343 /** 344 * @return true if the {@link ImsCallSessionImplBase} is in a call, false otherwise. 345 */ isInCall()346 public boolean isInCall() { 347 return false; 348 } 349 350 /** 351 * Mutes or unmutes the mic for the active call. 352 * 353 * @param muted true if the call should be muted, false otherwise. 354 */ setMute(boolean muted)355 public void setMute(boolean muted) { 356 } 357 358 /** 359 * Initiates an IMS call with the specified number and call profile. 360 * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon 361 * defined session events. 362 * Only valid to call when the session state is in 363 * {@link ImsCallSession.State#IDLE}. 364 * 365 * @param callee dialed string to make the call to 366 * @param profile call profile to make the call with the specified service type, 367 * call type and media information 368 * @see {@link ImsCallSession.Listener#callSessionStarted}, 369 * {@link ImsCallSession.Listener#callSessionStartFailed} 370 */ start(String callee, ImsCallProfile profile)371 public void start(String callee, ImsCallProfile profile) { 372 } 373 374 /** 375 * Initiates an IMS call with the specified participants and call profile. 376 * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon 377 * defined session events. 378 * The method is only valid to call when the session state is in 379 * {@link ImsCallSession.State#IDLE}. 380 * 381 * @param participants participant list to initiate an IMS conference call 382 * @param profile call profile to make the call with the specified service type, 383 * call type and media information 384 * @see {@link ImsCallSession.Listener#callSessionStarted}, 385 * {@link ImsCallSession.Listener#callSessionStartFailed} 386 */ startConference(String[] participants, ImsCallProfile profile)387 public void startConference(String[] participants, ImsCallProfile profile) { 388 } 389 390 /** 391 * Accepts an incoming call or session update. 392 * 393 * @param callType call type specified in {@link ImsCallProfile} to be answered 394 * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered 395 * @see {@link ImsCallSession.Listener#callSessionStarted} 396 */ accept(int callType, ImsStreamMediaProfile profile)397 public void accept(int callType, ImsStreamMediaProfile profile) { 398 } 399 400 /** 401 * Deflects an incoming call. 402 * 403 * @param deflectNumber number to deflect the call 404 */ deflect(String deflectNumber)405 public void deflect(String deflectNumber) { 406 } 407 408 /** 409 * Rejects an incoming call or session update. 410 * 411 * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}. 412 * {@link ImsCallSession.Listener#callSessionStartFailed} 413 */ reject(int reason)414 public void reject(int reason) { 415 } 416 417 /** 418 * Terminates a call. 419 * 420 * @param reason reason code to terminate a call, defined in {@link ImsReasonInfo}. 421 * 422 * @see {@link ImsCallSession.Listener#callSessionTerminated} 423 */ terminate(int reason)424 public void terminate(int reason) { 425 } 426 427 /** 428 * Puts a call on hold. When it succeeds, {@link ImsCallSession.Listener#callSessionHeld} is 429 * called. 430 * 431 * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call 432 * @see {@link ImsCallSession.Listener#callSessionHeld}, 433 * {@link ImsCallSession.Listener#callSessionHoldFailed} 434 */ hold(ImsStreamMediaProfile profile)435 public void hold(ImsStreamMediaProfile profile) { 436 } 437 438 /** 439 * Continues a call that's on hold. When it succeeds, 440 * {@link ImsCallSession.Listener#callSessionResumed} is called. 441 * 442 * @param profile stream media profile with {@link ImsStreamMediaProfile} to resume the call 443 * @see {@link ImsCallSession.Listener#callSessionResumed}, 444 * {@link ImsCallSession.Listener#callSessionResumeFailed} 445 */ resume(ImsStreamMediaProfile profile)446 public void resume(ImsStreamMediaProfile profile) { 447 } 448 449 /** 450 * Merges the active and held call. When the merge starts, 451 * {@link ImsCallSession.Listener#callSessionMergeStarted} is called. 452 * {@link ImsCallSession.Listener#callSessionMergeComplete} is called if the merge is 453 * successful, and {@link ImsCallSession.Listener#callSessionMergeFailed} is called if the merge 454 * fails. 455 * 456 * @see {@link ImsCallSession.Listener#callSessionMergeStarted}, 457 * {@link ImsCallSession.Listener#callSessionMergeComplete}, 458 * {@link ImsCallSession.Listener#callSessionMergeFailed} 459 */ merge()460 public void merge() { 461 } 462 463 /** 464 * Updates the current call's properties (ex. call mode change: video upgrade / downgrade). 465 * 466 * @param callType call type specified in {@link ImsCallProfile} to be updated 467 * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated 468 * @see {@link ImsCallSession.Listener#callSessionUpdated}, 469 * {@link ImsCallSession.Listener#callSessionUpdateFailed} 470 */ update(int callType, ImsStreamMediaProfile profile)471 public void update(int callType, ImsStreamMediaProfile profile) { 472 } 473 474 /** 475 * Extends this call to the conference call with the specified recipients. 476 * 477 * @param participants participant list to be invited to the conference call after extending the 478 * call 479 * @see {@link ImsCallSession.Listener#callSessionConferenceExtended}, 480 * {@link ImsCallSession.Listener#callSessionConferenceExtendFailed} 481 */ extendToConference(String[] participants)482 public void extendToConference(String[] participants) { 483 } 484 485 /** 486 * Requests the conference server to invite an additional participants to the conference. 487 * 488 * @param participants participant list to be invited to the conference call 489 * @see {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestDelivered}, 490 * {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestFailed} 491 */ inviteParticipants(String[] participants)492 public void inviteParticipants(String[] participants) { 493 } 494 495 /** 496 * Requests the conference server to remove the specified participants from the conference. 497 * 498 * @param participants participant list to be removed from the conference call 499 * @see {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestDelivered}, 500 * {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestFailed} 501 */ removeParticipants(String[] participants)502 public void removeParticipants(String[] participants) { 503 } 504 505 /** 506 * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>, 507 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15, 508 * and event flash to 16. Currently, event flash is not supported. 509 * 510 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs. 511 * @param result If non-null, the {@link Message} to send when the operation is complete. This 512 * is done by using the associated {@link android.os.Messenger} in 513 * {@link Message#replyTo}. For example: 514 * {@code 515 * // Send DTMF and other operations... 516 * try { 517 * // Notify framework that the DTMF was sent. 518 * Messenger dtmfMessenger = result.replyTo; 519 * if (dtmfMessenger != null) { 520 * dtmfMessenger.send(result); 521 * } 522 * } catch (RemoteException e) { 523 * // Remote side is dead 524 * } 525 * } 526 */ sendDtmf(char c, Message result)527 public void sendDtmf(char c, Message result) { 528 } 529 530 /** 531 * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>, 532 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15, 533 * and event flash to 16. Currently, event flash is not supported. 534 * 535 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs. 536 */ startDtmf(char c)537 public void startDtmf(char c) { 538 } 539 540 /** 541 * Stop a DTMF code. 542 */ stopDtmf()543 public void stopDtmf() { 544 } 545 546 /** 547 * Sends an USSD message. 548 * 549 * @param ussdMessage USSD message to send 550 */ sendUssd(String ussdMessage)551 public void sendUssd(String ussdMessage) { 552 } 553 554 /** 555 * See {@link #getImsVideoCallProvider()}, used directly in older ImsService implementations. 556 * @hide 557 */ getVideoCallProvider()558 public IImsVideoCallProvider getVideoCallProvider() { 559 ImsVideoCallProvider provider = getImsVideoCallProvider(); 560 return provider != null ? provider.getInterface() : null; 561 } 562 563 /** 564 * @return The {@link ImsVideoCallProvider} implementation contained within the IMS service 565 * process. 566 */ getImsVideoCallProvider()567 public ImsVideoCallProvider getImsVideoCallProvider() { 568 return null; 569 } 570 571 /** 572 * Determines if the current session is multiparty. 573 * @return {@code True} if the session is multiparty. 574 */ isMultiparty()575 public boolean isMultiparty() { 576 return false; 577 } 578 579 /** 580 * Device issues RTT modify request 581 * @param toProfile The profile with requested changes made 582 */ sendRttModifyRequest(ImsCallProfile toProfile)583 public void sendRttModifyRequest(ImsCallProfile toProfile) { 584 } 585 586 /** 587 * Device responds to Remote RTT modify request 588 * @param status true if the the request was accepted or false of the request is defined. 589 */ sendRttModifyResponse(boolean status)590 public void sendRttModifyResponse(boolean status) { 591 } 592 593 /** 594 * Device sends RTT message 595 * @param rttMessage RTT message to be sent 596 */ sendRttMessage(String rttMessage)597 public void sendRttMessage(String rttMessage) { 598 } 599 600 /** @hide */ getServiceImpl()601 public IImsCallSession getServiceImpl() { 602 return mServiceImpl; 603 } 604 605 /** @hide */ setServiceImpl(IImsCallSession serviceImpl)606 public void setServiceImpl(IImsCallSession serviceImpl) { 607 mServiceImpl = serviceImpl; 608 } 609 } 610