1 /* 2 * Copyright (C) 2018 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.feature; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.annotation.TestApi; 24 import android.os.Bundle; 25 import android.os.Message; 26 import android.os.RemoteException; 27 import android.telecom.TelecomManager; 28 import android.telephony.ims.ImsCallProfile; 29 import android.telephony.ims.ImsCallSession; 30 import android.telephony.ims.ImsReasonInfo; 31 import android.telephony.ims.aidl.IImsCapabilityCallback; 32 import android.telephony.ims.aidl.IImsMmTelFeature; 33 import android.telephony.ims.aidl.IImsMmTelListener; 34 import android.telephony.ims.aidl.IImsSmsListener; 35 import android.telephony.ims.stub.ImsCallSessionImplBase; 36 import android.telephony.ims.stub.ImsEcbmImplBase; 37 import android.telephony.ims.stub.ImsMultiEndpointImplBase; 38 import android.telephony.ims.stub.ImsRegistrationImplBase; 39 import android.telephony.ims.stub.ImsSmsImplBase; 40 import android.telephony.ims.stub.ImsUtImplBase; 41 42 import com.android.ims.internal.IImsCallSession; 43 import com.android.ims.internal.IImsEcbm; 44 import com.android.ims.internal.IImsMultiEndpoint; 45 import com.android.ims.internal.IImsUt; 46 47 import java.lang.annotation.Retention; 48 import java.lang.annotation.RetentionPolicy; 49 50 /** 51 * Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support. 52 * 53 * Any class wishing to use MmTelFeature should extend this class and implement all methods that the 54 * service supports. 55 */ 56 public class MmTelFeature extends ImsFeature { 57 58 private static final String LOG_TAG = "MmTelFeature"; 59 60 /** 61 * @hide 62 */ 63 @SystemApi @TestApi MmTelFeature()64 public MmTelFeature() { 65 } 66 67 private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() { 68 69 @Override 70 public void setListener(IImsMmTelListener l) { 71 MmTelFeature.this.setListener(l); 72 } 73 74 @Override 75 public int getFeatureState() throws RemoteException { 76 try { 77 return MmTelFeature.this.getFeatureState(); 78 } catch (Exception e) { 79 throw new RemoteException(e.getMessage()); 80 } 81 } 82 83 84 @Override 85 public ImsCallProfile createCallProfile(int callSessionType, int callType) 86 throws RemoteException { 87 synchronized (mLock) { 88 try { 89 return MmTelFeature.this.createCallProfile(callSessionType, callType); 90 } catch (Exception e) { 91 throw new RemoteException(e.getMessage()); 92 } 93 } 94 } 95 96 @Override 97 public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException { 98 synchronized (mLock) { 99 return createCallSessionInterface(profile); 100 } 101 } 102 103 @Override 104 public int shouldProcessCall(String[] numbers) { 105 synchronized (mLock) { 106 return MmTelFeature.this.shouldProcessCall(numbers); 107 } 108 } 109 110 @Override 111 public IImsUt getUtInterface() throws RemoteException { 112 synchronized (mLock) { 113 return MmTelFeature.this.getUtInterface(); 114 } 115 } 116 117 @Override 118 public IImsEcbm getEcbmInterface() throws RemoteException { 119 synchronized (mLock) { 120 return MmTelFeature.this.getEcbmInterface(); 121 } 122 } 123 124 @Override 125 public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException { 126 synchronized (mLock) { 127 try { 128 MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage); 129 } catch (Exception e) { 130 throw new RemoteException(e.getMessage()); 131 } 132 } 133 } 134 135 @Override 136 public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { 137 synchronized (mLock) { 138 return MmTelFeature.this.getMultiEndpointInterface(); 139 } 140 } 141 142 @Override 143 public int queryCapabilityStatus() { 144 return MmTelFeature.this.queryCapabilityStatus().mCapabilities; 145 } 146 147 @Override 148 public void addCapabilityCallback(IImsCapabilityCallback c) { 149 // no need to lock, structure already handles multithreading. 150 MmTelFeature.this.addCapabilityCallback(c); 151 } 152 153 @Override 154 public void removeCapabilityCallback(IImsCapabilityCallback c) { 155 // no need to lock, structure already handles multithreading. 156 MmTelFeature.this.removeCapabilityCallback(c); 157 } 158 159 @Override 160 public void changeCapabilitiesConfiguration(CapabilityChangeRequest request, 161 IImsCapabilityCallback c) { 162 MmTelFeature.this.requestChangeEnabledCapabilities(request, c); 163 } 164 165 @Override 166 public void queryCapabilityConfiguration(int capability, int radioTech, 167 IImsCapabilityCallback c) { 168 queryCapabilityConfigurationInternal(capability, radioTech, c); 169 } 170 171 @Override 172 public void setSmsListener(IImsSmsListener l) { 173 MmTelFeature.this.setSmsListener(l); 174 } 175 176 @Override 177 public void sendSms(int token, int messageRef, String format, String smsc, boolean retry, 178 byte[] pdu) { 179 synchronized (mLock) { 180 MmTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu); 181 } 182 } 183 184 @Override 185 public void acknowledgeSms(int token, int messageRef, int result) { 186 synchronized (mLock) { 187 MmTelFeature.this.acknowledgeSms(token, messageRef, result); 188 } 189 } 190 191 @Override 192 public void acknowledgeSmsReport(int token, int messageRef, int result) { 193 synchronized (mLock) { 194 MmTelFeature.this.acknowledgeSmsReport(token, messageRef, result); 195 } 196 } 197 198 @Override 199 public String getSmsFormat() { 200 synchronized (mLock) { 201 return MmTelFeature.this.getSmsFormat(); 202 } 203 } 204 205 @Override 206 public void onSmsReady() { 207 synchronized (mLock) { 208 MmTelFeature.this.onSmsReady(); 209 } 210 } 211 }; 212 213 /** 214 * Contains the capabilities defined and supported by a MmTelFeature in the form of a Bitmask. 215 * The capabilities that are used in MmTelFeature are defined as 216 * {@link MmTelCapabilities#CAPABILITY_TYPE_VOICE}, 217 * {@link MmTelCapabilities#CAPABILITY_TYPE_VIDEO}, 218 * {@link MmTelCapabilities#CAPABILITY_TYPE_UT}, and 219 * {@link MmTelCapabilities#CAPABILITY_TYPE_SMS}. 220 * 221 * The capabilities of this MmTelFeature will be set by the framework. 222 */ 223 public static class MmTelCapabilities extends Capabilities { 224 225 /** 226 * Create a new empty {@link MmTelCapabilities} instance. 227 * @see #addCapabilities(int) 228 * @see #removeCapabilities(int) 229 * @hide 230 */ 231 @SystemApi @TestApi MmTelCapabilities()232 public MmTelCapabilities() { 233 super(); 234 } 235 236 /**@deprecated Use {@link MmTelCapabilities} to construct a new instance instead. 237 * @hide 238 */ 239 @Deprecated 240 @SystemApi @TestApi MmTelCapabilities(Capabilities c)241 public MmTelCapabilities(Capabilities c) { 242 mCapabilities = c.mCapabilities; 243 } 244 245 /** 246 * Create a new {link @MmTelCapabilities} instance with the provided capabilities. 247 * @param capabilities The capabilities that are supported for MmTel in the form of a 248 * bitfield. 249 * @hide 250 */ 251 @SystemApi @TestApi MmTelCapabilities(@mTelCapability int capabilities)252 public MmTelCapabilities(@MmTelCapability int capabilities) { 253 super(capabilities); 254 } 255 256 /** @hide */ 257 @IntDef(flag = true, 258 value = { 259 CAPABILITY_TYPE_VOICE, 260 CAPABILITY_TYPE_VIDEO, 261 CAPABILITY_TYPE_UT, 262 CAPABILITY_TYPE_SMS 263 }) 264 @Retention(RetentionPolicy.SOURCE) 265 public @interface MmTelCapability {} 266 267 /** 268 * This MmTelFeature supports Voice calling (IR.92) 269 */ 270 public static final int CAPABILITY_TYPE_VOICE = 1 << 0; 271 272 /** 273 * This MmTelFeature supports Video (IR.94) 274 */ 275 public static final int CAPABILITY_TYPE_VIDEO = 1 << 1; 276 277 /** 278 * This MmTelFeature supports XCAP over Ut for supplementary services. (IR.92) 279 */ 280 public static final int CAPABILITY_TYPE_UT = 1 << 2; 281 282 /** 283 * This MmTelFeature supports SMS (IR.92) 284 */ 285 public static final int CAPABILITY_TYPE_SMS = 1 << 3; 286 287 /** 288 * @hide 289 */ 290 @Override 291 @SystemApi @TestApi addCapabilities(@mTelCapability int capabilities)292 public final void addCapabilities(@MmTelCapability int capabilities) { 293 super.addCapabilities(capabilities); 294 } 295 296 /** 297 * @hide 298 */ 299 @Override 300 @SystemApi @TestApi removeCapabilities(@mTelCapability int capability)301 public final void removeCapabilities(@MmTelCapability int capability) { 302 super.removeCapabilities(capability); 303 } 304 305 /** 306 * @hide 307 */ 308 @Override 309 @SystemApi @TestApi isCapable(@mTelCapability int capabilities)310 public final boolean isCapable(@MmTelCapability int capabilities) { 311 return super.isCapable(capabilities); 312 } 313 314 /** 315 * @hide 316 */ 317 @NonNull 318 @Override toString()319 public String toString() { 320 StringBuilder builder = new StringBuilder("MmTel Capabilities - ["); 321 builder.append("Voice: "); 322 builder.append(isCapable(CAPABILITY_TYPE_VOICE)); 323 builder.append(" Video: "); 324 builder.append(isCapable(CAPABILITY_TYPE_VIDEO)); 325 builder.append(" UT: "); 326 builder.append(isCapable(CAPABILITY_TYPE_UT)); 327 builder.append(" SMS: "); 328 builder.append(isCapable(CAPABILITY_TYPE_SMS)); 329 builder.append("]"); 330 return builder.toString(); 331 } 332 } 333 334 /** 335 * Listener that the framework implements for communication from the MmTelFeature. 336 * @hide 337 */ 338 public static class Listener extends IImsMmTelListener.Stub { 339 340 /** 341 * Called when the IMS provider receives an incoming call. 342 * @param c The {@link ImsCallSession} associated with the new call. 343 * @hide 344 */ 345 @Override 346 @SystemApi @TestApi onIncomingCall(IImsCallSession c, Bundle extras)347 public void onIncomingCall(IImsCallSession c, Bundle extras) { 348 349 } 350 351 /** 352 * Called when the IMS provider implicitly rejects an incoming call during setup. 353 * @param callProfile An {@link ImsCallProfile} with the call details. 354 * @param reason The {@link ImsReasonInfo} reason for call rejection. 355 * @hide 356 */ 357 @Override 358 @SystemApi @TestApi onRejectedCall(ImsCallProfile callProfile, ImsReasonInfo reason)359 public void onRejectedCall(ImsCallProfile callProfile, ImsReasonInfo reason) { 360 361 } 362 363 /** 364 * Updates the Listener when the voice message count for IMS has changed. 365 * @param count an integer representing the new message count. 366 * @hide 367 */ 368 @Override 369 @SystemApi @TestApi onVoiceMessageCountUpdate(int count)370 public void onVoiceMessageCountUpdate(int count) { 371 372 } 373 } 374 375 /** 376 * To be returned by {@link #shouldProcessCall(String[])} when the ImsService should process the 377 * outgoing call as IMS. 378 * @hide 379 */ 380 @SystemApi @TestApi 381 public static final int PROCESS_CALL_IMS = 0; 382 /** 383 * To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should 384 * not process the outgoing call as IMS and should instead use circuit switch. 385 * @hide 386 */ 387 @SystemApi @TestApi 388 public static final int PROCESS_CALL_CSFB = 1; 389 390 /** @hide */ 391 @IntDef(flag = true, 392 value = { 393 PROCESS_CALL_IMS, 394 PROCESS_CALL_CSFB 395 }) 396 @Retention(RetentionPolicy.SOURCE) 397 public @interface ProcessCallResult {} 398 399 /** 400 * If the flag is present and true, it indicates that the incoming call is for USSD. 401 * <p> 402 * This is an optional boolean flag. 403 * @hide 404 */ 405 @SystemApi @TestApi 406 public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; 407 408 /** 409 * If this flag is present and true, this call is marked as an unknown dialing call instead 410 * of an incoming call. An example of such a call is a call that is originated by sending 411 * commands (like AT commands) directly to the modem without Android involvement or dialing 412 * calls appearing over IMS when the modem does a silent redial from circuit-switched to IMS in 413 * certain situations. 414 * <p> 415 * This is an optional boolean flag. 416 * @hide 417 */ 418 @SystemApi @TestApi 419 public static final String EXTRA_IS_UNKNOWN_CALL = 420 "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; 421 422 private IImsMmTelListener mListener; 423 424 /** 425 * @param listener A {@link Listener} used when the MmTelFeature receives an incoming call and 426 * notifies the framework. 427 */ setListener(IImsMmTelListener listener)428 private void setListener(IImsMmTelListener listener) { 429 synchronized (mLock) { 430 mListener = listener; 431 if (mListener != null) { 432 onFeatureReady(); 433 } 434 } 435 } 436 437 /** 438 * @return the listener associated with this MmTelFeature. May be null if it has not been set 439 * by the framework yet. 440 */ getListener()441 private IImsMmTelListener getListener() { 442 synchronized (mLock) { 443 return mListener; 444 } 445 } 446 447 /** 448 * The current capability status that this MmTelFeature has defined is available. This 449 * configuration will be used by the platform to figure out which capabilities are CURRENTLY 450 * available to be used. 451 * 452 * Should be a subset of the capabilities that are enabled by the framework in 453 * {@link #changeEnabledCapabilities}. 454 * @return A copy of the current MmTelFeature capability status. 455 * @hide 456 */ 457 @Override 458 @SystemApi @TestApi queryCapabilityStatus()459 public @NonNull final MmTelCapabilities queryCapabilityStatus() { 460 return new MmTelCapabilities(super.queryCapabilityStatus()); 461 } 462 463 /** 464 * Notify the framework that the status of the Capabilities has changed. Even though the 465 * MmTelFeature capability may be enabled by the framework, the status may be disabled due to 466 * the feature being unavailable from the network. 467 * @param c The current capability status of the MmTelFeature. If a capability is disabled, then 468 * the status of that capability is disabled. This can happen if the network does not currently 469 * support the capability that is enabled. A capability that is disabled by the framework (via 470 * {@link #changeEnabledCapabilities}) should also show the status as disabled. 471 * @hide 472 */ 473 @SystemApi @TestApi notifyCapabilitiesStatusChanged(@onNull MmTelCapabilities c)474 public final void notifyCapabilitiesStatusChanged(@NonNull MmTelCapabilities c) { 475 if (c == null) { 476 throw new IllegalArgumentException("MmTelCapabilities must be non-null!"); 477 } 478 super.notifyCapabilitiesStatusChanged(c); 479 } 480 481 /** 482 * Notify the framework of an incoming call. 483 * @param c The {@link ImsCallSessionImplBase} of the new incoming call. 484 * @param extras A bundle containing extra parameters related to the call. See 485 * {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above. 486 * @hide 487 */ 488 @SystemApi @TestApi notifyIncomingCall(@onNull ImsCallSessionImplBase c, @NonNull Bundle extras)489 public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c, 490 @NonNull Bundle extras) { 491 if (c == null || extras == null) { 492 throw new IllegalArgumentException("ImsCallSessionImplBase and Bundle can not be " 493 + "null."); 494 } 495 IImsMmTelListener listener = getListener(); 496 if (listener == null) { 497 throw new IllegalStateException("Session is not available."); 498 } 499 try { 500 listener.onIncomingCall(c.getServiceImpl(), extras); 501 } catch (RemoteException e) { 502 throw new RuntimeException(e); 503 } 504 } 505 506 /** 507 * Notify the framework that a call has been implicitly rejected by this MmTelFeature 508 * during call setup. 509 * @param callProfile The {@link ImsCallProfile} IMS call profile with details. 510 * This can be null if no call information is available for the rejected call. 511 * @param reason The {@link ImsReasonInfo} call rejection reason. 512 * @hide 513 */ 514 @SystemApi @TestApi notifyRejectedCall(@onNull ImsCallProfile callProfile, @NonNull ImsReasonInfo reason)515 public final void notifyRejectedCall(@NonNull ImsCallProfile callProfile, 516 @NonNull ImsReasonInfo reason) { 517 if (callProfile == null || reason == null) { 518 throw new IllegalArgumentException("ImsCallProfile and ImsReasonInfo must not be " 519 + "null."); 520 } 521 IImsMmTelListener listener = getListener(); 522 if (listener == null) { 523 throw new IllegalStateException("Session is not available."); 524 } 525 try { 526 listener.onRejectedCall(callProfile, reason); 527 } catch (RemoteException e) { 528 throw new RuntimeException(e); 529 } 530 } 531 532 /** 533 * 534 * @hide 535 */ notifyIncomingCallSession(IImsCallSession c, Bundle extras)536 public final void notifyIncomingCallSession(IImsCallSession c, Bundle extras) { 537 IImsMmTelListener listener = getListener(); 538 if (listener == null) { 539 throw new IllegalStateException("Session is not available."); 540 } 541 try { 542 listener.onIncomingCall(c, extras); 543 } catch (RemoteException e) { 544 throw new RuntimeException(e); 545 } 546 } 547 548 /** 549 * Notify the framework of a change in the Voice Message count. 550 * @link count the new Voice Message count. 551 * @hide 552 */ 553 @SystemApi @TestApi notifyVoiceMessageCountUpdate(int count)554 public final void notifyVoiceMessageCountUpdate(int count) { 555 IImsMmTelListener listener = getListener(); 556 if (listener == null) { 557 throw new IllegalStateException("Session is not available."); 558 } 559 try { 560 listener.onVoiceMessageCountUpdate(count); 561 } catch (RemoteException e) { 562 throw new RuntimeException(e); 563 } 564 } 565 566 /** 567 * Provides the MmTelFeature with the ability to return the framework Capability Configuration 568 * for a provided Capability. If the framework calls {@link #changeEnabledCapabilities} and 569 * includes a capability A to enable or disable, this method should return the correct enabled 570 * status for capability A. 571 * @param capability The capability that we are querying the configuration for. 572 * @return true if the capability is enabled, false otherwise. 573 * @hide 574 */ 575 @Override 576 @SystemApi @TestApi queryCapabilityConfiguration(@mTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech)577 public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability, 578 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { 579 // Base implementation - Override to provide functionality 580 return false; 581 } 582 583 /** 584 * The MmTelFeature should override this method to handle the enabling/disabling of 585 * MmTel Features, defined in {@link MmTelCapabilities.MmTelCapability}. The framework assumes 586 * the {@link CapabilityChangeRequest} was processed successfully. If a subset of capabilities 587 * could not be set to their new values, 588 * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} must be called 589 * individually for each capability whose processing resulted in an error. 590 * 591 * Enabling/Disabling a capability here indicates that the capability should be registered or 592 * deregistered (depending on the capability change) and become available or unavailable to 593 * the framework. 594 * * @hide 595 */ 596 @Override 597 @SystemApi @TestApi changeEnabledCapabilities(@onNull CapabilityChangeRequest request, @NonNull CapabilityCallbackProxy c)598 public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request, 599 @NonNull CapabilityCallbackProxy c) { 600 // Base implementation, no-op 601 } 602 603 /** 604 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state. 605 * 606 * @param callSessionType a service type that is specified in {@link ImsCallProfile} 607 * {@link ImsCallProfile#SERVICE_TYPE_NONE} 608 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL} 609 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY} 610 * @param callType a call type that is specified in {@link ImsCallProfile} 611 * {@link ImsCallProfile#CALL_TYPE_VOICE} 612 * {@link ImsCallProfile#CALL_TYPE_VT} 613 * {@link ImsCallProfile#CALL_TYPE_VT_TX} 614 * {@link ImsCallProfile#CALL_TYPE_VT_RX} 615 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR} 616 * {@link ImsCallProfile#CALL_TYPE_VS} 617 * {@link ImsCallProfile#CALL_TYPE_VS_TX} 618 * {@link ImsCallProfile#CALL_TYPE_VS_RX} 619 * @return a {@link ImsCallProfile} object 620 * @hide 621 */ 622 @SystemApi @TestApi createCallProfile(int callSessionType, int callType)623 public @Nullable ImsCallProfile createCallProfile(int callSessionType, int callType) { 624 // Base Implementation - Should be overridden 625 return null; 626 } 627 628 /** 629 * @hide 630 */ createCallSessionInterface(ImsCallProfile profile)631 public IImsCallSession createCallSessionInterface(ImsCallProfile profile) 632 throws RemoteException { 633 ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile); 634 return s != null ? s.getServiceImpl() : null; 635 } 636 637 /** 638 * Creates an {@link ImsCallSession} with the specified call profile. 639 * Use other methods, if applicable, instead of interacting with 640 * {@link ImsCallSession} directly. 641 * 642 * @param profile a call profile to make the call 643 * @hide 644 */ 645 @SystemApi @TestApi createCallSession(@onNull ImsCallProfile profile)646 public @Nullable ImsCallSessionImplBase createCallSession(@NonNull ImsCallProfile profile) { 647 // Base Implementation - Should be overridden 648 return null; 649 } 650 651 /** 652 * Called by the framework to determine if the outgoing call, designated by the outgoing 653 * {@link String}s, should be processed as an IMS call or CSFB call. If this method's 654 * functionality is not overridden, the platform will process every call as IMS as long as the 655 * MmTelFeature reports that the {@link MmTelCapabilities#CAPABILITY_TYPE_VOICE} capability is 656 * available. 657 * @param numbers An array of {@link String}s that will be used for placing the call. There can 658 * be multiple {@link String}s listed in the case when we want to place an outgoing 659 * call as a conference. 660 * @return a {@link ProcessCallResult} to the framework, which will be used to determine if the 661 * call will be placed over IMS or via CSFB. 662 * @hide 663 */ 664 @SystemApi @TestApi shouldProcessCall(@onNull String[] numbers)665 public @ProcessCallResult int shouldProcessCall(@NonNull String[] numbers) { 666 return PROCESS_CALL_IMS; 667 } 668 669 /** 670 * 671 * @hide 672 */ getUtInterface()673 protected IImsUt getUtInterface() throws RemoteException { 674 ImsUtImplBase utImpl = getUt(); 675 return utImpl != null ? utImpl.getInterface() : null; 676 } 677 678 /** 679 * @hide 680 */ getEcbmInterface()681 protected IImsEcbm getEcbmInterface() throws RemoteException { 682 ImsEcbmImplBase ecbmImpl = getEcbm(); 683 return ecbmImpl != null ? ecbmImpl.getImsEcbm() : null; 684 } 685 686 /** 687 * @hide 688 */ getMultiEndpointInterface()689 public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { 690 ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint(); 691 return multiendpointImpl != null ? multiendpointImpl.getIImsMultiEndpoint() : null; 692 } 693 694 /** 695 * @return The {@link ImsUtImplBase} Ut interface implementation for the supplementary service 696 * configuration. 697 * @hide 698 */ 699 @SystemApi @TestApi getUt()700 public @NonNull ImsUtImplBase getUt() { 701 // Base Implementation - Should be overridden 702 return new ImsUtImplBase(); 703 } 704 705 /** 706 * @return The {@link ImsEcbmImplBase} Emergency call-back mode interface for emergency VoLTE 707 * calls that support it. 708 * @hide 709 */ 710 @SystemApi @TestApi getEcbm()711 public @NonNull ImsEcbmImplBase getEcbm() { 712 // Base Implementation - Should be overridden 713 return new ImsEcbmImplBase(); 714 } 715 716 /** 717 * @return The {@link ImsMultiEndpointImplBase} implementation for implementing Dialog event 718 * package processing for multi-endpoint. 719 * @hide 720 */ 721 @SystemApi @TestApi getMultiEndpoint()722 public @NonNull ImsMultiEndpointImplBase getMultiEndpoint() { 723 // Base Implementation - Should be overridden 724 return new ImsMultiEndpointImplBase(); 725 } 726 727 /** 728 * Sets the current UI TTY mode for the MmTelFeature. 729 * @param mode An integer containing the new UI TTY Mode, can consist of 730 * {@link TelecomManager#TTY_MODE_OFF}, 731 * {@link TelecomManager#TTY_MODE_FULL}, 732 * {@link TelecomManager#TTY_MODE_HCO}, 733 * {@link TelecomManager#TTY_MODE_VCO} 734 * @param onCompleteMessage If non-null, this MmTelFeature should call this {@link Message} when 735 * the operation is complete by using the associated {@link android.os.Messenger} in 736 * {@link Message#replyTo}. For example: 737 * {@code 738 * // Set UI TTY Mode and other operations... 739 * try { 740 * // Notify framework that the mode was changed. 741 * Messenger uiMessenger = onCompleteMessage.replyTo; 742 * uiMessenger.send(onCompleteMessage); 743 * } catch (RemoteException e) { 744 * // Remote side is dead 745 * } 746 * } 747 * @hide 748 */ 749 @SystemApi @TestApi setUiTtyMode(int mode, @Nullable Message onCompleteMessage)750 public void setUiTtyMode(int mode, @Nullable Message onCompleteMessage) { 751 // Base Implementation - Should be overridden 752 } 753 setSmsListener(IImsSmsListener listener)754 private void setSmsListener(IImsSmsListener listener) { 755 getSmsImplementation().registerSmsListener(listener); 756 } 757 sendSms(int token, int messageRef, String format, String smsc, boolean isRetry, byte[] pdu)758 private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry, 759 byte[] pdu) { 760 getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu); 761 } 762 acknowledgeSms(int token, int messageRef, @ImsSmsImplBase.DeliverStatusResult int result)763 private void acknowledgeSms(int token, int messageRef, 764 @ImsSmsImplBase.DeliverStatusResult int result) { 765 getSmsImplementation().acknowledgeSms(token, messageRef, result); 766 } 767 acknowledgeSmsReport(int token, int messageRef, @ImsSmsImplBase.StatusReportResult int result)768 private void acknowledgeSmsReport(int token, int messageRef, 769 @ImsSmsImplBase.StatusReportResult int result) { 770 getSmsImplementation().acknowledgeSmsReport(token, messageRef, result); 771 } 772 onSmsReady()773 private void onSmsReady() { 774 getSmsImplementation().onReady(); 775 } 776 777 /** 778 * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default 779 * non-functional implementation is returned. 780 * 781 * @return an instance of {@link ImsSmsImplBase} which should be implemented by the IMS 782 * Provider. 783 * @hide 784 */ 785 @SystemApi @TestApi getSmsImplementation()786 public @NonNull ImsSmsImplBase getSmsImplementation() { 787 return new ImsSmsImplBase(); 788 } 789 getSmsFormat()790 private String getSmsFormat() { 791 return getSmsImplementation().getSmsFormat(); 792 } 793 794 /** 795 * {@inheritDoc} 796 * @hide 797 */ 798 @Override 799 @SystemApi @TestApi onFeatureRemoved()800 public void onFeatureRemoved() { 801 // Base Implementation - Should be overridden 802 } 803 804 /** 805 * {@inheritDoc} 806 * @hide 807 */ 808 @Override 809 @SystemApi @TestApi onFeatureReady()810 public void onFeatureReady() { 811 // Base Implementation - Should be overridden 812 } 813 814 /** 815 * @hide 816 */ 817 @Override getBinder()818 public final IImsMmTelFeature getBinder() { 819 return mImsMMTelBinder; 820 } 821 } 822