• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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