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