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.NonNull; 20 import android.annotation.SystemApi; 21 import android.os.Message; 22 import android.os.RemoteException; 23 import android.telephony.ims.ImsCallProfile; 24 import android.telephony.ims.ImsCallSession; 25 import android.telephony.ims.ImsCallSessionListener; 26 import android.telephony.ims.ImsReasonInfo; 27 import android.telephony.ims.ImsStreamMediaProfile; 28 import android.telephony.ims.ImsVideoCallProvider; 29 import android.telephony.ims.RtpHeaderExtension; 30 import android.telephony.ims.RtpHeaderExtensionType; 31 import android.telephony.ims.aidl.IImsCallSessionListener; 32 import android.util.ArraySet; 33 import android.util.Log; 34 35 import com.android.ims.internal.IImsCallSession; 36 import com.android.ims.internal.IImsVideoCallProvider; 37 import com.android.internal.telephony.util.TelephonyUtils; 38 39 import java.util.List; 40 import java.util.Set; 41 import java.util.concurrent.CancellationException; 42 import java.util.concurrent.CompletableFuture; 43 import java.util.concurrent.CompletionException; 44 import java.util.concurrent.ExecutionException; 45 import java.util.concurrent.Executor; 46 import java.util.function.Supplier; 47 48 /** 49 * Base implementation of IImsCallSession, which implements stub versions of the methods available. 50 * 51 * Override the methods that your implementation of ImsCallSession supports. 52 * 53 * @hide 54 */ 55 @SystemApi 56 // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you 57 // will break other implementations of ImsCallSession maintained by other ImsServices. 58 public class ImsCallSessionImplBase implements AutoCloseable { 59 60 private static final String LOG_TAG = "ImsCallSessionImplBase"; 61 /** 62 * Notify USSD Mode. 63 */ 64 public static final int USSD_MODE_NOTIFY = 0; 65 /** 66 * Request USSD Mode 67 */ 68 public static final int USSD_MODE_REQUEST = 1; 69 70 /** 71 * Defines IMS call session state. 72 */ 73 public static class State { 74 public static final int IDLE = 0; 75 public static final int INITIATED = 1; 76 public static final int NEGOTIATING = 2; 77 public static final int ESTABLISHING = 3; 78 public static final int ESTABLISHED = 4; 79 80 public static final int RENEGOTIATING = 5; 81 public static final int REESTABLISHING = 6; 82 83 public static final int TERMINATING = 7; 84 public static final int TERMINATED = 8; 85 86 public static final int INVALID = (-1); 87 88 /** 89 * Converts the state to string. 90 */ toString(int state)91 public static String toString(int state) { 92 switch (state) { 93 case IDLE: 94 return "IDLE"; 95 case INITIATED: 96 return "INITIATED"; 97 case NEGOTIATING: 98 return "NEGOTIATING"; 99 case ESTABLISHING: 100 return "ESTABLISHING"; 101 case ESTABLISHED: 102 return "ESTABLISHED"; 103 case RENEGOTIATING: 104 return "RENEGOTIATING"; 105 case REESTABLISHING: 106 return "REESTABLISHING"; 107 case TERMINATING: 108 return "TERMINATING"; 109 case TERMINATED: 110 return "TERMINATED"; 111 default: 112 return "UNKNOWN"; 113 } 114 } 115 116 /** 117 * @hide 118 */ State()119 private State() { 120 } 121 } 122 123 private Executor mExecutor = Runnable::run; 124 125 // Non-final for injection by tests 126 private IImsCallSession mServiceImpl = new IImsCallSession.Stub() { 127 @Override 128 public void close() { 129 executeMethodAsync(() -> ImsCallSessionImplBase.this.close(), "close"); 130 } 131 132 @Override 133 public String getCallId() { 134 return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallId(), 135 "getCallId"); 136 } 137 138 @Override 139 public ImsCallProfile getCallProfile() { 140 return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallProfile(), 141 "getCallProfile"); 142 } 143 144 @Override 145 public ImsCallProfile getLocalCallProfile() { 146 return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this 147 .getLocalCallProfile(), "getLocalCallProfile"); 148 } 149 150 @Override 151 public ImsCallProfile getRemoteCallProfile() { 152 return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this 153 .getRemoteCallProfile(), "getRemoteCallProfile"); 154 } 155 156 @Override 157 public String getProperty(String name) { 158 return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getProperty(name), 159 "getProperty"); 160 } 161 162 @Override 163 public int getState() { 164 return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getState(), 165 "getState"); 166 } 167 168 @Override 169 public boolean isInCall() { 170 return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isInCall(), 171 "isInCall"); 172 } 173 174 @Override 175 public void setListener(IImsCallSessionListener listener) { 176 executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener( 177 new ImsCallSessionListener(listener)), "setListener"); 178 } 179 180 @Override 181 public void setMute(boolean muted) { 182 executeMethodAsync(() -> ImsCallSessionImplBase.this.setMute(muted), "setMute"); 183 } 184 185 @Override 186 public void start(String callee, ImsCallProfile profile) { 187 executeMethodAsync(() -> ImsCallSessionImplBase.this.start(callee, profile), "start"); 188 } 189 190 @Override 191 public void startConference(String[] participants, ImsCallProfile profile) throws 192 RemoteException { 193 executeMethodAsync(() -> ImsCallSessionImplBase.this.startConference(participants, 194 profile), "startConference"); 195 } 196 197 @Override 198 public void accept(int callType, ImsStreamMediaProfile profile) { 199 executeMethodAsync(() -> ImsCallSessionImplBase.this.accept(callType, profile), 200 "accept"); 201 } 202 203 @Override 204 public void deflect(String deflectNumber) { 205 executeMethodAsync(() -> ImsCallSessionImplBase.this.deflect(deflectNumber), 206 "deflect"); 207 } 208 209 @Override 210 public void reject(int reason) { 211 executeMethodAsync(() -> ImsCallSessionImplBase.this.reject(reason), "reject"); 212 } 213 214 @Override 215 public void transfer(@NonNull String number, boolean isConfirmationRequired) { 216 executeMethodAsync(() -> ImsCallSessionImplBase.this.transfer(number, 217 isConfirmationRequired), "transfer"); 218 } 219 220 @Override 221 public void consultativeTransfer(@NonNull IImsCallSession transferToSession) { 222 executeMethodAsync(() -> { 223 ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase(); 224 otherSession.setServiceImpl(transferToSession); 225 ImsCallSessionImplBase.this.transfer(otherSession); 226 }, "consultativeTransfer"); 227 } 228 229 @Override 230 public void terminate(int reason) { 231 executeMethodAsync(() -> ImsCallSessionImplBase.this.terminate(reason), "terminate"); 232 } 233 234 @Override 235 public void hold(ImsStreamMediaProfile profile) { 236 executeMethodAsync(() -> ImsCallSessionImplBase.this.hold(profile), "hold"); 237 } 238 239 @Override 240 public void resume(ImsStreamMediaProfile profile) { 241 executeMethodAsync(() -> ImsCallSessionImplBase.this.resume(profile), "resume"); 242 } 243 244 @Override 245 public void merge() { 246 executeMethodAsync(() -> ImsCallSessionImplBase.this.merge(), "merge"); 247 } 248 249 @Override 250 public void update(int callType, ImsStreamMediaProfile profile) { 251 executeMethodAsync(() -> ImsCallSessionImplBase.this.update(callType, profile), 252 "update"); 253 } 254 255 @Override 256 public void extendToConference(String[] participants) { 257 executeMethodAsync(() -> ImsCallSessionImplBase.this.extendToConference(participants), 258 "extendToConference"); 259 } 260 261 @Override 262 public void inviteParticipants(String[] participants) { 263 executeMethodAsync(() -> ImsCallSessionImplBase.this.inviteParticipants(participants), 264 "inviteParticipants"); 265 } 266 267 @Override 268 public void removeParticipants(String[] participants) { 269 executeMethodAsync(() -> ImsCallSessionImplBase.this.removeParticipants(participants), 270 "removeParticipants"); 271 } 272 273 @Override 274 public void sendDtmf(char c, Message result) { 275 executeMethodAsync(() -> ImsCallSessionImplBase.this.sendDtmf(c, result), "sendDtmf"); 276 } 277 278 @Override 279 public void startDtmf(char c) { 280 executeMethodAsync(() -> ImsCallSessionImplBase.this.startDtmf(c), "startDtmf"); 281 } 282 283 @Override 284 public void stopDtmf() { 285 executeMethodAsync(() -> ImsCallSessionImplBase.this.stopDtmf(), "stopDtmf"); 286 } 287 288 @Override 289 public void sendUssd(String ussdMessage) { 290 executeMethodAsync(() -> ImsCallSessionImplBase.this.sendUssd(ussdMessage), "sendUssd"); 291 } 292 293 @Override 294 public IImsVideoCallProvider getVideoCallProvider() { 295 return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this 296 .getVideoCallProvider(), "getVideoCallProvider"); 297 } 298 299 @Override 300 public boolean isMultiparty() { 301 return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isMultiparty(), 302 "isMultiparty"); 303 } 304 305 @Override 306 public void sendRttModifyRequest(ImsCallProfile toProfile) { 307 executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile), 308 "sendRttModifyRequest"); 309 } 310 311 @Override 312 public void sendRttModifyResponse(boolean status) { 313 executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyResponse(status), 314 "sendRttModifyResponse"); 315 } 316 317 @Override 318 public void sendRttMessage(String rttMessage) { 319 executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttMessage(rttMessage), 320 "sendRttMessage"); 321 } 322 323 @Override 324 public void sendRtpHeaderExtensions(@NonNull List<RtpHeaderExtension> extensions) { 325 executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRtpHeaderExtensions( 326 new ArraySet<RtpHeaderExtension>(extensions)), "sendRtpHeaderExtensions"); 327 } 328 329 // Call the methods with a clean calling identity on the executor and wait indefinitely for 330 // the future to return. 331 private void executeMethodAsync(Runnable r, String errorLogName) { 332 try { 333 CompletableFuture.runAsync( 334 () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join(); 335 } catch (CancellationException | CompletionException e) { 336 Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: " 337 + e.getMessage()); 338 } 339 } 340 341 private <T> T executeMethodAsyncForResult(Supplier<T> r, 342 String errorLogName) { 343 CompletableFuture<T> future = CompletableFuture.supplyAsync( 344 () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor); 345 try { 346 return future.get(); 347 } catch (ExecutionException | InterruptedException e) { 348 Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: " 349 + e.getMessage()); 350 return null; 351 } 352 } 353 }; 354 355 /** 356 * @hide 357 */ setListener(IImsCallSessionListener listener)358 public final void setListener(IImsCallSessionListener listener) throws RemoteException { 359 setListener(new ImsCallSessionListener(listener)); 360 } 361 362 /** 363 * Sets the listener to listen to the session events. An {@link ImsCallSession} 364 * can only hold one listener at a time. Subsequent calls to this method 365 * override the previous listener. 366 * 367 * @param listener {@link ImsCallSessionListener} used to notify the framework of updates 368 * to the ImsCallSession 369 */ setListener(ImsCallSessionListener listener)370 public void setListener(ImsCallSessionListener listener) { 371 } 372 373 /** 374 * Closes the object. This {@link ImsCallSessionImplBase} is not usable after being closed. 375 */ 376 @Override close()377 public void close() { 378 379 } 380 381 /** 382 * @return A String containing the unique call ID of this {@link ImsCallSessionImplBase}. 383 */ getCallId()384 public String getCallId() { 385 return null; 386 } 387 388 /** 389 * @return The {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is associated 390 * with. 391 */ getCallProfile()392 public ImsCallProfile getCallProfile() { 393 return null; 394 } 395 396 /** 397 * @return The local {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is 398 * associated with. 399 */ getLocalCallProfile()400 public ImsCallProfile getLocalCallProfile() { 401 return null; 402 } 403 404 /** 405 * @return The remote {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is 406 * associated with. 407 */ getRemoteCallProfile()408 public ImsCallProfile getRemoteCallProfile() { 409 return null; 410 } 411 412 /** 413 * @param name The String extra key. 414 * @return The string extra value associated with the specified property. 415 */ getProperty(String name)416 public String getProperty(String name) { 417 return null; 418 } 419 420 /** 421 * @return The {@link ImsCallSessionImplBase} state, defined in 422 * {@link ImsCallSessionImplBase.State}. 423 */ getState()424 public int getState() { 425 return ImsCallSessionImplBase.State.INVALID; 426 } 427 428 /** 429 * @return true if the {@link ImsCallSessionImplBase} is in a call, false otherwise. 430 */ isInCall()431 public boolean isInCall() { 432 return false; 433 } 434 435 /** 436 * Mutes or unmutes the mic for the active call. 437 * 438 * @param muted true if the call should be muted, false otherwise. 439 */ setMute(boolean muted)440 public void setMute(boolean muted) { 441 } 442 443 /** 444 * Initiates an IMS call with the specified number and call profile. 445 * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon 446 * defined session events. 447 * Only valid to call when the session state is in 448 * {@link ImsCallSession.State#IDLE}. 449 * 450 * @param callee dialed string to make the call to 451 * @param profile call profile to make the call with the specified service type, 452 * call type and media information 453 * @see {@link ImsCallSession.Listener#callSessionStarted}, 454 * {@link ImsCallSession.Listener#callSessionStartFailed} 455 */ start(String callee, ImsCallProfile profile)456 public void start(String callee, ImsCallProfile profile) { 457 } 458 459 /** 460 * Initiates an IMS call with the specified participants and call profile. 461 * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon 462 * defined session events. 463 * The method is only valid to call when the session state is in 464 * {@link ImsCallSession.State#IDLE}. 465 * 466 * @param participants participant list to initiate an IMS conference call 467 * @param profile call profile to make the call with the specified service type, 468 * call type and media information 469 * @see {@link ImsCallSession.Listener#callSessionStarted}, 470 * {@link ImsCallSession.Listener#callSessionStartFailed} 471 */ startConference(String[] participants, ImsCallProfile profile)472 public void startConference(String[] participants, ImsCallProfile profile) { 473 } 474 475 /** 476 * Accepts an incoming call or session update. 477 * 478 * @param callType call type specified in {@link ImsCallProfile} to be answered 479 * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered 480 * @see {@link ImsCallSession.Listener#callSessionStarted} 481 */ accept(int callType, ImsStreamMediaProfile profile)482 public void accept(int callType, ImsStreamMediaProfile profile) { 483 } 484 485 /** 486 * Deflects an incoming call. 487 * 488 * @param deflectNumber number to deflect the call 489 */ deflect(String deflectNumber)490 public void deflect(String deflectNumber) { 491 } 492 493 /** 494 * Rejects an incoming call or session update. 495 * 496 * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}. 497 * The {@link android.telecom.InCallService} (dialer app) can use the 498 * {@link android.telecom.Call#reject(int)} API to reject a call while specifying 499 * a user-indicated reason for rejecting the call. 500 * Normal call declines ({@link android.telecom.Call#REJECT_REASON_DECLINED}) will 501 * map to {@link ImsReasonInfo#CODE_USER_DECLINE}. 502 * Unwanted calls ({@link android.telecom.Call#REJECT_REASON_UNWANTED}) will map 503 * to {@link ImsReasonInfo#CODE_SIP_USER_MARKED_UNWANTED}. 504 * {@link ImsCallSession.Listener#callSessionStartFailed} 505 */ reject(int reason)506 public void reject(int reason) { 507 } 508 509 /** 510 * Transfer an established call to given number 511 * 512 * @param number number to transfer the call 513 * @param isConfirmationRequired if {@code True}, indicates a confirmed transfer, 514 * if {@code False} it indicates an unconfirmed transfer. 515 * @hide 516 */ transfer(@onNull String number, boolean isConfirmationRequired)517 public void transfer(@NonNull String number, boolean isConfirmationRequired) { 518 } 519 520 /** 521 * Transfer an established call to another call session 522 * 523 * @param otherSession The other ImsCallSession to transfer the ongoing session to. 524 * @hide 525 */ transfer(@onNull ImsCallSessionImplBase otherSession)526 public void transfer(@NonNull ImsCallSessionImplBase otherSession) { 527 } 528 529 /** 530 * Terminates a call. 531 * 532 * @param reason reason code to terminate a call, defined in {@link ImsReasonInfo}. 533 * 534 * @see {@link ImsCallSession.Listener#callSessionTerminated} 535 */ terminate(int reason)536 public void terminate(int reason) { 537 } 538 539 /** 540 * Puts a call on hold. When it succeeds, {@link ImsCallSession.Listener#callSessionHeld} is 541 * called. 542 * 543 * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call 544 * @see {@link ImsCallSession.Listener#callSessionHeld}, 545 * {@link ImsCallSession.Listener#callSessionHoldFailed} 546 */ hold(ImsStreamMediaProfile profile)547 public void hold(ImsStreamMediaProfile profile) { 548 } 549 550 /** 551 * Continues a call that's on hold. When it succeeds, 552 * {@link ImsCallSession.Listener#callSessionResumed} is called. 553 * 554 * @param profile stream media profile with {@link ImsStreamMediaProfile} to resume the call 555 * @see {@link ImsCallSession.Listener#callSessionResumed}, 556 * {@link ImsCallSession.Listener#callSessionResumeFailed} 557 */ resume(ImsStreamMediaProfile profile)558 public void resume(ImsStreamMediaProfile profile) { 559 } 560 561 /** 562 * Merges the active and held call. When the merge starts, 563 * {@link ImsCallSession.Listener#callSessionMergeStarted} is called. 564 * {@link ImsCallSession.Listener#callSessionMergeComplete} is called if the merge is 565 * successful, and {@link ImsCallSession.Listener#callSessionMergeFailed} is called if the merge 566 * fails. 567 * 568 * @see {@link ImsCallSession.Listener#callSessionMergeStarted}, 569 * {@link ImsCallSession.Listener#callSessionMergeComplete}, 570 * {@link ImsCallSession.Listener#callSessionMergeFailed} 571 */ merge()572 public void merge() { 573 } 574 575 /** 576 * Updates the current call's properties (ex. call mode change: video upgrade / downgrade). 577 * 578 * @param callType call type specified in {@link ImsCallProfile} to be updated 579 * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated 580 * @see {@link ImsCallSession.Listener#callSessionUpdated}, 581 * {@link ImsCallSession.Listener#callSessionUpdateFailed} 582 */ update(int callType, ImsStreamMediaProfile profile)583 public void update(int callType, ImsStreamMediaProfile profile) { 584 } 585 586 /** 587 * Extends this call to the conference call with the specified recipients. 588 * 589 * @param participants participant list to be invited to the conference call after extending the 590 * call 591 * @see {@link ImsCallSession.Listener#callSessionConferenceExtended}, 592 * {@link ImsCallSession.Listener#callSessionConferenceExtendFailed} 593 */ extendToConference(String[] participants)594 public void extendToConference(String[] participants) { 595 } 596 597 /** 598 * Requests the conference server to invite an additional participants to the conference. 599 * 600 * @param participants participant list to be invited to the conference call 601 * @see {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestDelivered}, 602 * {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestFailed} 603 */ inviteParticipants(String[] participants)604 public void inviteParticipants(String[] participants) { 605 } 606 607 /** 608 * Requests the conference server to remove the specified participants from the conference. 609 * 610 * @param participants participant list to be removed from the conference call 611 * @see {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestDelivered}, 612 * {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestFailed} 613 */ removeParticipants(String[] participants)614 public void removeParticipants(String[] participants) { 615 } 616 617 /** 618 * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>, 619 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15, 620 * and event flash to 16. Currently, event flash is not supported. 621 * 622 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs. 623 * @param result If non-null, the {@link Message} to send when the operation is complete. This 624 * is done by using the associated {@link android.os.Messenger} in 625 * {@link Message#replyTo}. For example: 626 * {@code 627 * // Send DTMF and other operations... 628 * try { 629 * // Notify framework that the DTMF was sent. 630 * Messenger dtmfMessenger = result.replyTo; 631 * if (dtmfMessenger != null) { 632 * dtmfMessenger.send(result); 633 * } 634 * } catch (RemoteException e) { 635 * // Remote side is dead 636 * } 637 * } 638 */ sendDtmf(char c, Message result)639 public void sendDtmf(char c, Message result) { 640 } 641 642 /** 643 * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>, 644 * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15, 645 * and event flash to 16. Currently, event flash is not supported. 646 * 647 * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs. 648 */ startDtmf(char c)649 public void startDtmf(char c) { 650 } 651 652 /** 653 * Stop a DTMF code. 654 */ stopDtmf()655 public void stopDtmf() { 656 } 657 658 /** 659 * Sends an USSD message. 660 * 661 * @param ussdMessage USSD message to send 662 */ sendUssd(String ussdMessage)663 public void sendUssd(String ussdMessage) { 664 } 665 666 /** 667 * See {@link #getImsVideoCallProvider()}, used directly in older ImsService implementations. 668 * @hide 669 */ getVideoCallProvider()670 public IImsVideoCallProvider getVideoCallProvider() { 671 ImsVideoCallProvider provider = getImsVideoCallProvider(); 672 return provider != null ? provider.getInterface() : null; 673 } 674 675 /** 676 * @return The {@link ImsVideoCallProvider} implementation contained within the IMS service 677 * process. 678 */ getImsVideoCallProvider()679 public ImsVideoCallProvider getImsVideoCallProvider() { 680 return null; 681 } 682 683 /** 684 * Determines if the current session is multiparty. 685 * @return {@code True} if the session is multiparty. 686 */ isMultiparty()687 public boolean isMultiparty() { 688 return false; 689 } 690 691 /** 692 * Device issues RTT modify request 693 * @param toProfile The profile with requested changes made 694 */ sendRttModifyRequest(ImsCallProfile toProfile)695 public void sendRttModifyRequest(ImsCallProfile toProfile) { 696 } 697 698 /** 699 * Device responds to Remote RTT modify request 700 * @param status true if the the request was accepted or false of the request is defined. 701 */ sendRttModifyResponse(boolean status)702 public void sendRttModifyResponse(boolean status) { 703 } 704 705 /** 706 * Device sends RTT message 707 * @param rttMessage RTT message to be sent 708 */ sendRttMessage(String rttMessage)709 public void sendRttMessage(String rttMessage) { 710 } 711 712 /** 713 * Device requests that {@code rtpHeaderExtensions} are sent as a header extension with the next 714 * RTP packet sent by the IMS stack. 715 * <p> 716 * The {@link RtpHeaderExtensionType}s negotiated during SDP (Session Description Protocol) 717 * signalling determine the {@link RtpHeaderExtension}s which can be sent using this method. 718 * See RFC8285 for more information. 719 * <p> 720 * By specification, the RTP header extension is an unacknowledged transmission and there is no 721 * guarantee that the header extension will be delivered by the network to the other end of the 722 * call. 723 * @param rtpHeaderExtensions The RTP header extensions to be included in the next RTP header. 724 */ sendRtpHeaderExtensions(@onNull Set<RtpHeaderExtension> rtpHeaderExtensions)725 public void sendRtpHeaderExtensions(@NonNull Set<RtpHeaderExtension> rtpHeaderExtensions) { 726 } 727 728 /** @hide */ getServiceImpl()729 public IImsCallSession getServiceImpl() { 730 return mServiceImpl; 731 } 732 733 /** @hide */ setServiceImpl(IImsCallSession serviceImpl)734 public void setServiceImpl(IImsCallSession serviceImpl) { 735 mServiceImpl = serviceImpl; 736 } 737 738 /** 739 * Set default Executor from MmTelFeature. 740 * @param executor The default executor for the framework to use when executing the methods 741 * overridden by the implementation of ImsCallSession. 742 * @hide 743 */ setDefaultExecutor(@onNull Executor executor)744 public final void setDefaultExecutor(@NonNull Executor executor) { 745 mExecutor = executor; 746 } 747 } 748