• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 #define FAILURE_DEBUG_PREFIX "RadioVoice"
18 
19 #include "RadioVoice.h"
20 
21 #include "atCmds.h"
22 #include "debug.h"
23 #include "makeRadioResponseInfo.h"
24 
25 namespace aidl {
26 namespace android {
27 namespace hardware {
28 namespace radio {
29 namespace implementation {
30 
RadioVoice(std::shared_ptr<AtChannel> atChannel)31 RadioVoice::RadioVoice(std::shared_ptr<AtChannel> atChannel) : mAtChannel(std::move(atChannel)) {
32 }
33 
acceptCall(const int32_t serial)34 ScopedAStatus RadioVoice::acceptCall(const int32_t serial) {
35     mAtChannel->queueRequester([this, serial]
36                                (const AtChannel::RequestPipe requestPipe) -> bool {
37         requestPipe(atCmds::acceptCall);
38         NOT_NULL(mRadioVoiceResponse)->acceptCallResponse(
39             makeRadioResponseInfo(serial));
40         return true;
41     });
42 
43     return ScopedAStatus::ok();
44 }
45 
cancelPendingUssd(const int32_t serial)46 ScopedAStatus RadioVoice::cancelPendingUssd(const int32_t serial) {
47     mAtChannel->queueRequester([this, serial]
48                                (const AtChannel::RequestPipe requestPipe) -> bool {
49         requestPipe(atCmds::cancelUssd);
50         NOT_NULL(mRadioVoiceResponse)->cancelPendingUssdResponse(
51             makeRadioResponseInfo(serial));
52         return true;
53     });
54 
55     return ScopedAStatus::ok();
56 }
57 
conference(const int32_t serial)58 ScopedAStatus RadioVoice::conference(const int32_t serial) {
59     mAtChannel->queueRequester([this, serial]
60                                (const AtChannel::RequestPipe requestPipe) -> bool {
61         requestPipe(atCmds::conference);
62         NOT_NULL(mRadioVoiceResponse)->conferenceResponse(
63             makeRadioResponseInfo(serial));
64         return true;
65     });
66 
67     return ScopedAStatus::ok();
68 }
69 
dial(const int32_t serial,const voice::Dial & dialInfo)70 ScopedAStatus RadioVoice::dial(const int32_t serial,
71                                const voice::Dial& dialInfo) {
72     static const char* const kFunc = __func__;
73     mAtChannel->queueRequester([this, serial, dialInfo]
74                                (const AtChannel::RequestPipe requestPipe) -> bool {
75         using namespace std::literals;
76         using CmeError = AtResponse::CmeError;
77         using voice::Dial;
78 
79         RadioError status = RadioError::NONE;
80 
81         std::string_view clir;
82         switch (dialInfo.clir) {
83         case Dial::CLIR_INVOCATION:
84             clir = "I"sv;
85             break;
86         case Dial::CLIR_SUPPRESSION:
87             clir = "i"sv;
88             break;
89         default:
90         case Dial::CLIR_DEFAULT:
91             // clir is the empty string
92             break;
93         }
94 
95         const std::string request = std::format("ATD{0:s}{1:s};",
96             dialInfo.address, clir);
97 
98         const AtResponsePtr response =
99             mAtConversation(requestPipe, request,
100                             [](const AtResponse& response) -> bool {
101                                return response.isOK() || response.holds<CmeError>();
102                             });
103         if (!response || response->isParseError()) {
104             status = FAILURE(RadioError::INTERNAL_ERR);
105         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
106             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
107         } else if (!response->isOK()) {
108             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
109         }
110 
111         NOT_NULL(mRadioVoiceResponse)->dialResponse(
112             makeRadioResponseInfo(serial, status));
113         return status != RadioError::INTERNAL_ERR;
114     });
115 
116     return ScopedAStatus::ok();
117 }
118 
emergencyDial(const int32_t serial,const voice::Dial & dialInfo,const int32_t categories,const std::vector<std::string> &,const voice::EmergencyCallRouting routing,const bool,const bool)119 ScopedAStatus RadioVoice::emergencyDial(const int32_t serial,
120                                         const voice::Dial& dialInfo,
121                                         const int32_t categories,
122                                         const std::vector<std::string>& /*urns*/,
123                                         const voice::EmergencyCallRouting routing,
124                                         const bool /*hasKnownUserIntentEmergency*/,
125                                         const bool /*isTesting*/) {
126     static const char* const kFunc = __func__;
127     mAtChannel->queueRequester([this, serial, dialInfo, categories, routing]
128                                (const AtChannel::RequestPipe requestPipe) -> bool {
129         using namespace std::literals;
130         using CmeError = AtResponse::CmeError;
131         using voice::Dial;
132         using voice::EmergencyCallRouting;
133 
134         RadioError status = RadioError::NONE;
135 
136         std::string_view clir;
137         switch (dialInfo.clir) {
138         case Dial::CLIR_INVOCATION:
139             clir = "I"sv;
140             break;
141         case Dial::CLIR_SUPPRESSION:
142             clir = "i"sv;
143             break;
144         default:
145         case Dial::CLIR_DEFAULT:
146             // clir is the empty string
147             break;
148         }
149 
150         std::string request;
151         switch (routing) {
152         case EmergencyCallRouting::EMERGENCY:
153         case EmergencyCallRouting::UNKNOWN:
154             if (categories) {
155                 request = std::format("ATD{0:s}@{1:d},#{2:s};",
156                                       dialInfo.address, categories, clir);
157             } else {
158                 request = std::format("ATD{0:s}@,#{1:s};", dialInfo.address, clir);
159             }
160             break;
161 
162         default:
163         case EmergencyCallRouting::NORMAL:
164             request = std::format("ATD{0:s}{1:s};", dialInfo.address, clir);
165             break;
166         }
167 
168         const AtResponsePtr response =
169             mAtConversation(requestPipe, request,
170                             [](const AtResponse& response) -> bool {
171                                return response.isOK() || response.holds<CmeError>();
172                             });
173         if (!response || response->isParseError()) {
174             status = FAILURE(RadioError::INTERNAL_ERR);
175         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
176             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
177         } else if (!response->isOK()) {
178             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
179         }
180 
181         NOT_NULL(mRadioVoiceResponse)->emergencyDialResponse(
182             makeRadioResponseInfo(serial, status));
183         return status != RadioError::INTERNAL_ERR;
184     });
185 
186     return ScopedAStatus::ok();
187 }
188 
exitEmergencyCallbackMode(const int32_t serial)189 ScopedAStatus RadioVoice::exitEmergencyCallbackMode(const int32_t serial) {
190     static const char* const kFunc = __func__;
191     mAtChannel->queueRequester([this, serial]
192                                (const AtChannel::RequestPipe requestPipe) -> bool {
193         using CmeError = AtResponse::CmeError;
194 
195         RadioError status = RadioError::NONE;
196 
197         const AtResponsePtr response =
198             mAtConversation(requestPipe, atCmds::exitEmergencyMode,
199                             [](const AtResponse& response) -> bool {
200                                return response.isOK() || response.holds<CmeError>();
201                             });
202         if (!response || response->isParseError()) {
203             status = FAILURE(RadioError::INTERNAL_ERR);
204         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
205             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
206         } else if (!response->isOK()) {
207             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
208         }
209 
210         NOT_NULL(mRadioVoiceResponse)->exitEmergencyCallbackModeResponse(
211             makeRadioResponseInfo(serial, status));
212         return status != RadioError::INTERNAL_ERR;
213     });
214 
215     return ScopedAStatus::ok();
216 }
217 
explicitCallTransfer(const int32_t serial)218 ScopedAStatus RadioVoice::explicitCallTransfer(const int32_t serial) {
219     // matches reference-ril.c
220     NOT_NULL(mRadioVoiceResponse)->explicitCallTransferResponse(
221         makeRadioResponseInfoUnsupported(
222             serial, FAILURE_DEBUG_PREFIX, __func__));
223     return ScopedAStatus::ok();
224 }
225 
getCallForwardStatus(const int32_t serial,const voice::CallForwardInfo & callInfo)226 ScopedAStatus RadioVoice::getCallForwardStatus(const int32_t serial,
227                                                const voice::CallForwardInfo& callInfo) {
228     static const char* const kFunc = __func__;
229     mAtChannel->queueRequester([this, serial, callInfo](const AtChannel::RequestPipe requestPipe) -> bool {
230         using CCFCU = AtResponse::CCFCU;
231         using CmeError = AtResponse::CmeError;
232         using voice::CallForwardInfo;
233 
234         RadioError status = RadioError::NONE;
235         std::vector<CallForwardInfo> callForwardInfos;
236 
237         const std::string request = std::format(
238                 "AT+CCFCU={0:d},{1:d},{2:d},{3:d},\"{4:s}\",{5:d}",
239                 callInfo.reason, 2, 2, callInfo.toa,
240                 callInfo.number, callInfo.serviceClass);
241 
242         const AtResponsePtr response =
243             mAtConversation(requestPipe, request,
244                             [](const AtResponse& response) -> bool {
245                                return response.holds<CCFCU>() ||
246                                       response.isOK() ||
247                                       response.holds<CmeError>();
248                             });
249         if (!response || response->isParseError()) {
250             status = FAILURE(RadioError::INTERNAL_ERR);
251         } else if (const CCFCU* ccfcu = response->get_if<CCFCU>()) {
252             callForwardInfos = ccfcu->callForwardInfos;
253         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
254             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
255         } else if (!response->isOK()) {
256             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
257         }
258 
259         NOT_NULL(mRadioVoiceResponse)->getCallForwardStatusResponse(
260                 makeRadioResponseInfo(serial, status),
261                 std::move(callForwardInfos));
262         return status != RadioError::INTERNAL_ERR;
263     });
264 
265     return ScopedAStatus::ok();
266 }
267 
getCallWaiting(const int32_t serial,const int32_t serviceClass)268 ScopedAStatus RadioVoice::getCallWaiting(const int32_t serial,
269                                          const int32_t serviceClass) {
270     static const char* const kFunc = __func__;
271     mAtChannel->queueRequester([this, serial, serviceClass]
272                                (const AtChannel::RequestPipe requestPipe) -> bool {
273         using CCWA = AtResponse::CCWA;
274         using CmeError = AtResponse::CmeError;
275 
276         RadioError status = RadioError::NONE;
277         bool enable = false;
278         int serviceClassOut = -1;
279 
280         const std::string request =
281             std::format("AT+CCWA={0:d},{1:d},{2:d}",
282                         1, 2, serviceClass);
283         const AtResponsePtr response =
284             mAtConversation(requestPipe, request,
285                             [](const AtResponse& response) -> bool {
286                                return response.holds<CCWA>() ||
287                                       response.holds<CmeError>();
288                             });
289         if (!response || response->isParseError()) {
290             status = FAILURE(RadioError::INTERNAL_ERR);
291         } else if (const CCWA* ccwa = response->get_if<CCWA>()) {
292             enable = ccwa->enable;
293             serviceClassOut = ccwa->serviceClass;
294         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
295             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
296         } else {
297             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
298         }
299 
300         NOT_NULL(mRadioVoiceResponse)->getCallWaitingResponse(
301             makeRadioResponseInfo(serial, status), enable, serviceClassOut);
302         return status != RadioError::INTERNAL_ERR;
303     });
304 
305     return ScopedAStatus::ok();
306 }
307 
getClip(const int32_t serial)308 ScopedAStatus RadioVoice::getClip(const int32_t serial) {
309     static const char* const kFunc = __func__;
310     mAtChannel->queueRequester([this, serial]
311                                (const AtChannel::RequestPipe requestPipe) -> bool {
312         using CLIP = AtResponse::CLIP;
313         using CmeError = AtResponse::CmeError;
314         using ClipStatus = voice::ClipStatus;
315 
316         RadioError status = RadioError::NONE;
317         ClipStatus clipStatus = ClipStatus::UNKNOWN;
318 
319         const AtResponsePtr response =
320             mAtConversation(requestPipe, atCmds::getClip,
321                             [](const AtResponse& response) -> bool {
322                                return response.holds<CLIP>() ||
323                                       response.holds<CmeError>();
324                             });
325         if (!response || response->isParseError()) {
326             status = FAILURE(RadioError::INTERNAL_ERR);
327         } else if (const CLIP* clip = response->get_if<CLIP>()) {
328             clipStatus = clip->status;
329         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
330             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
331         } else {
332             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
333         }
334 
335         NOT_NULL(mRadioVoiceResponse)->getClipResponse(
336             makeRadioResponseInfo(serial, status), clipStatus);
337         return status != RadioError::INTERNAL_ERR;
338     });
339 
340     return ScopedAStatus::ok();
341 }
342 
getClir(const int32_t serial)343 ScopedAStatus RadioVoice::getClir(const int32_t serial) {
344     static const char* const kFunc = __func__;
345     mAtChannel->queueRequester([this, serial]
346                                (const AtChannel::RequestPipe requestPipe) -> bool {
347         using CLIR = AtResponse::CLIR;
348         using CmeError = AtResponse::CmeError;
349 
350         RadioError status = RadioError::NONE;
351         int n = -1;
352         int m = -1;
353 
354         const AtResponsePtr response =
355             mAtConversation(requestPipe, atCmds::getClir,
356                             [](const AtResponse& response) -> bool {
357                                return response.holds<CLIR>() ||
358                                       response.holds<CmeError>();
359                             });
360         if (!response || response->isParseError()) {
361             status = FAILURE(RadioError::INTERNAL_ERR);
362         } else if (const CLIR* clir = response->get_if<CLIR>()) {
363             n = clir->n;
364             m = clir->m;
365         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
366             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
367         } else {
368             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
369         }
370 
371         NOT_NULL(mRadioVoiceResponse)->getClirResponse(
372             makeRadioResponseInfo(serial, status), n, m);
373         return status != RadioError::INTERNAL_ERR;
374     });
375 
376     return ScopedAStatus::ok();
377 }
378 
getCurrentCalls(const int32_t serial)379 ScopedAStatus RadioVoice::getCurrentCalls(const int32_t serial) {
380     static const char* const kFunc = __func__;
381     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
382         using CLCC = AtResponse::CLCC;
383         using CmeError = AtResponse::CmeError;
384 
385         RadioError status = RadioError::NONE;
386         std::vector<voice::Call> calls;
387 
388         const AtResponsePtr response =
389             mAtConversation(requestPipe, atCmds::getCurrentCalls,
390                             [](const AtResponse& response) -> bool {
391                                return response.holds<CLCC>() ||
392                                       response.isOK() ||
393                                       response.holds<CmeError>();
394                             });
395         if (!response || response->isParseError()) {
396             status = FAILURE(RadioError::INTERNAL_ERR);
397         } else if (const CLCC* clcc = response->get_if<CLCC>()) {
398             calls = clcc->calls;
399         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
400             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
401         } else if (!response->isOK()) {
402             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
403         }
404 
405         NOT_NULL(mRadioVoiceResponse)->getCurrentCallsResponse(
406             makeRadioResponseInfo(serial, status), std::move(calls));
407         return status != RadioError::INTERNAL_ERR;
408     });
409 
410     return ScopedAStatus::ok();
411 }
412 
getLastCallFailCause(const int32_t serial)413 ScopedAStatus RadioVoice::getLastCallFailCause(const int32_t serial) {
414     // matches reference-ril.c
415     NOT_NULL(mRadioVoiceResponse)->getLastCallFailCauseResponse(
416         makeRadioResponseInfoUnsupported(
417             serial, FAILURE_DEBUG_PREFIX, __func__), {});
418     return ScopedAStatus::ok();
419 }
420 
getMute(const int32_t serial)421 ScopedAStatus RadioVoice::getMute(const int32_t serial) {
422     static const char* const kFunc = __func__;
423     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
424         using CMUT = AtResponse::CMUT;
425         using CmeError = AtResponse::CmeError;
426 
427         RadioError status = RadioError::NONE;
428         bool isMuted = false;
429 
430         const AtResponsePtr response =
431             mAtConversation(requestPipe, atCmds::getCurrentCalls,
432                             [](const AtResponse& response) -> bool {
433                                return response.holds<CMUT>() ||
434                                       response.holds<CmeError>();
435                             });
436         if (!response || response->isParseError()) {
437              NOT_NULL(mRadioVoiceResponse)->getCurrentCallsResponse(
438                     makeRadioResponseInfo(serial, FAILURE(RadioError::INTERNAL_ERR)), {});
439             return false;
440         } else if (const CMUT* cmut = response->get_if<CMUT>()) {
441             isMuted = cmut->on;
442         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
443             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
444         } else if (!response->isOK()) {
445             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
446         }
447 
448 
449         NOT_NULL(mRadioVoiceResponse)->getMuteResponse(
450             makeRadioResponseInfo(serial, status), isMuted);
451         return status != RadioError::INTERNAL_ERR;
452     });
453 
454     return ScopedAStatus::ok();
455 }
456 
getPreferredVoicePrivacy(const int32_t serial)457 ScopedAStatus RadioVoice::getPreferredVoicePrivacy(const int32_t serial) {
458     // matches reference-ril.c
459     NOT_NULL(mRadioVoiceResponse)->getPreferredVoicePrivacyResponse(
460         makeRadioResponseInfoUnsupported(
461             serial, FAILURE_DEBUG_PREFIX, __func__), false);
462     return ScopedAStatus::ok();
463 }
464 
getTtyMode(const int32_t serial)465 ScopedAStatus RadioVoice::getTtyMode(const int32_t serial) {
466     NOT_NULL(mRadioVoiceResponse)->getTtyModeResponse(
467         makeRadioResponseInfo(serial), voice::TtyMode::FULL);
468     return ScopedAStatus::ok();
469 }
470 
handleStkCallSetupRequestFromSim(const int32_t serial,const bool)471 ScopedAStatus RadioVoice::handleStkCallSetupRequestFromSim(const int32_t serial,
472                                                            const bool /*accept*/) {
473     // matches reference-ril.c
474     NOT_NULL(mRadioVoiceResponse)->handleStkCallSetupRequestFromSimResponse(
475         makeRadioResponseInfoUnsupported(
476             serial, FAILURE_DEBUG_PREFIX, __func__));
477     return ScopedAStatus::ok();
478 }
479 
hangup(const int32_t serial,const int32_t gsmIndex)480 ScopedAStatus RadioVoice::hangup(const int32_t serial,
481                                  const int32_t gsmIndex) {
482     static const char* const kFunc = __func__;
483     mAtChannel->queueRequester([this, serial, gsmIndex]
484                                (const AtChannel::RequestPipe requestPipe) -> bool {
485         requestPipe(std::format("AT+CHLD=1{0:d}", gsmIndex));
486         NOT_NULL(mRadioVoiceResponse)->hangupConnectionResponse(
487             makeRadioResponseInfo(serial));
488         return true;
489     });
490 
491     return ScopedAStatus::ok();
492 }
493 
hangupForegroundResumeBackground(const int32_t serial)494 ScopedAStatus RadioVoice::hangupForegroundResumeBackground(const int32_t serial) {
495     mAtChannel->queueRequester([this, serial]
496                                (const AtChannel::RequestPipe requestPipe) -> bool {
497         requestPipe(atCmds::hangupForeground);
498         NOT_NULL(mRadioVoiceResponse)->hangupForegroundResumeBackgroundResponse(
499             makeRadioResponseInfo(serial));
500         return true;
501     });
502 
503     return ScopedAStatus::ok();
504 }
505 
hangupWaitingOrBackground(const int32_t serial)506 ScopedAStatus RadioVoice::hangupWaitingOrBackground(const int32_t serial) {
507     mAtChannel->queueRequester([this, serial]
508                                (const AtChannel::RequestPipe requestPipe) -> bool {
509         requestPipe(atCmds::hangupWaiting);
510         NOT_NULL(mRadioVoiceResponse)->hangupWaitingOrBackgroundResponse(
511             makeRadioResponseInfo(serial));
512         return true;
513     });
514 
515     return ScopedAStatus::ok();
516 }
517 
isVoNrEnabled(const int32_t serial)518 ScopedAStatus RadioVoice::isVoNrEnabled(const int32_t serial) {
519     NOT_NULL(mRadioVoiceResponse)->isVoNrEnabledResponse(
520             makeRadioResponseInfoNOP(serial), false);
521     return ScopedAStatus::ok();
522 }
523 
rejectCall(const int32_t serial)524 ScopedAStatus RadioVoice::rejectCall(const int32_t serial) {
525     mAtChannel->queueRequester([this, serial]
526                                (const AtChannel::RequestPipe requestPipe) -> bool {
527         requestPipe(atCmds::rejectCall);
528         NOT_NULL(mRadioVoiceResponse)->rejectCallResponse(
529             makeRadioResponseInfo(serial));
530         return true;
531     });
532 
533     return ScopedAStatus::ok();
534 }
535 
sendBurstDtmf(const int32_t serial,const std::string &,const int32_t,const int32_t)536 ScopedAStatus RadioVoice::sendBurstDtmf(const int32_t serial,
537                                         const std::string& /*dtmf*/,
538                                         const int32_t /*on*/,
539                                         const int32_t /*off*/) {
540     // matches reference-ril.c
541     NOT_NULL(mRadioVoiceResponse)->sendBurstDtmfResponse(
542         makeRadioResponseInfoUnsupported(
543             serial, FAILURE_DEBUG_PREFIX, __func__));
544     return ScopedAStatus::ok();
545 }
546 
sendCdmaFeatureCode(const int32_t serial,const std::string &)547 ScopedAStatus RadioVoice::sendCdmaFeatureCode(const int32_t serial,
548                                               const std::string& /*fcode*/) {
549     // matches reference-ril.c
550     NOT_NULL(mRadioVoiceResponse)->sendCdmaFeatureCodeResponse(
551         makeRadioResponseInfoUnsupported(
552             serial, FAILURE_DEBUG_PREFIX, __func__));
553     return ScopedAStatus::ok();
554 }
555 
sendDtmf(const int32_t serial,const std::string & s)556 ScopedAStatus RadioVoice::sendDtmf(const int32_t serial,
557                                    const std::string& s) {
558     static const char* const kFunc = __func__;
559     mAtChannel->queueRequester([this, serial, s]
560                                (const AtChannel::RequestPipe requestPipe) -> bool {
561         requestPipe(std::format("AT+VTS={0:s}", s));
562         NOT_NULL(mRadioVoiceResponse)->sendDtmfResponse(
563             makeRadioResponseInfo(serial));
564         return true;
565     });
566 
567     return ScopedAStatus::ok();
568 }
569 
sendUssd(const int32_t serial,const std::string & ussd)570 ScopedAStatus RadioVoice::sendUssd(const int32_t serial,
571                                    const std::string& ussd) {
572     static const char* const kFunc = __func__;
573     mAtChannel->queueRequester([this, serial, ussd]
574                                (const AtChannel::RequestPipe requestPipe) -> bool {
575         requestPipe(std::format("AT+CUSD=1,\"%s\"", ussd));
576         NOT_NULL(mRadioVoiceResponse)->sendUssdResponse(
577             makeRadioResponseInfo(serial));
578         return true;
579     });
580 
581     return ScopedAStatus::ok();
582 }
583 
separateConnection(const int32_t serial,const int32_t gsmIndex)584 ScopedAStatus RadioVoice::separateConnection(const int32_t serial,
585                                              const int32_t gsmIndex) {
586     static const char* const kFunc = __func__;
587     mAtChannel->queueRequester([this, serial, gsmIndex]
588                                (const AtChannel::RequestPipe requestPipe) -> bool {
589         if ((gsmIndex > 0) && (gsmIndex < 10)) {
590             requestPipe(std::format("AT+CHLD=2{0:d}", gsmIndex));
591             NOT_NULL(mRadioVoiceResponse)->separateConnectionResponse(
592                 makeRadioResponseInfo(serial));
593         } else {
594             NOT_NULL(mRadioVoiceResponse)->separateConnectionResponse(
595                 makeRadioResponseInfo(serial, FAILURE(RadioError::GENERIC_FAILURE)));
596         }
597 
598         return true;
599     });
600 
601     return ScopedAStatus::ok();
602 }
603 
setCallForward(const int32_t serial,const voice::CallForwardInfo & callInfo)604 ScopedAStatus RadioVoice::setCallForward(const int32_t serial,
605                                          const voice::CallForwardInfo& callInfo) {
606     static const char* const kFunc = __func__;
607     mAtChannel->queueRequester([this, serial, callInfo](const AtChannel::RequestPipe requestPipe) -> bool {
608         using CmeError = AtResponse::CmeError;
609 
610         RadioError status = RadioError::NONE;
611 
612         std::string request = std::format(
613                 "AT+CCFCU={0:d},{1:d},{2:d},{3:d},\"{4:s}\",{5:d}",
614                 callInfo.reason, callInfo.status, 2, callInfo.toa,
615                 callInfo.number, callInfo.serviceClass);
616         if ((callInfo.timeSeconds > 0) && (callInfo.status == 3)) {
617             request += std::format(",\"\",\"\",,{0:d}", callInfo.timeSeconds);
618         } else if (callInfo.serviceClass) {
619             request += ",\"\"";
620         }
621 
622         const AtResponsePtr response =
623             mAtConversation(requestPipe, request,
624                             [](const AtResponse& response) -> bool {
625                                return response.isOK() ||
626                                       response.holds<CmeError>();
627                             });
628         if (!response || response->isParseError()) {
629             status = FAILURE(RadioError::INTERNAL_ERR);
630         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
631             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
632         } else if (!response->isOK()) {
633             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
634         }
635 
636         NOT_NULL(mRadioVoiceResponse)->setCallForwardResponse(
637                 makeRadioResponseInfo(serial, status));
638         return status != RadioError::INTERNAL_ERR;
639     });
640 
641     return ScopedAStatus::ok();
642 }
643 
setCallWaiting(const int32_t serial,const bool enable,const int32_t serviceClass)644 ScopedAStatus RadioVoice::setCallWaiting(const int32_t serial,
645                                          const bool enable,
646                                          const int32_t serviceClass) {
647     static const char* const kFunc = __func__;
648     mAtChannel->queueRequester([this, serial, enable, serviceClass]
649                                (const AtChannel::RequestPipe requestPipe) -> bool {
650         using CmeError = AtResponse::CmeError;
651 
652         RadioError status = RadioError::NONE;
653 
654         const std::string request =
655             std::format("AT+CCWA={0:d},{1:d},{2:d}", 1, (enable ? 1 : 0),
656                         serviceClass);
657         const AtResponsePtr response =
658             mAtConversation(requestPipe, request,
659                             [](const AtResponse& response) -> bool {
660                                return response.isOK() ||
661                                       response.holds<CmeError>();
662                             });
663         if (!response || response->isParseError()) {
664             status = FAILURE(RadioError::INTERNAL_ERR);
665         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
666             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
667         } else if (!response->isOK()) {
668             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
669         }
670 
671         NOT_NULL(mRadioVoiceResponse)->setCallWaitingResponse(
672                 makeRadioResponseInfo(serial, status));
673         return status != RadioError::INTERNAL_ERR;
674     });
675 
676 
677     return ScopedAStatus::ok();
678 }
679 
setClir(const int32_t serial,const int32_t clirStatus)680 ScopedAStatus RadioVoice::setClir(const int32_t serial, const int32_t clirStatus) {
681     static const char* const kFunc = __func__;
682     mAtChannel->queueRequester([this, serial, clirStatus]
683                                (const AtChannel::RequestPipe requestPipe) -> bool {
684         using CmeError = AtResponse::CmeError;
685 
686         RadioError status = RadioError::NONE;
687 
688         const std::string request = std::format("AT+CLIR: {0:d}", clirStatus);
689         const AtResponsePtr response =
690             mAtConversation(requestPipe, request,
691                             [](const AtResponse& response) -> bool {
692                                return response.isOK() ||
693                                       response.holds<CmeError>();
694                             });
695         if (!response || response->isParseError()) {
696             status = FAILURE(RadioError::INTERNAL_ERR);
697         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
698             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
699         } else if (!response->isOK()) {
700             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
701         }
702 
703         NOT_NULL(mRadioVoiceResponse)->setClirResponse(
704                 makeRadioResponseInfo(serial, status));
705         return status != RadioError::INTERNAL_ERR;
706     });
707 
708     return ScopedAStatus::ok();
709 }
710 
setMute(const int32_t serial,const bool enable)711 ScopedAStatus RadioVoice::setMute(const int32_t serial,
712                                   const bool enable) {
713     static const char* const kFunc = __func__;
714     mAtChannel->queueRequester([this, serial, enable]
715                                (const AtChannel::RequestPipe requestPipe) -> bool {
716         using CmeError = AtResponse::CmeError;
717         RadioError status = RadioError::NONE;
718 
719         const std::string request =
720             std::format("AT+CMUT={0:d}", (enable ? 1 : 0));
721         const AtResponsePtr response =
722             mAtConversation(requestPipe, request,
723                             [](const AtResponse& response) -> bool {
724                                return response.isOK() ||
725                                       response.holds<CmeError>();
726                             });
727         if (!response || response->isParseError()) {
728              NOT_NULL(mRadioVoiceResponse)->getCurrentCallsResponse(
729                     makeRadioResponseInfo(serial, FAILURE(RadioError::INTERNAL_ERR)), {});
730             return false;
731         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
732             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
733         } else if (!response->isOK()) {
734             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
735         }
736 
737         NOT_NULL(mRadioVoiceResponse)->setMuteResponse(
738             makeRadioResponseInfo(serial, status));
739         return status != RadioError::INTERNAL_ERR;
740     });
741 
742     return ScopedAStatus::ok();
743 }
744 
setPreferredVoicePrivacy(const int32_t serial,const bool)745 ScopedAStatus RadioVoice::setPreferredVoicePrivacy(const int32_t serial,
746                                                    const bool /*enable*/) {
747     // matches reference-ril.c
748     NOT_NULL(mRadioVoiceResponse)->setPreferredVoicePrivacyResponse(
749         makeRadioResponseInfoNOP(serial));
750     return ScopedAStatus::ok();
751 }
752 
setTtyMode(const int32_t serial,voice::TtyMode)753 ScopedAStatus RadioVoice::setTtyMode(const int32_t serial, voice::TtyMode /*mode*/) {
754     NOT_NULL(mRadioVoiceResponse)->setTtyModeResponse(
755         makeRadioResponseInfoNOP(serial));
756     return ScopedAStatus::ok();
757 }
758 
setVoNrEnabled(const int32_t serial,const bool enable)759 ScopedAStatus RadioVoice::setVoNrEnabled(const int32_t serial, const bool enable) {
760     // matches reference-ril.c
761     NOT_NULL(mRadioVoiceResponse)->setVoNrEnabledResponse(
762         makeRadioResponseInfo(serial, enable ?
763             FAILURE(RadioError::REQUEST_NOT_SUPPORTED) : RadioError::NONE));
764     return ScopedAStatus::ok();
765 }
766 
startDtmf(const int32_t serial,const std::string &)767 ScopedAStatus RadioVoice::startDtmf(const int32_t serial, const std::string& /*s*/) {
768     // matches reference-ril.c
769     NOT_NULL(mRadioVoiceResponse)->startDtmfResponse(
770         makeRadioResponseInfoUnsupported(
771             serial, FAILURE_DEBUG_PREFIX, __func__));
772     return ScopedAStatus::ok();
773 }
774 
stopDtmf(const int32_t serial)775 ScopedAStatus RadioVoice::stopDtmf(const int32_t serial) {
776     // matches reference-ril.c
777     NOT_NULL(mRadioVoiceResponse)->stopDtmfResponse(
778         makeRadioResponseInfoUnsupported(
779             serial, FAILURE_DEBUG_PREFIX, __func__));
780     return ScopedAStatus::ok();
781 }
782 
switchWaitingOrHoldingAndActive(const int32_t serial)783 ScopedAStatus RadioVoice::switchWaitingOrHoldingAndActive(const int32_t serial) {
784     mAtChannel->queueRequester([this, serial]
785                                (const AtChannel::RequestPipe requestPipe) -> bool {
786         requestPipe(atCmds::switchWaiting);
787         NOT_NULL(mRadioVoiceResponse)->switchWaitingOrHoldingAndActiveResponse(
788             makeRadioResponseInfo(serial));
789         return true;
790     });
791     return ScopedAStatus::ok();
792 }
793 
atResponseSink(const AtResponsePtr & response)794 void RadioVoice::atResponseSink(const AtResponsePtr& response) {
795     if (!mAtConversation.send(response)) {
796         response->visit([this](const auto& msg){ handleUnsolicited(msg); });
797     }
798 }
799 
handleUnsolicited(const AtResponse::RING &)800 void RadioVoice::handleUnsolicited(const AtResponse::RING&) {
801     if (mRadioVoiceIndication) {
802         mRadioVoiceIndication->callRing(RadioIndicationType::UNSOLICITED, true, {});
803         mRadioVoiceIndication->callStateChanged(RadioIndicationType::UNSOLICITED);
804     }
805 }
806 
handleUnsolicited(const AtResponse::WSOS & wsos)807 void RadioVoice::handleUnsolicited(const AtResponse::WSOS& wsos) {
808     if (mRadioVoiceIndication) {
809         if (wsos.isEmergencyMode) {
810             mRadioVoiceIndication->enterEmergencyCallbackMode(
811                 RadioIndicationType::UNSOLICITED);
812         } else {
813             mRadioVoiceIndication->exitEmergencyCallbackMode(
814                 RadioIndicationType::UNSOLICITED);
815         }
816     }
817 }
818 
responseAcknowledgement()819 ScopedAStatus RadioVoice::responseAcknowledgement() {
820     return ScopedAStatus::ok();
821 }
822 
setResponseFunctions(const std::shared_ptr<voice::IRadioVoiceResponse> & radioVoiceResponse,const std::shared_ptr<voice::IRadioVoiceIndication> & radioVoiceIndication)823 ScopedAStatus RadioVoice::setResponseFunctions(
824         const std::shared_ptr<voice::IRadioVoiceResponse>& radioVoiceResponse,
825         const std::shared_ptr<voice::IRadioVoiceIndication>& radioVoiceIndication) {
826     mRadioVoiceResponse = NOT_NULL(radioVoiceResponse);
827     mRadioVoiceIndication = NOT_NULL(radioVoiceIndication);
828     return ScopedAStatus::ok();
829 }
830 
831 }  // namespace implementation
832 }  // namespace radio
833 }  // namespace hardware
834 }  // namespace android
835 }  // namespace aidl
836