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 /** 257 * @hide 258 */ 259 @SystemApi @TestApi 260 @IntDef(flag = true, 261 value = { 262 CAPABILITY_TYPE_VOICE, 263 CAPABILITY_TYPE_VIDEO, 264 CAPABILITY_TYPE_UT, 265 CAPABILITY_TYPE_SMS 266 }) 267 @Retention(RetentionPolicy.SOURCE) 268 public @interface MmTelCapability {} 269 270 /** 271 * This MmTelFeature supports Voice calling (IR.92) 272 */ 273 public static final int CAPABILITY_TYPE_VOICE = 1 << 0; 274 275 /** 276 * This MmTelFeature supports Video (IR.94) 277 */ 278 public static final int CAPABILITY_TYPE_VIDEO = 1 << 1; 279 280 /** 281 * This MmTelFeature supports XCAP over Ut for supplementary services. (IR.92) 282 */ 283 public static final int CAPABILITY_TYPE_UT = 1 << 2; 284 285 /** 286 * This MmTelFeature supports SMS (IR.92) 287 */ 288 public static final int CAPABILITY_TYPE_SMS = 1 << 3; 289 290 /** 291 * @hide 292 */ 293 @Override 294 @SystemApi @TestApi addCapabilities(@mTelCapability int capabilities)295 public final void addCapabilities(@MmTelCapability int capabilities) { 296 super.addCapabilities(capabilities); 297 } 298 299 /** 300 * @hide 301 */ 302 @Override 303 @SystemApi @TestApi removeCapabilities(@mTelCapability int capability)304 public final void removeCapabilities(@MmTelCapability int capability) { 305 super.removeCapabilities(capability); 306 } 307 308 /** 309 * @hide 310 */ 311 @Override 312 @SystemApi @TestApi isCapable(@mTelCapability int capabilities)313 public final boolean isCapable(@MmTelCapability int capabilities) { 314 return super.isCapable(capabilities); 315 } 316 317 /** 318 * @hide 319 */ 320 @NonNull 321 @Override toString()322 public String toString() { 323 StringBuilder builder = new StringBuilder("MmTel Capabilities - ["); 324 builder.append("Voice: "); 325 builder.append(isCapable(CAPABILITY_TYPE_VOICE)); 326 builder.append(" Video: "); 327 builder.append(isCapable(CAPABILITY_TYPE_VIDEO)); 328 builder.append(" UT: "); 329 builder.append(isCapable(CAPABILITY_TYPE_UT)); 330 builder.append(" SMS: "); 331 builder.append(isCapable(CAPABILITY_TYPE_SMS)); 332 builder.append("]"); 333 return builder.toString(); 334 } 335 } 336 337 /** 338 * Listener that the framework implements for communication from the MmTelFeature. 339 * @hide 340 */ 341 public static class Listener extends IImsMmTelListener.Stub { 342 343 /** 344 * Called when the IMS provider receives an incoming call. 345 * @param c The {@link ImsCallSession} associated with the new call. 346 * @hide 347 */ 348 @Override onIncomingCall(IImsCallSession c, Bundle extras)349 public void onIncomingCall(IImsCallSession c, Bundle extras) { 350 351 } 352 353 /** 354 * Called when the IMS provider implicitly rejects an incoming call during setup. 355 * @param callProfile An {@link ImsCallProfile} with the call details. 356 * @param reason The {@link ImsReasonInfo} reason for call rejection. 357 * @hide 358 */ 359 @Override onRejectedCall(ImsCallProfile callProfile, ImsReasonInfo reason)360 public void onRejectedCall(ImsCallProfile callProfile, ImsReasonInfo reason) { 361 362 } 363 364 /** 365 * Updates the Listener when the voice message count for IMS has changed. 366 * @param count an integer representing the new message count. 367 * @hide 368 */ 369 @Override 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 /** 391 * @hide 392 */ 393 @SystemApi @TestApi 394 @IntDef(flag = true, 395 value = { 396 PROCESS_CALL_IMS, 397 PROCESS_CALL_CSFB 398 }) 399 @Retention(RetentionPolicy.SOURCE) 400 public @interface ProcessCallResult {} 401 402 /** 403 * If the flag is present and true, it indicates that the incoming call is for USSD. 404 * <p> 405 * This is an optional boolean flag. 406 * @hide 407 */ 408 @SystemApi @TestApi 409 public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; 410 411 /** 412 * If this flag is present and true, this call is marked as an unknown dialing call instead 413 * of an incoming call. An example of such a call is a call that is originated by sending 414 * commands (like AT commands) directly to the modem without Android involvement or dialing 415 * calls appearing over IMS when the modem does a silent redial from circuit-switched to IMS in 416 * certain situations. 417 * <p> 418 * This is an optional boolean flag. 419 * @hide 420 */ 421 @SystemApi @TestApi 422 public static final String EXTRA_IS_UNKNOWN_CALL = 423 "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; 424 425 private IImsMmTelListener mListener; 426 427 /** 428 * @param listener A {@link Listener} used when the MmTelFeature receives an incoming call and 429 * notifies the framework. 430 */ setListener(IImsMmTelListener listener)431 private void setListener(IImsMmTelListener listener) { 432 synchronized (mLock) { 433 mListener = listener; 434 if (mListener != null) { 435 onFeatureReady(); 436 } 437 } 438 } 439 440 /** 441 * @return the listener associated with this MmTelFeature. May be null if it has not been set 442 * by the framework yet. 443 */ getListener()444 private IImsMmTelListener getListener() { 445 synchronized (mLock) { 446 return mListener; 447 } 448 } 449 450 /** 451 * The current capability status that this MmTelFeature has defined is available. This 452 * configuration will be used by the platform to figure out which capabilities are CURRENTLY 453 * available to be used. 454 * 455 * Should be a subset of the capabilities that are enabled by the framework in 456 * {@link #changeEnabledCapabilities}. 457 * @return A copy of the current MmTelFeature capability status. 458 * @hide 459 */ 460 @Override 461 @SystemApi @TestApi queryCapabilityStatus()462 public @NonNull final MmTelCapabilities queryCapabilityStatus() { 463 return new MmTelCapabilities(super.queryCapabilityStatus()); 464 } 465 466 /** 467 * Notify the framework that the status of the Capabilities has changed. Even though the 468 * MmTelFeature capability may be enabled by the framework, the status may be disabled due to 469 * the feature being unavailable from the network. 470 * @param c The current capability status of the MmTelFeature. If a capability is disabled, then 471 * the status of that capability is disabled. This can happen if the network does not currently 472 * support the capability that is enabled. A capability that is disabled by the framework (via 473 * {@link #changeEnabledCapabilities}) should also show the status as disabled. 474 * @hide 475 */ 476 @SystemApi @TestApi notifyCapabilitiesStatusChanged(@onNull MmTelCapabilities c)477 public final void notifyCapabilitiesStatusChanged(@NonNull MmTelCapabilities c) { 478 if (c == null) { 479 throw new IllegalArgumentException("MmTelCapabilities must be non-null!"); 480 } 481 super.notifyCapabilitiesStatusChanged(c); 482 } 483 484 /** 485 * Notify the framework of an incoming call. 486 * @param c The {@link ImsCallSessionImplBase} of the new incoming call. 487 * @param extras A bundle containing extra parameters related to the call. See 488 * {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above. 489 * @hide 490 */ 491 @SystemApi @TestApi notifyIncomingCall(@onNull ImsCallSessionImplBase c, @NonNull Bundle extras)492 public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c, 493 @NonNull Bundle extras) { 494 if (c == null || extras == null) { 495 throw new IllegalArgumentException("ImsCallSessionImplBase and Bundle can not be " 496 + "null."); 497 } 498 IImsMmTelListener listener = getListener(); 499 if (listener == null) { 500 throw new IllegalStateException("Session is not available."); 501 } 502 try { 503 listener.onIncomingCall(c.getServiceImpl(), extras); 504 } catch (RemoteException e) { 505 throw new RuntimeException(e); 506 } 507 } 508 509 /** 510 * Notify the framework that a call has been implicitly rejected by this MmTelFeature 511 * during call setup. 512 * @param callProfile The {@link ImsCallProfile} IMS call profile with details. 513 * This can be null if no call information is available for the rejected call. 514 * @param reason The {@link ImsReasonInfo} call rejection reason. 515 * @hide 516 */ 517 @SystemApi @TestApi notifyRejectedCall(@onNull ImsCallProfile callProfile, @NonNull ImsReasonInfo reason)518 public final void notifyRejectedCall(@NonNull ImsCallProfile callProfile, 519 @NonNull ImsReasonInfo reason) { 520 if (callProfile == null || reason == null) { 521 throw new IllegalArgumentException("ImsCallProfile and ImsReasonInfo must not be " 522 + "null."); 523 } 524 IImsMmTelListener listener = getListener(); 525 if (listener == null) { 526 throw new IllegalStateException("Session is not available."); 527 } 528 try { 529 listener.onRejectedCall(callProfile, reason); 530 } catch (RemoteException e) { 531 throw new RuntimeException(e); 532 } 533 } 534 535 /** 536 * 537 * @hide 538 */ notifyIncomingCallSession(IImsCallSession c, Bundle extras)539 public final void notifyIncomingCallSession(IImsCallSession c, Bundle extras) { 540 IImsMmTelListener listener = getListener(); 541 if (listener == null) { 542 throw new IllegalStateException("Session is not available."); 543 } 544 try { 545 listener.onIncomingCall(c, extras); 546 } catch (RemoteException e) { 547 throw new RuntimeException(e); 548 } 549 } 550 551 /** 552 * Notify the framework of a change in the Voice Message count. 553 * @link count the new Voice Message count. 554 * @hide 555 */ 556 @SystemApi @TestApi notifyVoiceMessageCountUpdate(int count)557 public final void notifyVoiceMessageCountUpdate(int count) { 558 IImsMmTelListener listener = getListener(); 559 if (listener == null) { 560 throw new IllegalStateException("Session is not available."); 561 } 562 try { 563 listener.onVoiceMessageCountUpdate(count); 564 } catch (RemoteException e) { 565 throw new RuntimeException(e); 566 } 567 } 568 569 /** 570 * Provides the MmTelFeature with the ability to return the framework Capability Configuration 571 * for a provided Capability. If the framework calls {@link #changeEnabledCapabilities} and 572 * includes a capability A to enable or disable, this method should return the correct enabled 573 * status for capability A. 574 * @param capability The capability that we are querying the configuration for. 575 * @return true if the capability is enabled, false otherwise. 576 * @hide 577 */ 578 @Override 579 @SystemApi @TestApi queryCapabilityConfiguration(@mTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech)580 public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability, 581 @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { 582 // Base implementation - Override to provide functionality 583 return false; 584 } 585 586 /** 587 * The MmTelFeature should override this method to handle the enabling/disabling of 588 * MmTel Features, defined in {@link MmTelCapabilities.MmTelCapability}. The framework assumes 589 * the {@link CapabilityChangeRequest} was processed successfully. If a subset of capabilities 590 * could not be set to their new values, 591 * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} must be called 592 * individually for each capability whose processing resulted in an error. 593 * 594 * Enabling/Disabling a capability here indicates that the capability should be registered or 595 * deregistered (depending on the capability change) and become available or unavailable to 596 * the framework. 597 * * @hide 598 */ 599 @Override 600 @SystemApi @TestApi changeEnabledCapabilities(@onNull CapabilityChangeRequest request, @NonNull CapabilityCallbackProxy c)601 public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request, 602 @NonNull CapabilityCallbackProxy c) { 603 // Base implementation, no-op 604 } 605 606 /** 607 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state. 608 * 609 * @param callSessionType a service type that is specified in {@link ImsCallProfile} 610 * {@link ImsCallProfile#SERVICE_TYPE_NONE} 611 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL} 612 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY} 613 * @param callType a call type that is specified in {@link ImsCallProfile} 614 * {@link ImsCallProfile#CALL_TYPE_VOICE} 615 * {@link ImsCallProfile#CALL_TYPE_VT} 616 * {@link ImsCallProfile#CALL_TYPE_VT_TX} 617 * {@link ImsCallProfile#CALL_TYPE_VT_RX} 618 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR} 619 * {@link ImsCallProfile#CALL_TYPE_VS} 620 * {@link ImsCallProfile#CALL_TYPE_VS_TX} 621 * {@link ImsCallProfile#CALL_TYPE_VS_RX} 622 * @return a {@link ImsCallProfile} object 623 * @hide 624 */ 625 @SystemApi @TestApi createCallProfile(int callSessionType, int callType)626 public @Nullable ImsCallProfile createCallProfile(int callSessionType, int callType) { 627 // Base Implementation - Should be overridden 628 return null; 629 } 630 631 /** 632 * @hide 633 */ createCallSessionInterface(ImsCallProfile profile)634 public IImsCallSession createCallSessionInterface(ImsCallProfile profile) 635 throws RemoteException { 636 ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile); 637 return s != null ? s.getServiceImpl() : null; 638 } 639 640 /** 641 * Creates an {@link ImsCallSession} with the specified call profile. 642 * Use other methods, if applicable, instead of interacting with 643 * {@link ImsCallSession} directly. 644 * 645 * @param profile a call profile to make the call 646 * @hide 647 */ 648 @SystemApi @TestApi createCallSession(@onNull ImsCallProfile profile)649 public @Nullable ImsCallSessionImplBase createCallSession(@NonNull ImsCallProfile profile) { 650 // Base Implementation - Should be overridden 651 return null; 652 } 653 654 /** 655 * Called by the framework to determine if the outgoing call, designated by the outgoing 656 * {@link String}s, should be processed as an IMS call or CSFB call. If this method's 657 * functionality is not overridden, the platform will process every call as IMS as long as the 658 * MmTelFeature reports that the {@link MmTelCapabilities#CAPABILITY_TYPE_VOICE} capability is 659 * available. 660 * @param numbers An array of {@link String}s that will be used for placing the call. There can 661 * be multiple {@link String}s listed in the case when we want to place an outgoing 662 * call as a conference. 663 * @return a {@link ProcessCallResult} to the framework, which will be used to determine if the 664 * call will be placed over IMS or via CSFB. 665 * @hide 666 */ 667 @SystemApi @TestApi shouldProcessCall(@onNull String[] numbers)668 public @ProcessCallResult int shouldProcessCall(@NonNull String[] numbers) { 669 return PROCESS_CALL_IMS; 670 } 671 672 /** 673 * 674 * @hide 675 */ getUtInterface()676 protected IImsUt getUtInterface() throws RemoteException { 677 ImsUtImplBase utImpl = getUt(); 678 return utImpl != null ? utImpl.getInterface() : null; 679 } 680 681 /** 682 * @hide 683 */ getEcbmInterface()684 protected IImsEcbm getEcbmInterface() throws RemoteException { 685 ImsEcbmImplBase ecbmImpl = getEcbm(); 686 return ecbmImpl != null ? ecbmImpl.getImsEcbm() : null; 687 } 688 689 /** 690 * @hide 691 */ getMultiEndpointInterface()692 public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { 693 ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint(); 694 return multiendpointImpl != null ? multiendpointImpl.getIImsMultiEndpoint() : null; 695 } 696 697 /** 698 * @return The {@link ImsUtImplBase} Ut interface implementation for the supplementary service 699 * configuration. 700 * @hide 701 */ 702 @SystemApi @TestApi getUt()703 public @NonNull ImsUtImplBase getUt() { 704 // Base Implementation - Should be overridden 705 return new ImsUtImplBase(); 706 } 707 708 /** 709 * @return The {@link ImsEcbmImplBase} Emergency call-back mode interface for emergency VoLTE 710 * calls that support it. 711 * @hide 712 */ 713 @SystemApi @TestApi getEcbm()714 public @NonNull ImsEcbmImplBase getEcbm() { 715 // Base Implementation - Should be overridden 716 return new ImsEcbmImplBase(); 717 } 718 719 /** 720 * @return The {@link ImsMultiEndpointImplBase} implementation for implementing Dialog event 721 * package processing for multi-endpoint. 722 * @hide 723 */ 724 @SystemApi @TestApi getMultiEndpoint()725 public @NonNull ImsMultiEndpointImplBase getMultiEndpoint() { 726 // Base Implementation - Should be overridden 727 return new ImsMultiEndpointImplBase(); 728 } 729 730 /** 731 * Sets the current UI TTY mode for the MmTelFeature. 732 * @param mode An integer containing the new UI TTY Mode, can consist of 733 * {@link TelecomManager#TTY_MODE_OFF}, 734 * {@link TelecomManager#TTY_MODE_FULL}, 735 * {@link TelecomManager#TTY_MODE_HCO}, 736 * {@link TelecomManager#TTY_MODE_VCO} 737 * @param onCompleteMessage If non-null, this MmTelFeature should call this {@link Message} when 738 * the operation is complete by using the associated {@link android.os.Messenger} in 739 * {@link Message#replyTo}. For example: 740 * {@code 741 * // Set UI TTY Mode and other operations... 742 * try { 743 * // Notify framework that the mode was changed. 744 * Messenger uiMessenger = onCompleteMessage.replyTo; 745 * uiMessenger.send(onCompleteMessage); 746 * } catch (RemoteException e) { 747 * // Remote side is dead 748 * } 749 * } 750 * @hide 751 */ 752 @SystemApi @TestApi setUiTtyMode(int mode, @Nullable Message onCompleteMessage)753 public void setUiTtyMode(int mode, @Nullable Message onCompleteMessage) { 754 // Base Implementation - Should be overridden 755 } 756 setSmsListener(IImsSmsListener listener)757 private void setSmsListener(IImsSmsListener listener) { 758 getSmsImplementation().registerSmsListener(listener); 759 } 760 sendSms(int token, int messageRef, String format, String smsc, boolean isRetry, byte[] pdu)761 private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry, 762 byte[] pdu) { 763 getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu); 764 } 765 acknowledgeSms(int token, int messageRef, @ImsSmsImplBase.DeliverStatusResult int result)766 private void acknowledgeSms(int token, int messageRef, 767 @ImsSmsImplBase.DeliverStatusResult int result) { 768 getSmsImplementation().acknowledgeSms(token, messageRef, result); 769 } 770 acknowledgeSmsReport(int token, int messageRef, @ImsSmsImplBase.StatusReportResult int result)771 private void acknowledgeSmsReport(int token, int messageRef, 772 @ImsSmsImplBase.StatusReportResult int result) { 773 getSmsImplementation().acknowledgeSmsReport(token, messageRef, result); 774 } 775 onSmsReady()776 private void onSmsReady() { 777 getSmsImplementation().onReady(); 778 } 779 780 /** 781 * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default 782 * non-functional implementation is returned. 783 * 784 * @return an instance of {@link ImsSmsImplBase} which should be implemented by the IMS 785 * Provider. 786 * @hide 787 */ 788 @SystemApi @TestApi getSmsImplementation()789 public @NonNull ImsSmsImplBase getSmsImplementation() { 790 return new ImsSmsImplBase(); 791 } 792 getSmsFormat()793 private String getSmsFormat() { 794 return getSmsImplementation().getSmsFormat(); 795 } 796 797 /** 798 * {@inheritDoc} 799 * @hide 800 */ 801 @Override 802 @SystemApi @TestApi onFeatureRemoved()803 public void onFeatureRemoved() { 804 // Base Implementation - Should be overridden 805 } 806 807 /** 808 * {@inheritDoc} 809 * @hide 810 */ 811 @Override 812 @SystemApi @TestApi onFeatureReady()813 public void onFeatureReady() { 814 // Base Implementation - Should be overridden 815 } 816 817 /** 818 * @hide 819 */ 820 @Override getBinder()821 public final IImsMmTelFeature getBinder() { 822 return mImsMMTelBinder; 823 } 824 } 825