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;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.os.RemoteException;
23 import android.telephony.Annotation;
24 import android.telephony.CallQuality;
25 import android.telephony.ServiceState;
26 import android.telephony.ims.aidl.IImsCallSessionListener;
27 import android.telephony.ims.stub.ImsCallSessionImplBase;
28 
29 import com.android.ims.internal.IImsCallSession;
30 
31 import java.util.ArrayList;
32 import java.util.Objects;
33 import java.util.Set;
34 
35 /**
36  * Listener interface for notifying the Framework's {@link ImsCallSession} for updates to an ongoing
37  * IMS call.
38  *
39  * @hide
40  */
41 // DO NOT remove or change the existing APIs, only add new ones to this implementation or you
42 // will break other implementations of ImsCallSessionListener maintained by other ImsServices.
43 // TODO: APIs in here do not conform to API guidelines yet. This can be changed if
44 // ImsCallSessionListenerConverter is also changed.
45 @SystemApi
46 public class ImsCallSessionListener {
47 
48     private final IImsCallSessionListener mListener;
49 
50     /** @hide */
ImsCallSessionListener(IImsCallSessionListener l)51     public ImsCallSessionListener(IImsCallSessionListener l) {
52         mListener = l;
53     }
54 
55     /**
56      * Called when the network first begins to establish the call session and is now connecting
57      * to the remote party. This must be called once after {@link ImsCallSessionImplBase#start} and
58      * before any other method on this listener.  After this is called,
59      * {@link #callSessionProgressing(ImsStreamMediaProfile)} must be called to communicate any
60      * further updates.
61      * <p/>
62      * Once this is called, {@link #callSessionTerminated} must be called
63      * to end the call session.  In the event that the session failed before the remote party
64      * was contacted, {@link #callSessionInitiatingFailed} must be called.
65      *
66      * @param profile the associated {@link ImsCallProfile}.
67      */
callSessionInitiating(@onNull ImsCallProfile profile)68     public void callSessionInitiating(@NonNull ImsCallProfile profile) {
69         try {
70             mListener.callSessionInitiating(profile);
71         } catch (RemoteException e) {
72             e.rethrowFromSystemServer();
73         }
74     }
75 
76     /**
77      * The IMS call session establishment has failed while initiating.
78      *
79      * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the IMS call session
80      * establishment failure.
81      */
callSessionInitiatingFailed(@onNull ImsReasonInfo reasonInfo)82     public void callSessionInitiatingFailed(@NonNull ImsReasonInfo reasonInfo) {
83         try {
84             mListener.callSessionInitiatingFailed(reasonInfo);
85         } catch (RemoteException e) {
86             e.rethrowFromSystemServer();
87         }
88     }
89 
90     /**
91      * Called after the network has contacted the remote party and the call state should move to
92      * ALERTING.
93      *
94      * @param profile the associated {@link ImsCallProfile}.
95      */
callSessionProgressing(ImsStreamMediaProfile profile)96     public void callSessionProgressing(ImsStreamMediaProfile profile) {
97         try {
98             mListener.callSessionProgressing(profile);
99         } catch (RemoteException e) {
100             e.rethrowFromSystemServer();
101         }
102     }
103 
104     /**
105      * Called once the outgoing IMS call session has been begun between the local and remote party.
106      * The call state should move to ACTIVE.
107      *
108      * @param profile the associated {@link ImsCallProfile}.
109      */
callSessionInitiated(ImsCallProfile profile)110     public void callSessionInitiated(ImsCallProfile profile) {
111         try {
112             mListener.callSessionInitiated(profile);
113         } catch (RemoteException e) {
114             e.rethrowFromSystemServer();
115         }
116     }
117 
118     /**
119      * The IMS call session establishment has failed.
120      *
121      * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the IMS call session
122      * establishment failure.
123      * @deprecated {@link #callSessionInitiated(ImsCallProfile)} is called immediately after
124      * the session is first started which meant that there was no time in which a call to this
125      * method was technically valid.  This method is replaced starting Android S in favor of
126      * {@link #callSessionInitiatingFailed(ImsReasonInfo)}.
127      */
128     @Deprecated
callSessionInitiatedFailed(ImsReasonInfo reasonInfo)129     public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) {
130         try {
131             mListener.callSessionInitiatedFailed(reasonInfo);
132         } catch (RemoteException e) {
133             e.rethrowFromSystemServer();
134         }
135     }
136 
137     /**
138      * The IMS call session has been terminated.
139      *
140      * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the session termination.
141      */
callSessionTerminated(ImsReasonInfo reasonInfo)142     public void callSessionTerminated(ImsReasonInfo reasonInfo) {
143         try {
144             mListener.callSessionTerminated(reasonInfo);
145         } catch (RemoteException e) {
146             e.rethrowFromSystemServer();
147         }
148     }
149 
150     /**
151      * The IMS call session has started the process of holding the call. If it fails,
152      * {@link #callSessionHoldFailed(ImsReasonInfo)} should be called.
153      *
154      * If the IMS call session is resumed, call {@link #callSessionResumed(ImsCallProfile)}.
155      *
156      * @param profile The associated {@link ImsCallProfile} of the call session that has been put
157      * on hold.
158      */
callSessionHeld(ImsCallProfile profile)159     public void callSessionHeld(ImsCallProfile profile) {
160         try {
161             mListener.callSessionHeld(profile);
162         } catch (RemoteException e) {
163             e.rethrowFromSystemServer();
164         }
165     }
166 
167     /**
168      * The IMS call session has failed to be held.
169      *
170      * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the session hold failure.
171      */
callSessionHoldFailed(ImsReasonInfo reasonInfo)172     public void callSessionHoldFailed(ImsReasonInfo reasonInfo) {
173         try {
174             mListener.callSessionHoldFailed(reasonInfo);
175         } catch (RemoteException e) {
176             e.rethrowFromSystemServer();
177         }
178     }
179 
180     /**
181      * This IMS Call session has been put on hold by the remote party.
182      *
183      * @param profile The {@link ImsCallProfile} associated with this IMS call session.
184      */
callSessionHoldReceived(ImsCallProfile profile)185     public void callSessionHoldReceived(ImsCallProfile profile) {
186         try {
187             mListener.callSessionHoldReceived(profile);
188         } catch (RemoteException e) {
189             e.rethrowFromSystemServer();
190         }
191     }
192 
193     /**
194      * The IMS call session has started the process of resuming the call. If the process of resuming
195      * the call fails, call {@link #callSessionResumeFailed(ImsReasonInfo)}.
196      *
197      * @param profile The {@link ImsCallProfile} associated with this IMS call session.
198      */
callSessionResumed(ImsCallProfile profile)199     public void callSessionResumed(ImsCallProfile profile) {
200         try {
201             mListener.callSessionResumed(profile);
202         } catch (RemoteException e) {
203             e.rethrowFromSystemServer();
204         }
205     }
206 
207     /**
208      * The IMS call session resume has failed.
209      *
210      * @param reasonInfo {@link ImsReasonInfo} containing the detailed reason of the session resume
211      * failure.
212      */
callSessionResumeFailed(ImsReasonInfo reasonInfo)213     public void callSessionResumeFailed(ImsReasonInfo reasonInfo) {
214         try {
215             mListener.callSessionResumeFailed(reasonInfo);
216         } catch (RemoteException e) {
217             e.rethrowFromSystemServer();
218         }
219     }
220 
221     /**
222      * The remote party has resumed this IMS call session.
223      *
224      * @param profile {@link ImsCallProfile} associated with the IMS call session.
225      */
callSessionResumeReceived(ImsCallProfile profile)226     public void callSessionResumeReceived(ImsCallProfile profile) {
227         try {
228             mListener.callSessionResumeReceived(profile);
229         } catch (RemoteException e) {
230             e.rethrowFromSystemServer();
231         }
232     }
233 
234     /**
235      * The IMS call session merge has been started.  At this point, the {@code newSession}
236      * represents the IMS call session which represents the new merged conference and has been
237      * initiated to the IMS conference server.
238      *
239      * @param newSession the {@link ImsCallSessionImplBase} that represents the merged active & held
240      * sessions.
241      * @param profile The {@link ImsCallProfile} associated with this IMS call session.
242      */
callSessionMergeStarted(ImsCallSessionImplBase newSession, ImsCallProfile profile)243     public void callSessionMergeStarted(ImsCallSessionImplBase newSession, ImsCallProfile profile)
244     {
245         try {
246             mListener.callSessionMergeStarted(newSession != null ?
247                             newSession.getServiceImpl() : null, profile);
248         } catch (RemoteException e) {
249             e.rethrowFromSystemServer();
250         }
251     }
252 
253     /**
254      * Compatibility method for older implementations.
255      * See {@link #callSessionMergeStarted(ImsCallSessionImplBase, ImsCallProfile)}.
256      *
257      * @hide
258      */
callSessionMergeStarted(IImsCallSession newSession, ImsCallProfile profile)259     public void callSessionMergeStarted(IImsCallSession newSession, ImsCallProfile profile)
260     {
261         try {
262             mListener.callSessionMergeStarted(newSession, profile);
263         } catch (RemoteException e) {
264             e.rethrowFromSystemServer();
265         }
266     }
267 
268     /**
269      * The session merge is successful and the merged {@link ImsCallSession} is active.
270      *
271      * @param newSession the new {@link ImsCallSessionImplBase}
272      *                  that represents the conference IMS call
273      * session.
274      */
callSessionMergeComplete(ImsCallSessionImplBase newSession)275     public void callSessionMergeComplete(ImsCallSessionImplBase newSession) {
276         try {
277             mListener.callSessionMergeComplete(newSession != null ?
278                     newSession.getServiceImpl() : null);
279         } catch (RemoteException e) {
280             e.rethrowFromSystemServer();
281         }
282     }
283 
284     /**
285      * Compatibility method for older implementations of ImsService.
286      *
287      * See {@link #callSessionMergeComplete(ImsCallSessionImplBase)}}.
288      *
289      * @hide
290      */
callSessionMergeComplete(IImsCallSession newSession)291     public void callSessionMergeComplete(IImsCallSession newSession) {
292         try {
293             mListener.callSessionMergeComplete(newSession);
294         } catch (RemoteException e) {
295             e.rethrowFromSystemServer();
296         }
297     }
298 
299     /**
300      * The IMS call session merge has failed.
301      *
302      * @param reasonInfo {@link ImsReasonInfo} contining the reason for the call merge failure.
303      */
callSessionMergeFailed(ImsReasonInfo reasonInfo)304     public void callSessionMergeFailed(ImsReasonInfo reasonInfo) {
305         try {
306             mListener.callSessionMergeFailed(reasonInfo);
307         } catch (RemoteException e) {
308             e.rethrowFromSystemServer();
309         }
310     }
311 
312     /**
313      * The IMS call session profile has been updated. Does not include holding or resuming a call.
314      *
315      * @param profile The {@link ImsCallProfile} associated with the updated IMS call session.
316      */
callSessionUpdated(ImsCallProfile profile)317     public void callSessionUpdated(ImsCallProfile profile) {
318         try {
319             mListener.callSessionUpdated(profile);
320         } catch (RemoteException e) {
321             e.rethrowFromSystemServer();
322         }
323     }
324 
325     /**
326      * The IMS call session profile update has failed.
327      *
328      * @param reasonInfo {@link ImsReasonInfo} containing a reason for the session update failure.
329      */
callSessionUpdateFailed(ImsReasonInfo reasonInfo)330     public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) {
331         try {
332             mListener.callSessionUpdateFailed(reasonInfo);
333         } catch (RemoteException e) {
334             e.rethrowFromSystemServer();
335         }
336     }
337 
338     /**
339      * The IMS call session profile has received an update from the remote user.
340      *
341      * @param profile The new {@link ImsCallProfile} associated with the update.
342      */
callSessionUpdateReceived(ImsCallProfile profile)343     public void callSessionUpdateReceived(ImsCallProfile profile) {
344         try {
345             mListener.callSessionUpdateReceived(profile);
346         } catch (RemoteException e) {
347             e.rethrowFromSystemServer();
348         }
349     }
350 
351     /**
352      * Called when the session has been extended to a conference session.
353      *
354      * If the conference extension fails, call
355      * {@link #callSessionConferenceExtendFailed(ImsReasonInfo)}.
356      *
357      * @param newSession the session object that is extended to the conference from the active
358      * IMS Call session.
359      * @param profile The {@link ImsCallProfile} associated with the IMS call session.
360      */
callSessionConferenceExtended(ImsCallSessionImplBase newSession, ImsCallProfile profile)361     public void callSessionConferenceExtended(ImsCallSessionImplBase newSession,
362             ImsCallProfile profile) {
363         try {
364             mListener.callSessionConferenceExtended(
365                     newSession != null ? newSession.getServiceImpl() : null, profile);
366         } catch (RemoteException e) {
367             e.rethrowFromSystemServer();
368         }
369     }
370 
371     /**
372      * Compatibility method to interface with older versions of ImsService.
373      * See {@link #callSessionConferenceExtended(ImsCallSessionImplBase, ImsCallProfile)}.
374      *
375      * @hide
376      */
callSessionConferenceExtended(IImsCallSession newSession, ImsCallProfile profile)377     public void callSessionConferenceExtended(IImsCallSession newSession, ImsCallProfile profile) {
378         try {
379             mListener.callSessionConferenceExtended(newSession, profile);
380         } catch (RemoteException e) {
381             e.rethrowFromSystemServer();
382         }
383     }
384 
385     /**
386      * The previous conference extension has failed.
387      *
388      * @param reasonInfo {@link ImsReasonInfo} containing the detailed reason of the conference
389      * extension failure.
390      */
callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo)391     public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) {
392         try {
393             mListener.callSessionConferenceExtendFailed(reasonInfo);
394         } catch (RemoteException e) {
395             e.rethrowFromSystemServer();
396         }
397     }
398 
399     /**
400      * A conference extension has been received received from the remote party.
401      *
402      * @param newSession An {@link ImsCallSessionImplBase}
403      *                   representing the extended IMS call session.
404      * @param profile The {@link ImsCallProfile} associated with the new IMS call session.
405      */
callSessionConferenceExtendReceived(ImsCallSessionImplBase newSession, ImsCallProfile profile)406     public void callSessionConferenceExtendReceived(ImsCallSessionImplBase newSession,
407             ImsCallProfile profile) {
408         try {
409             mListener.callSessionConferenceExtendReceived(newSession != null
410                     ? newSession.getServiceImpl() : null, profile);
411         } catch (RemoteException e) {
412             e.rethrowFromSystemServer();
413         }
414     }
415 
416     /**
417      * Compatibility method to interface with older versions of ImsService.
418      * See {@link #callSessionConferenceExtendReceived(ImsCallSessionImplBase, ImsCallProfile)}.
419      *
420      * @hide
421      */
callSessionConferenceExtendReceived(IImsCallSession newSession, ImsCallProfile profile)422     public void callSessionConferenceExtendReceived(IImsCallSession newSession,
423             ImsCallProfile profile) {
424         try {
425             mListener.callSessionConferenceExtendReceived(newSession, profile);
426         } catch (RemoteException e) {
427             e.rethrowFromSystemServer();
428         }
429     }
430 
431     /**
432      * The request to invite participants to the conference has been delivered to the conference
433      * server.
434      */
callSessionInviteParticipantsRequestDelivered()435     public void callSessionInviteParticipantsRequestDelivered() {
436         try {
437             mListener.callSessionInviteParticipantsRequestDelivered();
438         } catch (RemoteException e) {
439             e.rethrowFromSystemServer();
440         }
441     }
442 
443     /**
444      * The previous request to invite participants to the conference (see
445      * {@link #callSessionInviteParticipantsRequestDelivered()}) has failed.
446      *
447      * @param reasonInfo {@link ImsReasonInfo} detailing the reason forthe conference invitation
448      * failure.
449      */
callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo)450     public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo)
451     {
452         try {
453             mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
454         } catch (RemoteException e) {
455             e.rethrowFromSystemServer();
456         }
457     }
458 
459     /**
460      * The request to remove participants from the conference has been delivered to the conference
461      * server.
462      */
callSessionRemoveParticipantsRequestDelivered()463     public void callSessionRemoveParticipantsRequestDelivered() {
464         try {
465             mListener.callSessionRemoveParticipantsRequestDelivered();
466         } catch (RemoteException e) {
467             e.rethrowFromSystemServer();
468         }
469     }
470 
471     /**
472      * The previous request to remove participants from the conference (see
473      * {@link #callSessionRemoveParticipantsRequestDelivered()}) has failed.
474      *
475      * @param reasonInfo {@link ImsReasonInfo} detailing the reason for the conference removal
476      * failure.
477      */
callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo)478     public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo)
479     {
480         try {
481             mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
482         } catch (RemoteException e) {
483             e.rethrowFromSystemServer();
484         }
485     }
486 
487     /**
488      * The IMS call session's conference state has changed.
489      *
490      * @param state The new {@link ImsConferenceState} associated with the conference.
491      */
callSessionConferenceStateUpdated(ImsConferenceState state)492     public void callSessionConferenceStateUpdated(ImsConferenceState state) {
493         try {
494             mListener.callSessionConferenceStateUpdated(state);
495         } catch (RemoteException e) {
496             e.rethrowFromSystemServer();
497         }
498     }
499 
500     /**
501      * The IMS call session has received a Ussd message.
502      *
503      * @param mode The mode of the USSD message, either
504      * {@link ImsCallSessionImplBase#USSD_MODE_NOTIFY} or
505      * {@link ImsCallSessionImplBase#USSD_MODE_REQUEST}.
506      * @param ussdMessage The USSD message.
507      */
callSessionUssdMessageReceived(int mode, String ussdMessage)508     public void callSessionUssdMessageReceived(int mode, String ussdMessage)
509     {
510         try {
511             mListener.callSessionUssdMessageReceived(mode, ussdMessage);
512         } catch (RemoteException e) {
513             e.rethrowFromSystemServer();
514         }
515     }
516 
517     /**
518      * An {@link ImsCallSession} may potentially handover from one radio
519      * technology to another.
520      *
521      * @param srcAccessTech The source radio access technology; one of the access technology
522      * constants defined in {@link android.telephony.ServiceState}. For example
523      * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
524      * @param targetAccessTech The target radio access technology; one of the access technology
525      * constants defined in {@link android.telephony.ServiceState}. For example
526      * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
527      * @deprecated Uses hidden constants for radio access technology, use
528      * {@link #onMayHandover(int, int)} instead.
529      */
530     @Deprecated
callSessionMayHandover(int srcAccessTech, int targetAccessTech)531     public void callSessionMayHandover(int srcAccessTech, int targetAccessTech) {
532         // Use new API internally.
533         onMayHandover(ServiceState.rilRadioTechnologyToNetworkType(srcAccessTech),
534                 ServiceState.rilRadioTechnologyToNetworkType(targetAccessTech));
535     }
536 
537     /**
538      * Notify the framework that the associated {@link ImsCallSession} may handover from one network
539      * type to another.
540      *
541      * @param srcNetworkType The source network type.
542      * @param targetNetworkType The target network type.
543      */
onMayHandover(@nnotation.NetworkType int srcNetworkType, @Annotation.NetworkType int targetNetworkType)544     public void onMayHandover(@Annotation.NetworkType int srcNetworkType,
545             @Annotation.NetworkType int targetNetworkType) {
546         try {
547             mListener.callSessionMayHandover(srcNetworkType, targetNetworkType);
548         } catch (RemoteException e) {
549             e.rethrowFromSystemServer();
550         }
551     }
552 
553     /**
554      * The IMS call session's access technology has changed.
555      *
556      * @param srcAccessTech original access technology, defined in
557      * {@link android.telephony.ServiceState}.
558      * @param targetAccessTech new access technology, defined in
559      * {@link android.telephony.ServiceState}.
560      * @param reasonInfo The {@link ImsReasonInfo} associated with this handover.
561      * @deprecated Uses hidden radio access technology constants, use
562      * {@link #onHandover(int, int, ImsReasonInfo)} instead.
563      */
564     @Deprecated
callSessionHandover(int srcAccessTech, int targetAccessTech, ImsReasonInfo reasonInfo)565     public void callSessionHandover(int srcAccessTech, int targetAccessTech,
566             ImsReasonInfo reasonInfo) {
567         // Use new API internally.
568         onHandover(ServiceState.rilRadioTechnologyToNetworkType(srcAccessTech),
569                 ServiceState.rilRadioTechnologyToNetworkType(targetAccessTech), reasonInfo);
570     }
571 
572     /**
573      * Notify the framework that the associated {@link ImsCallSession} has handed over from one
574      * network type to another.
575      *
576      * @param srcNetworkType original network type.
577      * @param targetNetworkType target network type after handover..
578      * @param reasonInfo An optional {@link ImsReasonInfo} associated with this handover.
579      */
onHandover(@nnotation.NetworkType int srcNetworkType, @Annotation.NetworkType int targetNetworkType, @Nullable ImsReasonInfo reasonInfo)580     public void onHandover(@Annotation.NetworkType int srcNetworkType,
581             @Annotation.NetworkType int targetNetworkType, @Nullable ImsReasonInfo reasonInfo) {
582         try {
583             mListener.callSessionHandover(srcNetworkType, targetNetworkType, reasonInfo);
584         } catch (RemoteException e) {
585             e.rethrowFromSystemServer();
586         }
587     }
588 
589     /**
590      * The IMS call session's access technology change has failed..
591      *
592      * @param srcAccessTech original access technology
593      * @param targetAccessTech new access technology
594      * @param reasonInfo An {@link ImsReasonInfo} detailing the reason for the failure.
595      * @deprecated Uses hidden radio access technology constants, use
596      * {@link #onHandoverFailed(int, int, ImsReasonInfo)} instead
597      */
598     @Deprecated
callSessionHandoverFailed(int srcAccessTech, int targetAccessTech, ImsReasonInfo reasonInfo)599     public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
600             ImsReasonInfo reasonInfo) {
601         // Use new API internally.
602         onHandoverFailed(ServiceState.rilRadioTechnologyToNetworkType(srcAccessTech),
603                 ServiceState.rilRadioTechnologyToNetworkType(targetAccessTech), reasonInfo);
604     }
605 
606     /**
607      * The IMS call session's access technology change has failed..
608      *
609      * @param srcNetworkType original network type.
610      * @param targetNetworkType target network type that the handover failed for.
611      * @param reasonInfo An {@link ImsReasonInfo} detailing the reason for the failure.
612      */
onHandoverFailed(@nnotation.NetworkType int srcNetworkType, @Annotation.NetworkType int targetNetworkType, @NonNull ImsReasonInfo reasonInfo)613     public void onHandoverFailed(@Annotation.NetworkType int srcNetworkType,
614             @Annotation.NetworkType int targetNetworkType, @NonNull ImsReasonInfo reasonInfo) {
615         try {
616             mListener.callSessionHandoverFailed(srcNetworkType, targetNetworkType, reasonInfo);
617         } catch (RemoteException e) {
618             e.rethrowFromSystemServer();
619         }
620     }
621 
622     /**
623      * The TTY mode has been changed by the remote party.
624      *
625      * @param mode one of the following: -
626      *             {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} -
627      *             {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} -
628      *             {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} -
629      *             {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
630      */
callSessionTtyModeReceived(int mode)631     public void callSessionTtyModeReceived(int mode) {
632         try {
633             mListener.callSessionTtyModeReceived(mode);
634         } catch (RemoteException e) {
635             e.rethrowFromSystemServer();
636         }
637     }
638 
639     /**
640      * The multiparty state has been changed for this {@code ImsCallSession}.
641      *
642      * @param isMultiParty {@code true} if the session became multiparty, {@code false} otherwise.
643      */
callSessionMultipartyStateChanged(boolean isMultiParty)644     public void callSessionMultipartyStateChanged(boolean isMultiParty) {
645         try {
646             mListener.callSessionMultipartyStateChanged(isMultiParty);
647         } catch (RemoteException e) {
648             e.rethrowFromSystemServer();
649         }
650     }
651 
652     /**
653      * Supplementary service information has been received for the current IMS call session.
654      *
655      * @param suppSrvNotification The {@link ImsSuppServiceNotification} containing the change.
656      */
callSessionSuppServiceReceived(ImsSuppServiceNotification suppSrvNotification)657     public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppSrvNotification)
658     {
659         try {
660             mListener.callSessionSuppServiceReceived(suppSrvNotification);
661         } catch (RemoteException e) {
662             e.rethrowFromSystemServer();
663         }
664     }
665 
666     /**
667      * An RTT modify request has been received from the remote party.
668      *
669      * @param callProfile An {@link ImsCallProfile} with the updated attributes
670      */
callSessionRttModifyRequestReceived(ImsCallProfile callProfile)671     public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile)
672     {
673         try {
674             mListener.callSessionRttModifyRequestReceived(callProfile);
675         } catch (RemoteException e) {
676             e.rethrowFromSystemServer();
677         }
678     }
679 
680     /**
681      * An RTT modify response has been received.
682      *
683      * @param status the received response for RTT modify request.
684      */
callSessionRttModifyResponseReceived(int status)685     public void callSessionRttModifyResponseReceived(int status) {
686         try {
687             mListener.callSessionRttModifyResponseReceived(status);
688         } catch (RemoteException e) {
689             e.rethrowFromSystemServer();
690         }
691     }
692 
693     /**
694      * An RTT message has been received from the remote party.
695      *
696      * @param rttMessage The RTT message that has been received.
697      */
callSessionRttMessageReceived(String rttMessage)698     public void callSessionRttMessageReceived(String rttMessage) {
699         try {
700             mListener.callSessionRttMessageReceived(rttMessage);
701         } catch (RemoteException e) {
702             e.rethrowFromSystemServer();
703         }
704     }
705 
706     /**
707      * While in call, there has been a change in RTT audio indicator.
708      *
709      * @param profile updated ImsStreamMediaProfile
710      */
callSessionRttAudioIndicatorChanged(@onNull ImsStreamMediaProfile profile)711     public void callSessionRttAudioIndicatorChanged(@NonNull ImsStreamMediaProfile profile) {
712         try {
713             mListener.callSessionRttAudioIndicatorChanged(profile);
714         } catch (RemoteException e) {
715             e.rethrowFromSystemServer();
716         }
717     }
718 
719     /**
720      * The call quality has changed.
721      *
722      * @param callQuality The new call quality
723      */
callQualityChanged(@onNull CallQuality callQuality)724     public void callQualityChanged(@NonNull CallQuality callQuality) {
725         try {
726             mListener.callQualityChanged(callQuality);
727         } catch (RemoteException e) {
728             e.rethrowFromSystemServer();
729         }
730     }
731 
732     /**
733      * The {@link ImsService} calls this method to inform the framework of a DTMF digit which was
734      * received from the network.
735      * <p>
736      * According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833 sec 3.10</a>,
737      * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15.
738      * <p>
739      * <em>Note:</em> Alpha DTMF digits are converted from lower-case to upper-case.
740      *
741      * @param dtmf The DTMF digit received, '0'-'9', *, #, A, B, C, or D.
742      * @throws IllegalArgumentException If an invalid DTMF character is provided.
743      */
callSessionDtmfReceived(char dtmf)744     public void callSessionDtmfReceived(char dtmf) {
745         if (!(dtmf >= '0' && dtmf <= '9'
746                 || dtmf >= 'A' && dtmf <= 'D'
747                 || dtmf >= 'a' && dtmf <= 'd'
748                 || dtmf == '*'
749                 || dtmf == '#')) {
750             throw new IllegalArgumentException("DTMF digit must be 0-9, *, #, A, B, C, D");
751         }
752         try {
753             mListener.callSessionDtmfReceived(Character.toUpperCase(dtmf));
754         } catch (RemoteException e) {
755             e.rethrowFromSystemServer();
756         }
757     }
758 
759     /**
760      * The {@link ImsService} calls this method to inform the framework of RTP header extension data
761      * which was received from the network.
762      * <p>
763      * The set of {@link RtpHeaderExtension} data are identified by local identifiers which were
764      * negotiated during SDP signalling.  See RFC8285,
765      * {@link ImsCallProfile#getAcceptedRtpHeaderExtensionTypes()} and
766      * {@link RtpHeaderExtensionType} for more information.
767      * <p>
768      * By specification, the RTP header extension is an unacknowledged transmission and there is no
769      * guarantee that the header extension will be delivered by the network to the other end of the
770      * call.
771      *
772      * @param extensions The RTP header extension data received.
773      */
callSessionRtpHeaderExtensionsReceived( @onNull Set<RtpHeaderExtension> extensions)774     public void callSessionRtpHeaderExtensionsReceived(
775             @NonNull Set<RtpHeaderExtension> extensions) {
776         Objects.requireNonNull(extensions, "extensions are required.");
777         try {
778             mListener.callSessionRtpHeaderExtensionsReceived(
779                     new ArrayList<RtpHeaderExtension>(extensions));
780         } catch (RemoteException e) {
781             e.rethrowFromSystemServer();
782         }
783     }
784 
785     /**
786      * Notifies the result of transfer request.
787      * @hide
788      */
callSessionTransferred()789     public void callSessionTransferred() {
790         try {
791             mListener.callSessionTransferred();
792         } catch (RemoteException e) {
793             e.rethrowFromSystemServer();
794         }
795     }
796 
797     /**
798      * Notifies the result of transfer request.
799      *
800      * @param reasonInfo {@link ImsReasonInfo} containing a reason for the
801      * session transfer failure
802      * @hide
803      */
callSessionTransferFailed(ImsReasonInfo reasonInfo)804     public void callSessionTransferFailed(ImsReasonInfo reasonInfo) {
805         try {
806             mListener.callSessionTransferFailed(reasonInfo);
807         } catch (RemoteException e) {
808             e.rethrowFromSystemServer();
809         }
810     }
811 }
812 
813