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