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