1 /*
2  * Copyright (C) 2021 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 com.android.internal.telephony;
18 
19 import android.os.RemoteException;
20 import android.telephony.PhoneNumberUtils;
21 import android.telephony.Rlog;
22 import android.telephony.emergency.EmergencyNumber;
23 
24 import java.util.ArrayList;
25 
26 /**
27  * A holder for IRadioVoice.
28  * Use getAidl to get IRadioVoice and call the AIDL implementations of the HAL APIs.
29  */
30 public class RadioVoiceProxy extends RadioServiceProxy {
31     private static final String TAG = "RadioVoiceProxy";
32     private volatile android.hardware.radio.voice.IRadioVoice mVoiceProxy = null;
33 
34     /**
35      * Set IRadioVoice as the AIDL implementation for RadioServiceProxy
36      * @param halVersion Radio HAL version
37      * @param voice IRadioVoice implementation
38      *
39      * @return updated HAL version
40      */
setAidl(HalVersion halVersion, android.hardware.radio.voice.IRadioVoice voice)41     public HalVersion setAidl(HalVersion halVersion,
42             android.hardware.radio.voice.IRadioVoice voice) {
43         HalVersion version = halVersion;
44         try {
45             version = RIL.getServiceHalVersion(voice.getInterfaceVersion());
46         } catch (RemoteException e) {
47             Rlog.e(TAG, "setAidl: " + e);
48         }
49         mHalVersion = version;
50         mVoiceProxy = voice;
51         mIsAidl = true;
52 
53         Rlog.d(TAG, "AIDL initialized mHalVersion=" + mHalVersion);
54         return mHalVersion;
55     }
56 
57     /**
58      * Get the AIDL implementation of RadioVoiceProxy
59      * @return IRadioVoice implementation
60      */
getAidl()61     public android.hardware.radio.voice.IRadioVoice getAidl() {
62         return mVoiceProxy;
63     }
64 
65     /**
66      * Reset RadioVoiceProxy
67      */
68     @Override
clear()69     public void clear() {
70         super.clear();
71         mVoiceProxy = null;
72     }
73 
74     /**
75      * Check whether a RadioVoice implementation exists
76      * @return true if there is neither a HIDL nor AIDL implementation
77      */
78     @Override
isEmpty()79     public boolean isEmpty() {
80         return mRadioProxy == null && mVoiceProxy == null;
81     }
82 
83     /**
84      * Call IRadioVoice#acceptCall
85      * @param serial Serial number of request
86      * @throws RemoteException
87      */
acceptCall(int serial)88     public void acceptCall(int serial) throws RemoteException {
89         if (isEmpty()) return;
90         if (isAidl()) {
91             mVoiceProxy.acceptCall(serial);
92         } else {
93             mRadioProxy.acceptCall(serial);
94         }
95     }
96 
97     /**
98      * Call IRadioVoice#cancelPendingUssd
99      * @param serial Serial number of request
100      * @throws RemoteException
101      */
cancelPendingUssd(int serial)102     public void cancelPendingUssd(int serial) throws RemoteException {
103         if (isEmpty()) return;
104         if (isAidl()) {
105             mVoiceProxy.cancelPendingUssd(serial);
106         } else {
107             mRadioProxy.cancelPendingUssd(serial);
108         }
109     }
110 
111     /**
112      * Call IRadioVoice#conference
113      * @param serial Serial number of request
114      * @throws RemoteException
115      */
conference(int serial)116     public void conference(int serial) throws RemoteException {
117         if (isEmpty()) return;
118         if (isAidl()) {
119             mVoiceProxy.conference(serial);
120         } else {
121             mRadioProxy.conference(serial);
122         }
123     }
124 
125     /**
126      * Call IRadioVoice#dial
127      * @param serial Serial number of request
128      * @param address Address
129      * @param clirMode CLIR mode
130      * @param uusInfo UUS info
131      * @throws RemoteException
132      */
dial(int serial, String address, int clirMode, UUSInfo uusInfo)133     public void dial(int serial, String address, int clirMode, UUSInfo uusInfo)
134             throws RemoteException {
135         if (isEmpty()) return;
136         if (isAidl()) {
137             mVoiceProxy.dial(serial, RILUtils.convertToHalDialAidl(address, clirMode, uusInfo));
138         } else {
139             mRadioProxy.dial(serial, RILUtils.convertToHalDial(address, clirMode, uusInfo));
140         }
141     }
142 
143     /**
144      * Call IRadioVoice#emergencyDial
145      * @param serial Serial number of request
146      * @param address Address
147      * @param emergencyNumberInfo Emergency number information
148      * @param hasKnownUserIntentEmergency Whether or not the request has known user intent emergency
149      * @param clirMode CLIR mode
150      * @param uusInfo UUS info
151      * @throws RemoteException
152      */
emergencyDial(int serial, String address, EmergencyNumber emergencyNumberInfo, boolean hasKnownUserIntentEmergency, int clirMode, UUSInfo uusInfo)153     public void emergencyDial(int serial, String address, EmergencyNumber emergencyNumberInfo,
154             boolean hasKnownUserIntentEmergency, int clirMode, UUSInfo uusInfo)
155             throws RemoteException {
156         if (isEmpty()) return;
157         if (isAidl()) {
158             mVoiceProxy.emergencyDial(serial,
159                     RILUtils.convertToHalDialAidl(address, clirMode, uusInfo),
160                     emergencyNumberInfo.getEmergencyServiceCategoryBitmaskInternalDial(),
161                     emergencyNumberInfo.getEmergencyUrns() != null
162                             ? emergencyNumberInfo.getEmergencyUrns().stream().toArray(String[]::new)
163                             : new String[0],
164                     emergencyNumberInfo.getEmergencyCallRouting(),
165                     hasKnownUserIntentEmergency,
166                     emergencyNumberInfo.getEmergencyNumberSourceBitmask()
167                             == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST);
168         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) {
169             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).emergencyDial_1_6(serial,
170                     RILUtils.convertToHalDial(address, clirMode, uusInfo),
171                     emergencyNumberInfo.getEmergencyServiceCategoryBitmaskInternalDial(),
172                     emergencyNumberInfo.getEmergencyUrns() != null
173                             ? new ArrayList(emergencyNumberInfo.getEmergencyUrns())
174                             : new ArrayList<>(),
175                     emergencyNumberInfo.getEmergencyCallRouting(),
176                     hasKnownUserIntentEmergency,
177                     emergencyNumberInfo.getEmergencyNumberSourceBitmask()
178                             == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST);
179         } else {
180             mRadioProxy.emergencyDial(serial,
181                     RILUtils.convertToHalDial(address, clirMode, uusInfo),
182                     emergencyNumberInfo.getEmergencyServiceCategoryBitmaskInternalDial(),
183                     emergencyNumberInfo.getEmergencyUrns() != null
184                             ? new ArrayList(emergencyNumberInfo.getEmergencyUrns())
185                             : new ArrayList<>(),
186                     emergencyNumberInfo.getEmergencyCallRouting(),
187                     hasKnownUserIntentEmergency,
188                     emergencyNumberInfo.getEmergencyNumberSourceBitmask()
189                             == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST);
190         }
191     }
192 
193     /**
194      * Call IRadioVoice#exitEmergencyCallbackMode
195      * @param serial Serial number of request
196      * @throws RemoteException
197      */
exitEmergencyCallbackMode(int serial)198     public void exitEmergencyCallbackMode(int serial) throws RemoteException {
199         if (isEmpty()) return;
200         if (isAidl()) {
201             mVoiceProxy.exitEmergencyCallbackMode(serial);
202         } else {
203             mRadioProxy.exitEmergencyCallbackMode(serial);
204         }
205     }
206 
207     /**
208      * Call IRadioVoice#explicitCallTransfer
209      * @param serial Serial number of request
210      * @throws RemoteException
211      */
explicitCallTransfer(int serial)212     public void explicitCallTransfer(int serial) throws RemoteException {
213         if (isEmpty()) return;
214         if (isAidl()) {
215             mVoiceProxy.explicitCallTransfer(serial);
216         } else {
217             mRadioProxy.explicitCallTransfer(serial);
218         }
219     }
220 
221     /**
222      * Call IRadioVoice#getCallForwardStatus
223      * @param serial Serial number of request
224      * @param cfReason One of CF_REASON_*
225      * @param serviceClass Sum of SERVICE_CLASS_*
226      * @param number Number
227      * @throws RemoteException
228      */
getCallForwardStatus(int serial, int cfReason, int serviceClass, String number)229     public void getCallForwardStatus(int serial, int cfReason, int serviceClass, String number)
230             throws RemoteException {
231         if (isEmpty()) return;
232         if (isAidl()) {
233             android.hardware.radio.voice.CallForwardInfo cfInfo =
234                     new android.hardware.radio.voice.CallForwardInfo();
235             cfInfo.reason = cfReason;
236             cfInfo.serviceClass = serviceClass;
237             cfInfo.toa = PhoneNumberUtils.toaFromString(number);
238             cfInfo.number = RILUtils.convertNullToEmptyString(number);
239             cfInfo.timeSeconds = 0;
240             mVoiceProxy.getCallForwardStatus(serial, cfInfo);
241         } else {
242             android.hardware.radio.V1_0.CallForwardInfo cfInfo =
243                     new android.hardware.radio.V1_0.CallForwardInfo();
244             cfInfo.reason = cfReason;
245             cfInfo.serviceClass = serviceClass;
246             cfInfo.toa = PhoneNumberUtils.toaFromString(number);
247             cfInfo.number = RILUtils.convertNullToEmptyString(number);
248             cfInfo.timeSeconds = 0;
249             mRadioProxy.getCallForwardStatus(serial, cfInfo);
250         }
251     }
252 
253     /**
254      * Call IRadioVoice#getCallWaiting
255      * @param serial Serial number of request
256      * @param serviceClass Sum of SERVICE_CLASS_*
257      * @throws RemoteException
258      */
getCallWaiting(int serial, int serviceClass)259     public void getCallWaiting(int serial, int serviceClass) throws RemoteException {
260         if (isEmpty()) return;
261         if (isAidl()) {
262             mVoiceProxy.getCallWaiting(serial, serviceClass);
263         } else {
264             mRadioProxy.getCallWaiting(serial, serviceClass);
265         }
266     }
267 
268     /**
269      * Call IRadioVoice#getClip
270      * @param serial Serial number of request
271      * @throws RemoteException
272      */
getClip(int serial)273     public void getClip(int serial) throws RemoteException {
274         if (isEmpty()) return;
275         if (isAidl()) {
276             mVoiceProxy.getClip(serial);
277         } else {
278             mRadioProxy.getClip(serial);
279         }
280     }
281 
282     /**
283      * Call IRadioVoice#getClir
284      * @param serial Serial number of request
285      * @throws RemoteException
286      */
getClir(int serial)287     public void getClir(int serial) throws RemoteException {
288         if (isEmpty()) return;
289         if (isAidl()) {
290             mVoiceProxy.getClir(serial);
291         } else {
292             mRadioProxy.getClir(serial);
293         }
294     }
295 
296     /**
297      * Call IRadioVoice#getCurrentCalls
298      * @param serial Serial number of request
299      * @throws RemoteException
300      */
getCurrentCalls(int serial)301     public void getCurrentCalls(int serial) throws RemoteException {
302         if (isEmpty()) return;
303         if (isAidl()) {
304             mVoiceProxy.getCurrentCalls(serial);
305         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) {
306             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).getCurrentCalls_1_6(serial);
307         } else {
308             mRadioProxy.getCurrentCalls(serial);
309         }
310     }
311 
312     /**
313      * Call IRadioVoice#getLastCallFailCause
314      * @param serial Serial number of request
315      * @throws RemoteException
316      */
getLastCallFailCause(int serial)317     public void getLastCallFailCause(int serial) throws RemoteException {
318         if (isEmpty()) return;
319         if (isAidl()) {
320             mVoiceProxy.getLastCallFailCause(serial);
321         } else {
322             mRadioProxy.getLastCallFailCause(serial);
323         }
324     }
325 
326     /**
327      * Call IRadioVoice#getMute
328      * @param serial Serial number of request
329      * @throws RemoteException
330      */
getMute(int serial)331     public void getMute(int serial) throws RemoteException {
332         if (isEmpty()) return;
333         if (isAidl()) {
334             mVoiceProxy.getMute(serial);
335         } else {
336             mRadioProxy.getMute(serial);
337         }
338     }
339 
340     /**
341      * Call IRadioVoice#getPreferredVoicePrivacy
342      * @param serial Serial number of request
343      * @throws RemoteException
344      */
getPreferredVoicePrivacy(int serial)345     public void getPreferredVoicePrivacy(int serial) throws RemoteException {
346         if (isEmpty()) return;
347         if (isAidl()) {
348             mVoiceProxy.getPreferredVoicePrivacy(serial);
349         } else {
350             mRadioProxy.getPreferredVoicePrivacy(serial);
351         }
352     }
353 
354     /**
355      * Call IRadioVoice#getTtyMode
356      * @param serial Serial number of request
357      * @throws RemoteException
358      */
getTtyMode(int serial)359     public void getTtyMode(int serial) throws RemoteException {
360         if (isEmpty()) return;
361         if (isAidl()) {
362             mVoiceProxy.getTtyMode(serial);
363         } else {
364             mRadioProxy.getTTYMode(serial);
365         }
366     }
367 
368     /**
369      * Call IRadioVoice#handleStkCallSetupRequestFromSim
370      * @param serial Serial number of request
371      * @param accept Whether or not the call is to be accepted
372      * @throws RemoteException
373      */
handleStkCallSetupRequestFromSim(int serial, boolean accept)374     public void handleStkCallSetupRequestFromSim(int serial, boolean accept)
375             throws RemoteException {
376         if (isEmpty()) return;
377         if (isAidl()) {
378             mVoiceProxy.handleStkCallSetupRequestFromSim(serial, accept);
379         } else {
380             mRadioProxy.handleStkCallSetupRequestFromSim(serial, accept);
381         }
382     }
383 
384     /**
385      * Call IRadioVoice#hangup
386      * @param serial Serial number of request
387      * @param gsmIndex Connection index
388      * @throws RemoteException
389      */
hangup(int serial, int gsmIndex)390     public void hangup(int serial, int gsmIndex) throws RemoteException {
391         if (isEmpty()) return;
392         if (isAidl()) {
393             mVoiceProxy.hangup(serial, gsmIndex);
394         } else {
395             mRadioProxy.hangup(serial, gsmIndex);
396         }
397     }
398 
399     /**
400      * Call IRadioVoice#hangupForegroundResumeBackground
401      * @param serial Serial number of request
402      * @throws RemoteException
403      */
hangupForegroundResumeBackground(int serial)404     public void hangupForegroundResumeBackground(int serial) throws RemoteException {
405         if (isEmpty()) return;
406         if (isAidl()) {
407             mVoiceProxy.hangupForegroundResumeBackground(serial);
408         } else {
409             mRadioProxy.hangupForegroundResumeBackground(serial);
410         }
411     }
412 
413     /**
414      * Call IRadioVoice#hangupWaitingOrBackground
415      * @param serial Serial number of request
416      * @throws RemoteException
417      */
hangupWaitingOrBackground(int serial)418     public void hangupWaitingOrBackground(int serial) throws RemoteException {
419         if (isEmpty()) return;
420         if (isAidl()) {
421             mVoiceProxy.hangupWaitingOrBackground(serial);
422         } else {
423             mRadioProxy.hangupWaitingOrBackground(serial);
424         }
425     }
426 
427     /**
428      * Call IRadioVoice#isVoNrEnabled
429      * @param serial Serial number of request
430      * @throws RemoteException
431      */
isVoNrEnabled(int serial)432     public void isVoNrEnabled(int serial) throws RemoteException {
433         if (isEmpty()) return;
434         if (isAidl()) {
435             mVoiceProxy.isVoNrEnabled(serial);
436         }
437     }
438 
439     /**
440      * Call IRadioVoice#rejectCall
441      * @param serial Serial number of request
442      * @throws RemoteException
443      */
rejectCall(int serial)444     public void rejectCall(int serial) throws RemoteException {
445         if (isEmpty()) return;
446         if (isAidl()) {
447             mVoiceProxy.rejectCall(serial);
448         } else {
449             mRadioProxy.rejectCall(serial);
450         }
451     }
452 
453     /**
454      * Call IRadioVoice#responseAcknowledgement
455      * @throws RemoteException
456      */
457     @Override
responseAcknowledgement()458     public void responseAcknowledgement() throws RemoteException {
459         if (isEmpty()) return;
460         if (isAidl()) {
461             mVoiceProxy.responseAcknowledgement();
462         } else {
463             mRadioProxy.responseAcknowledgement();
464         }
465     }
466 
467     /**
468      * Call IRadioVoice#sendBurstDtmf
469      * @param serial Serial number of request
470      * @param dtmf DTMF string
471      * @param on DTMF ON length in milliseconds, or 0 to use default
472      * @param off DTMF OFF length in milliseconds, or 0 to use default
473      * @throws RemoteException
474      */
sendBurstDtmf(int serial, String dtmf, int on, int off)475     public void sendBurstDtmf(int serial, String dtmf, int on, int off) throws RemoteException {
476         if (isEmpty()) return;
477         if (isAidl()) {
478             mVoiceProxy.sendBurstDtmf(serial, dtmf, on, off);
479         } else {
480             mRadioProxy.sendBurstDtmf(serial, dtmf, on, off);
481         }
482     }
483 
484     /**
485      * Call IRadioVoice#sendCdmaFeatureCode
486      * @param serial Serial number of request
487      * @param featureCode String associated with FLASH command
488      * @throws RemoteException
489      */
sendCdmaFeatureCode(int serial, String featureCode)490     public void sendCdmaFeatureCode(int serial, String featureCode) throws RemoteException {
491         if (isEmpty()) return;
492         if (isAidl()) {
493             mVoiceProxy.sendCdmaFeatureCode(serial, featureCode);
494         } else {
495             mRadioProxy.sendCDMAFeatureCode(serial, featureCode);
496         }
497     }
498 
499     /**
500      * Call IRadioVoice#sendDtmf
501      * @param serial Serial number of request
502      * @param s String with single char having one of 12 values: 0-0, *, #
503      * @throws RemoteException
504      */
sendDtmf(int serial, String s)505     public void sendDtmf(int serial, String s) throws RemoteException {
506         if (isEmpty()) return;
507         if (isAidl()) {
508             mVoiceProxy.sendDtmf(serial, s);
509         } else {
510             mRadioProxy.sendDtmf(serial, s);
511         }
512     }
513 
514     /**
515      * Call IRadioVoice#sendUssd
516      * @param serial Serial number of request
517      * @param ussd String containing the USSD request in UTF-8 format
518      * @throws RemoteException
519      */
sendUssd(int serial, String ussd)520     public void sendUssd(int serial, String ussd) throws RemoteException {
521         if (isEmpty()) return;
522         if (isAidl()) {
523             mVoiceProxy.sendUssd(serial, ussd);
524         } else {
525             mRadioProxy.sendUssd(serial, ussd);
526         }
527     }
528 
529     /**
530      * Call IRadioVoice#separateConnection
531      * @param serial Serial number of request
532      * @param gsmIndex Connection index
533      * @throws RemoteException
534      */
separateConnection(int serial, int gsmIndex)535     public void separateConnection(int serial, int gsmIndex) throws RemoteException {
536         if (isEmpty()) return;
537         if (isAidl()) {
538             mVoiceProxy.separateConnection(serial, gsmIndex);
539         } else {
540             mRadioProxy.separateConnection(serial, gsmIndex);
541         }
542     }
543 
544     /**
545      * Call IRadioVoice#setCallForward
546      * @param serial Serial number of request
547      * @param action One of CF_ACTION_*
548      * @param cfReason One of CF_REASON_*
549      * @param serviceClass Sum of SERVICE_CLASSS_*
550      * @param number Number
551      * @param timeSeconds Time in seconds
552      * @throws RemoteException
553      */
setCallForward(int serial, int action, int cfReason, int serviceClass, String number, int timeSeconds)554     public void setCallForward(int serial, int action, int cfReason, int serviceClass,
555             String number, int timeSeconds) throws RemoteException {
556         if (isEmpty()) return;
557         if (isAidl()) {
558             android.hardware.radio.voice.CallForwardInfo cfInfo =
559                     new android.hardware.radio.voice.CallForwardInfo();
560             cfInfo.status = action;
561             cfInfo.reason = cfReason;
562             cfInfo.serviceClass = serviceClass;
563             cfInfo.toa = PhoneNumberUtils.toaFromString(number);
564             cfInfo.number = RILUtils.convertNullToEmptyString(number);
565             cfInfo.timeSeconds = timeSeconds;
566             mVoiceProxy.setCallForward(serial, cfInfo);
567         } else {
568             android.hardware.radio.V1_0.CallForwardInfo cfInfo =
569                     new android.hardware.radio.V1_0.CallForwardInfo();
570             cfInfo.status = action;
571             cfInfo.reason = cfReason;
572             cfInfo.serviceClass = serviceClass;
573             cfInfo.toa = PhoneNumberUtils.toaFromString(number);
574             cfInfo.number = RILUtils.convertNullToEmptyString(number);
575             cfInfo.timeSeconds = timeSeconds;
576             mRadioProxy.setCallForward(serial, cfInfo);
577         }
578     }
579 
580     /**
581      * Call IRadioVoice#setCallWaiting
582      * @param serial Serial number of request
583      * @param enable True to enable, false to disable
584      * @param serviceClass Sum of SERVICE_CLASS_*
585      * @throws RemoteException
586      */
setCallWaiting(int serial, boolean enable, int serviceClass)587     public void setCallWaiting(int serial, boolean enable, int serviceClass)
588             throws RemoteException {
589         if (isEmpty()) return;
590         if (isAidl()) {
591             mVoiceProxy.setCallWaiting(serial, enable, serviceClass);
592         } else {
593             mRadioProxy.setCallWaiting(serial, enable, serviceClass);
594         }
595     }
596 
597     /**
598      * Call IRadioVoice#setClir
599      * @param serial Serial number of request
600      * @param status One of CLIR_*
601      * @throws RemoteException
602      */
setClir(int serial, int status)603     public void setClir(int serial, int status) throws RemoteException {
604         if (isEmpty()) return;
605         if (isAidl()) {
606             mVoiceProxy.setClir(serial, status);
607         } else {
608             mRadioProxy.setClir(serial, status);
609         }
610     }
611 
612     /**
613      * Call IRadioVoice#setMute
614      * @param serial Serial number of request
615      * @param enable True to enable, false to disable
616      * @throws RemoteException
617      */
setMute(int serial, boolean enable)618     public void setMute(int serial, boolean enable) throws RemoteException {
619         if (isEmpty()) return;
620         if (isAidl()) {
621             mVoiceProxy.setMute(serial, enable);
622         } else {
623             mRadioProxy.setMute(serial, enable);
624         }
625     }
626 
627     /**
628      * Call IRadioVoice#setPreferredVoicePrivacy
629      * @param serial Serial number of request
630      * @param enable True is enhanced, false is normal voice privacy
631      * @throws RemoteException
632      */
setPreferredVoicePrivacy(int serial, boolean enable)633     public void setPreferredVoicePrivacy(int serial, boolean enable) throws RemoteException {
634         if (isEmpty()) return;
635         if (isAidl()) {
636             mVoiceProxy.setPreferredVoicePrivacy(serial, enable);
637         } else {
638             mRadioProxy.setPreferredVoicePrivacy(serial, enable);
639         }
640     }
641 
642     /**
643      * Call IRadioVoice#setTtyMode
644      * @param serial Serial number of request
645      * @param mode One of TTY_MODE_*
646      * @throws RemoteException
647      */
setTtyMode(int serial, int mode)648     public void setTtyMode(int serial, int mode) throws RemoteException {
649         if (isEmpty()) return;
650         if (isAidl()) {
651             mVoiceProxy.setTtyMode(serial, mode);
652         } else {
653             mRadioProxy.setTTYMode(serial, mode);
654         }
655     }
656 
657     /**
658      * Call IRadioVoice#setVoNrEnabled
659      * @param serial Serial number of request
660      * @param enable True to enable, false to disable
661      * @throws RemoteException
662      */
setVoNrEnabled(int serial, boolean enable)663     public void setVoNrEnabled(int serial, boolean enable) throws RemoteException {
664         if (isEmpty()) return;
665         if (isAidl()) {
666             mVoiceProxy.setVoNrEnabled(serial, enable);
667         }
668     }
669 
670     /**
671      * Call IRadioVoice#startDtmf
672      * @param serial Serial number of request
673      * @param s String having a single character with one of 12 values: 0-9, *, #
674      * @throws RemoteException
675      */
startDtmf(int serial, String s)676     public void startDtmf(int serial, String s) throws RemoteException {
677         if (isEmpty()) return;
678         if (isAidl()) {
679             mVoiceProxy.startDtmf(serial, s);
680         } else {
681             mRadioProxy.startDtmf(serial, s);
682         }
683     }
684 
685     /**
686      * Call IRadioVoice#stopDtmf
687      * @param serial Serial number of request
688      * @throws RemoteException
689      */
stopDtmf(int serial)690     public void stopDtmf(int serial) throws RemoteException {
691         if (isEmpty()) return;
692         if (isAidl()) {
693             mVoiceProxy.stopDtmf(serial);
694         } else {
695             mRadioProxy.stopDtmf(serial);
696         }
697     }
698 
699     /**
700      * Call IRadioVoice#switchWaitingOrHoldingAndActive
701      * @param serial Serial number of request
702      * @throws RemoteException
703      */
switchWaitingOrHoldingAndActive(int serial)704     public void switchWaitingOrHoldingAndActive(int serial) throws RemoteException {
705         if (isEmpty()) return;
706         if (isAidl()) {
707             mVoiceProxy.switchWaitingOrHoldingAndActive(serial);
708         } else {
709             mRadioProxy.switchWaitingOrHoldingAndActive(serial);
710         }
711     }
712 }
713