1 /*
2  * Copyright (C) 2017 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.stub;
18 
19 import android.annotation.NonNull;
20 import android.annotation.SystemApi;
21 import android.annotation.TestApi;
22 import android.os.Message;
23 import android.os.RemoteException;
24 import android.telephony.ims.ImsCallProfile;
25 import android.telephony.ims.ImsCallSession;
26 import android.telephony.ims.ImsCallSessionListener;
27 import android.telephony.ims.ImsReasonInfo;
28 import android.telephony.ims.ImsStreamMediaProfile;
29 import android.telephony.ims.ImsVideoCallProvider;
30 import android.telephony.ims.aidl.IImsCallSessionListener;
31 
32 import com.android.ims.internal.IImsCallSession;
33 import com.android.ims.internal.IImsVideoCallProvider;
34 /**
35  * Base implementation of IImsCallSession, which implements stub versions of the methods available.
36  *
37  * Override the methods that your implementation of ImsCallSession supports.
38  *
39  * @hide
40  */
41 @SystemApi
42 @TestApi
43 // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
44 // will break other implementations of ImsCallSession maintained by other ImsServices.
45 public class ImsCallSessionImplBase implements AutoCloseable {
46     /**
47      * Notify USSD Mode.
48      */
49     public static final int USSD_MODE_NOTIFY = 0;
50     /**
51      * Request USSD Mode
52      */
53     public static final int USSD_MODE_REQUEST = 1;
54 
55     /**
56      * Defines IMS call session state.
57      */
58     public static class State {
59         public static final int IDLE = 0;
60         public static final int INITIATED = 1;
61         public static final int NEGOTIATING = 2;
62         public static final int ESTABLISHING = 3;
63         public static final int ESTABLISHED = 4;
64 
65         public static final int RENEGOTIATING = 5;
66         public static final int REESTABLISHING = 6;
67 
68         public static final int TERMINATING = 7;
69         public static final int TERMINATED = 8;
70 
71         public static final int INVALID = (-1);
72 
73         /**
74          * Converts the state to string.
75          */
toString(int state)76         public static String toString(int state) {
77             switch (state) {
78                 case IDLE:
79                     return "IDLE";
80                 case INITIATED:
81                     return "INITIATED";
82                 case NEGOTIATING:
83                     return "NEGOTIATING";
84                 case ESTABLISHING:
85                     return "ESTABLISHING";
86                 case ESTABLISHED:
87                     return "ESTABLISHED";
88                 case RENEGOTIATING:
89                     return "RENEGOTIATING";
90                 case REESTABLISHING:
91                     return "REESTABLISHING";
92                 case TERMINATING:
93                     return "TERMINATING";
94                 case TERMINATED:
95                     return "TERMINATED";
96                 default:
97                     return "UNKNOWN";
98             }
99         }
100 
101         /**
102          * @hide
103          */
State()104         private State() {
105         }
106     }
107 
108     // Non-final for injection by tests
109     private IImsCallSession mServiceImpl = new IImsCallSession.Stub() {
110         @Override
111         public void close() {
112             ImsCallSessionImplBase.this.close();
113         }
114 
115         @Override
116         public String getCallId() {
117             return ImsCallSessionImplBase.this.getCallId();
118         }
119 
120         @Override
121         public ImsCallProfile getCallProfile() {
122             return ImsCallSessionImplBase.this.getCallProfile();
123         }
124 
125         @Override
126         public ImsCallProfile getLocalCallProfile() {
127             return ImsCallSessionImplBase.this.getLocalCallProfile();
128         }
129 
130         @Override
131         public ImsCallProfile getRemoteCallProfile() {
132             return ImsCallSessionImplBase.this.getRemoteCallProfile();
133         }
134 
135         @Override
136         public String getProperty(String name) {
137             return ImsCallSessionImplBase.this.getProperty(name);
138         }
139 
140         @Override
141         public int getState() {
142             return ImsCallSessionImplBase.this.getState();
143         }
144 
145         @Override
146         public boolean isInCall() {
147             return ImsCallSessionImplBase.this.isInCall();
148         }
149 
150         @Override
151         public void setListener(IImsCallSessionListener listener) {
152             ImsCallSessionImplBase.this.setListener(new ImsCallSessionListener(listener));
153         }
154 
155         @Override
156         public void setMute(boolean muted) {
157             ImsCallSessionImplBase.this.setMute(muted);
158         }
159 
160         @Override
161         public void start(String callee, ImsCallProfile profile) {
162             ImsCallSessionImplBase.this.start(callee, profile);
163         }
164 
165         @Override
166         public void startConference(String[] participants, ImsCallProfile profile) throws
167                 RemoteException {
168             ImsCallSessionImplBase.this.startConference(participants, profile);
169         }
170 
171         @Override
172         public void accept(int callType, ImsStreamMediaProfile profile) {
173             ImsCallSessionImplBase.this.accept(callType, profile);
174         }
175 
176         @Override
177         public void deflect(String deflectNumber) {
178             ImsCallSessionImplBase.this.deflect(deflectNumber);
179         }
180 
181         @Override
182         public void reject(int reason) {
183             ImsCallSessionImplBase.this.reject(reason);
184         }
185 
186         @Override
187         public void transfer(@NonNull String number, boolean isConfirmationRequired) {
188             ImsCallSessionImplBase.this.transfer(number, isConfirmationRequired);
189         }
190 
191         @Override
192         public void consultativeTransfer(@NonNull IImsCallSession transferToSession) {
193             ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
194             otherSession.setServiceImpl(transferToSession);
195             ImsCallSessionImplBase.this.transfer(otherSession);
196         }
197 
198         @Override
199         public void terminate(int reason) {
200             ImsCallSessionImplBase.this.terminate(reason);
201         }
202 
203         @Override
204         public void hold(ImsStreamMediaProfile profile) {
205             ImsCallSessionImplBase.this.hold(profile);
206         }
207 
208         @Override
209         public void resume(ImsStreamMediaProfile profile) {
210             ImsCallSessionImplBase.this.resume(profile);
211         }
212 
213         @Override
214         public void merge() {
215             ImsCallSessionImplBase.this.merge();
216         }
217 
218         @Override
219         public void update(int callType, ImsStreamMediaProfile profile) {
220             ImsCallSessionImplBase.this.update(callType, profile);
221         }
222 
223         @Override
224         public void extendToConference(String[] participants) {
225             ImsCallSessionImplBase.this.extendToConference(participants);
226         }
227 
228         @Override
229         public void inviteParticipants(String[] participants) {
230             ImsCallSessionImplBase.this.inviteParticipants(participants);
231         }
232 
233         @Override
234         public void removeParticipants(String[] participants) {
235             ImsCallSessionImplBase.this.removeParticipants(participants);
236         }
237 
238         @Override
239         public void sendDtmf(char c, Message result) {
240             ImsCallSessionImplBase.this.sendDtmf(c, result);
241         }
242 
243         @Override
244         public void startDtmf(char c) {
245             ImsCallSessionImplBase.this.startDtmf(c);
246         }
247 
248         @Override
249         public void stopDtmf() {
250             ImsCallSessionImplBase.this.stopDtmf();
251         }
252 
253         @Override
254         public void sendUssd(String ussdMessage) {
255             ImsCallSessionImplBase.this.sendUssd(ussdMessage);
256         }
257 
258         @Override
259         public IImsVideoCallProvider getVideoCallProvider() {
260             return ImsCallSessionImplBase.this.getVideoCallProvider();
261         }
262 
263         @Override
264         public boolean isMultiparty() {
265             return ImsCallSessionImplBase.this.isMultiparty();
266         }
267 
268         @Override
269         public void sendRttModifyRequest(ImsCallProfile toProfile) {
270             ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile);
271         }
272 
273         @Override
274         public void sendRttModifyResponse(boolean status) {
275             ImsCallSessionImplBase.this.sendRttModifyResponse(status);
276         }
277 
278         @Override
279         public void sendRttMessage(String rttMessage) {
280             ImsCallSessionImplBase.this.sendRttMessage(rttMessage);
281         }
282     };
283 
284     /**
285      * @hide
286      */
setListener(IImsCallSessionListener listener)287     public final void setListener(IImsCallSessionListener listener) throws RemoteException {
288         setListener(new ImsCallSessionListener(listener));
289     }
290 
291     /**
292      * Sets the listener to listen to the session events. An {@link ImsCallSession}
293      * can only hold one listener at a time. Subsequent calls to this method
294      * override the previous listener.
295      *
296      * @param listener {@link ImsCallSessionListener} used to notify the framework of updates
297      * to the ImsCallSession
298      */
setListener(ImsCallSessionListener listener)299     public void setListener(ImsCallSessionListener listener) {
300     }
301 
302     /**
303      * Closes the object. This {@link ImsCallSessionImplBase} is not usable after being closed.
304      */
305     @Override
close()306     public void close() {
307 
308     }
309 
310     /**
311      * @return A String containing the unique call ID of this {@link ImsCallSessionImplBase}.
312      */
getCallId()313     public String getCallId() {
314         return null;
315     }
316 
317     /**
318      * @return The {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is associated
319      * with.
320      */
getCallProfile()321     public ImsCallProfile getCallProfile() {
322         return null;
323     }
324 
325     /**
326      * @return The local {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
327      * associated with.
328      */
getLocalCallProfile()329     public ImsCallProfile getLocalCallProfile() {
330         return null;
331     }
332 
333     /**
334      * @return The remote {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
335      * associated with.
336      */
getRemoteCallProfile()337     public ImsCallProfile getRemoteCallProfile() {
338         return null;
339     }
340 
341     /**
342      * @param name The String extra key.
343      * @return The string extra value associated with the specified property.
344      */
getProperty(String name)345     public String getProperty(String name) {
346         return null;
347     }
348 
349     /**
350      * @return The {@link ImsCallSessionImplBase} state, defined in
351      * {@link ImsCallSessionImplBase.State}.
352      */
getState()353     public int getState() {
354         return ImsCallSessionImplBase.State.INVALID;
355     }
356 
357     /**
358      * @return true if the {@link ImsCallSessionImplBase} is in a call, false otherwise.
359      */
isInCall()360     public boolean isInCall() {
361         return false;
362     }
363 
364     /**
365      * Mutes or unmutes the mic for the active call.
366      *
367      * @param muted true if the call should be muted, false otherwise.
368      */
setMute(boolean muted)369     public void setMute(boolean muted) {
370     }
371 
372     /**
373      * Initiates an IMS call with the specified number and call profile.
374      * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon
375      * defined session events.
376      * Only valid to call when the session state is in
377      * {@link ImsCallSession.State#IDLE}.
378      *
379      * @param callee dialed string to make the call to
380      * @param profile call profile to make the call with the specified service type,
381      *      call type and media information
382      * @see {@link ImsCallSession.Listener#callSessionStarted},
383      * {@link ImsCallSession.Listener#callSessionStartFailed}
384      */
start(String callee, ImsCallProfile profile)385     public void start(String callee, ImsCallProfile profile) {
386     }
387 
388     /**
389      * Initiates an IMS call with the specified participants and call profile.
390      * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon
391      * defined session events.
392      * The method is only valid to call when the session state is in
393      * {@link ImsCallSession.State#IDLE}.
394      *
395      * @param participants participant list to initiate an IMS conference call
396      * @param profile call profile to make the call with the specified service type,
397      *      call type and media information
398      * @see {@link ImsCallSession.Listener#callSessionStarted},
399      * {@link ImsCallSession.Listener#callSessionStartFailed}
400      */
startConference(String[] participants, ImsCallProfile profile)401     public void startConference(String[] participants, ImsCallProfile profile) {
402     }
403 
404     /**
405      * Accepts an incoming call or session update.
406      *
407      * @param callType call type specified in {@link ImsCallProfile} to be answered
408      * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
409      * @see {@link ImsCallSession.Listener#callSessionStarted}
410      */
accept(int callType, ImsStreamMediaProfile profile)411     public void accept(int callType, ImsStreamMediaProfile profile) {
412     }
413 
414     /**
415      * Deflects an incoming call.
416      *
417      * @param deflectNumber number to deflect the call
418      */
deflect(String deflectNumber)419     public void deflect(String deflectNumber) {
420     }
421 
422     /**
423      * Rejects an incoming call or session update.
424      *
425      * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
426      *               The {@link android.telecom.InCallService} (dialer app) can use the
427      *               {@link android.telecom.Call#reject(int)} API to reject a call while specifying
428      *               a user-indicated reason for rejecting the call.
429      *               Normal call declines ({@link android.telecom.Call#REJECT_REASON_DECLINED}) will
430      *               map to {@link ImsReasonInfo#CODE_USER_DECLINE}.
431      *               Unwanted calls ({@link android.telecom.Call#REJECT_REASON_UNWANTED}) will map
432      *               to {@link ImsReasonInfo#CODE_SIP_USER_MARKED_UNWANTED}.
433      * {@link ImsCallSession.Listener#callSessionStartFailed}
434      */
reject(int reason)435     public void reject(int reason) {
436     }
437 
438     /**
439      * Transfer an established call to given number
440      *
441      * @param number number to transfer the call
442      * @param isConfirmationRequired if {@code True}, indicates Assured transfer,
443      * if {@code False} it indicates Blind transfer.
444      * @hide
445      */
transfer(@onNull String number, boolean isConfirmationRequired)446     public void transfer(@NonNull String number, boolean isConfirmationRequired) {
447     }
448 
449     /**
450      * Transfer an established call to another call session
451      *
452      * @param otherSession The other ImsCallSession to transfer the ongoing session to.
453      * @hide
454      */
transfer(@onNull ImsCallSessionImplBase otherSession)455     public void transfer(@NonNull ImsCallSessionImplBase otherSession) {
456     }
457 
458     /**
459      * Terminates a call.
460      *
461      * @param reason reason code to terminate a call, defined in {@link ImsReasonInfo}.
462      *
463      * @see {@link ImsCallSession.Listener#callSessionTerminated}
464      */
terminate(int reason)465     public void terminate(int reason) {
466     }
467 
468     /**
469      * Puts a call on hold. When it succeeds, {@link ImsCallSession.Listener#callSessionHeld} is
470      * called.
471      *
472      * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call
473      * @see {@link ImsCallSession.Listener#callSessionHeld},
474      * {@link ImsCallSession.Listener#callSessionHoldFailed}
475      */
hold(ImsStreamMediaProfile profile)476     public void hold(ImsStreamMediaProfile profile) {
477     }
478 
479     /**
480      * Continues a call that's on hold. When it succeeds,
481      * {@link ImsCallSession.Listener#callSessionResumed} is called.
482      *
483      * @param profile stream media profile with {@link ImsStreamMediaProfile} to resume the call
484      * @see {@link ImsCallSession.Listener#callSessionResumed},
485      * {@link ImsCallSession.Listener#callSessionResumeFailed}
486      */
resume(ImsStreamMediaProfile profile)487     public void resume(ImsStreamMediaProfile profile) {
488     }
489 
490     /**
491      * Merges the active and held call. When the merge starts,
492      * {@link ImsCallSession.Listener#callSessionMergeStarted} is called.
493      * {@link ImsCallSession.Listener#callSessionMergeComplete} is called if the merge is
494      * successful, and {@link ImsCallSession.Listener#callSessionMergeFailed} is called if the merge
495      * fails.
496      *
497      * @see {@link ImsCallSession.Listener#callSessionMergeStarted},
498      * {@link ImsCallSession.Listener#callSessionMergeComplete},
499      *      {@link ImsCallSession.Listener#callSessionMergeFailed}
500      */
merge()501     public void merge() {
502     }
503 
504     /**
505      * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
506      *
507      * @param callType call type specified in {@link ImsCallProfile} to be updated
508      * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated
509      * @see {@link ImsCallSession.Listener#callSessionUpdated},
510      * {@link ImsCallSession.Listener#callSessionUpdateFailed}
511      */
update(int callType, ImsStreamMediaProfile profile)512     public void update(int callType, ImsStreamMediaProfile profile) {
513     }
514 
515     /**
516      * Extends this call to the conference call with the specified recipients.
517      *
518      * @param participants participant list to be invited to the conference call after extending the
519      * call
520      * @see {@link ImsCallSession.Listener#callSessionConferenceExtended},
521      * {@link ImsCallSession.Listener#callSessionConferenceExtendFailed}
522      */
extendToConference(String[] participants)523     public void extendToConference(String[] participants) {
524     }
525 
526     /**
527      * Requests the conference server to invite an additional participants to the conference.
528      *
529      * @param participants participant list to be invited to the conference call
530      * @see {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestDelivered},
531      *      {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestFailed}
532      */
inviteParticipants(String[] participants)533     public void inviteParticipants(String[] participants) {
534     }
535 
536     /**
537      * Requests the conference server to remove the specified participants from the conference.
538      *
539      * @param participants participant list to be removed from the conference call
540      * @see {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestDelivered},
541      *      {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestFailed}
542      */
removeParticipants(String[] participants)543     public void removeParticipants(String[] participants) {
544     }
545 
546     /**
547      * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
548      * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
549      * and event flash to 16. Currently, event flash is not supported.
550      *
551      * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
552      * @param result If non-null, the {@link Message} to send when the operation is complete. This
553      *         is done by using the associated {@link android.os.Messenger} in
554      *         {@link Message#replyTo}. For example:
555      * {@code
556      *     // Send DTMF and other operations...
557      *     try {
558      *         // Notify framework that the DTMF was sent.
559      *         Messenger dtmfMessenger = result.replyTo;
560      *         if (dtmfMessenger != null) {
561      *             dtmfMessenger.send(result);
562      *         }
563      *     } catch (RemoteException e) {
564      *         // Remote side is dead
565      *     }
566      * }
567      */
sendDtmf(char c, Message result)568     public void sendDtmf(char c, Message result) {
569     }
570 
571     /**
572      * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
573      * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
574      * and event flash to 16. Currently, event flash is not supported.
575      *
576      * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
577      */
startDtmf(char c)578     public void startDtmf(char c) {
579     }
580 
581     /**
582      * Stop a DTMF code.
583      */
stopDtmf()584     public void stopDtmf() {
585     }
586 
587     /**
588      * Sends an USSD message.
589      *
590      * @param ussdMessage USSD message to send
591      */
sendUssd(String ussdMessage)592     public void sendUssd(String ussdMessage) {
593     }
594 
595     /**
596      * See {@link #getImsVideoCallProvider()}, used directly in older ImsService implementations.
597      * @hide
598      */
getVideoCallProvider()599     public IImsVideoCallProvider getVideoCallProvider() {
600         ImsVideoCallProvider provider = getImsVideoCallProvider();
601         return provider != null ? provider.getInterface() : null;
602     }
603 
604     /**
605      * @return The {@link ImsVideoCallProvider} implementation contained within the IMS service
606      * process.
607      */
getImsVideoCallProvider()608     public ImsVideoCallProvider getImsVideoCallProvider() {
609         return null;
610     }
611 
612     /**
613      * Determines if the current session is multiparty.
614      * @return {@code True} if the session is multiparty.
615      */
isMultiparty()616     public boolean isMultiparty() {
617         return false;
618     }
619 
620     /**
621      * Device issues RTT modify request
622      * @param toProfile The profile with requested changes made
623      */
sendRttModifyRequest(ImsCallProfile toProfile)624     public void sendRttModifyRequest(ImsCallProfile toProfile) {
625     }
626 
627     /**
628      * Device responds to Remote RTT modify request
629      * @param status true if the the request was accepted or false of the request is defined.
630      */
sendRttModifyResponse(boolean status)631     public void sendRttModifyResponse(boolean status) {
632     }
633 
634     /**
635      * Device sends RTT message
636      * @param rttMessage RTT message to be sent
637      */
sendRttMessage(String rttMessage)638     public void sendRttMessage(String rttMessage) {
639     }
640 
641     /** @hide */
getServiceImpl()642     public IImsCallSession getServiceImpl() {
643         return mServiceImpl;
644     }
645 
646     /** @hide */
setServiceImpl(IImsCallSession serviceImpl)647     public void setServiceImpl(IImsCallSession serviceImpl) {
648         mServiceImpl = serviceImpl;
649     }
650 }
651