• 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 "RadioSim"
18 
19 #include <charconv>
20 #include <format>
21 #include <tuple>
22 #include <vector>
23 
24 #include "RadioSim.h"
25 
26 #include "atCmds.h"
27 #include "debug.h"
28 #include "hexbin.h"
29 #include "makeRadioResponseInfo.h"
30 
31 namespace aidl {
32 namespace android {
33 namespace hardware {
34 namespace radio {
35 namespace implementation {
36 namespace {
37 using namespace std::literals;
38 
39 enum class AuthContext {
40     SIM = 128,
41     AKA = 129,
42 };
43 
44 enum class StkCmdType {
45     RUN_AT        = 0x34,
46     SEND_DTMF     = 0x14,
47     SEND_SMS      = 0x13,
48     SEND_SS       = 0x11,
49     SEND_USSD     = 0x12,
50     PLAY_TONE     = 0x20,
51     OPEN_CHANNEL  = 0x40,
52     CLOSE_CHANNEL = 0x41,
53     RECEIVE_DATA  = 0x42,
54     SEND_DATA     = 0x43,
55     GET_CHANNEL_STATUS = 0x44,
56     REFRESH       = 0x01,
57 };
58 
59 #define USIM_DATA_OFFSET_2                      2
60 #define USIM_DATA_OFFSET_3                      3
61 #define USIM_RESPONSE_DATA_FILE_RECORD_LEN_1         6
62 #define USIM_RESPONSE_DATA_FILE_RECORD_LEN_2         7
63 #define USIM_TYPE_FILE_DES_LEN                       5
64 
65 #define USIM_RESPONSE_DATA_FILE_DES_FLAG             2
66 #define USIM_RESPONSE_DATA_FILE_DES_LEN_FLAG         3
67 
68 #define USIM_FILE_DES_TAG                       0x82
69 #define USIM_FILE_SIZE_TAG                      0x80
70 
71 
72 #define SIM_RESPONSE_EF_SIZE                        15
73 #define SIM_RESPONSE_DATA_FILE_SIZE_1               2
74 #define SIM_RESPONSE_DATA_FILE_SIZE_2               3
75 #define SIM_RESPONSE_DATA_FILE_TYPE                 6
76 #define SIM_RESPONSE_DATA_STRUCTURE                 13
77 #define SIM_RESPONSE_DATA_RECORD_LENGTH             14
78 #define SIM_TYPE_EF                                 4
79 
80 enum class UsimEfType {
81     TRANSPARENT = 1,
82     LINEAR_FIXED = 2,
83     CYCLIC = 6,
84 };
85 
86 // 62 17 82 02 41 2183022FE28A01058B032F06038002000A880110
convertUsimToSim(const std::vector<uint8_t> & bytesUSIM,std::string * hexSIM)87 bool convertUsimToSim(const std::vector<uint8_t>& bytesUSIM, std::string* hexSIM) {
88     const size_t sz = bytesUSIM.size();
89     size_t i = 0;
90 
91     size_t desIndex;
92     while (true) {
93         if (bytesUSIM[i] == USIM_FILE_DES_TAG) {
94             desIndex = i;
95             break;
96         } else {
97             ++i;
98             if (i >= sz) {
99                 return false;
100             }
101         }
102     }
103 
104     size_t sizeIndex;
105     while (true) {
106         if (bytesUSIM[i] == USIM_FILE_SIZE_TAG) {
107             sizeIndex = i;
108             break;
109         } else {
110             i += bytesUSIM[i + 1] + 2;
111             if (i >= sz) {
112                 return FAILURE(false);
113             }
114         }
115     }
116 
117     uint8_t bytesSIM[SIM_RESPONSE_EF_SIZE] = {0};
118     switch (static_cast<UsimEfType>(bytesUSIM[desIndex + USIM_RESPONSE_DATA_FILE_DES_FLAG] & 0x07)) {
119     case UsimEfType::TRANSPARENT:
120         bytesSIM[SIM_RESPONSE_DATA_STRUCTURE] = 0;
121         break;
122 
123     case UsimEfType::LINEAR_FIXED:
124         if (USIM_FILE_DES_TAG != bytesUSIM[USIM_RESPONSE_DATA_FILE_DES_FLAG]) {
125             return FAILURE(false);
126         }
127         if (USIM_TYPE_FILE_DES_LEN != bytesUSIM[USIM_RESPONSE_DATA_FILE_DES_LEN_FLAG]) {
128             return FAILURE(false);
129         }
130 
131         bytesSIM[SIM_RESPONSE_DATA_STRUCTURE] = 1;
132         bytesSIM[SIM_RESPONSE_DATA_RECORD_LENGTH] =
133                 //(byteUSIM[USIM_RESPONSE_DATA_FILE_RECORD_LEN_1] << 8) +
134                 bytesUSIM[USIM_RESPONSE_DATA_FILE_RECORD_LEN_2];
135         break;
136 
137     case UsimEfType::CYCLIC:
138         bytesSIM[SIM_RESPONSE_DATA_STRUCTURE] = 3;
139         bytesSIM[SIM_RESPONSE_DATA_RECORD_LENGTH] =
140                 //(byteUSIM[USIM_RESPONSE_DATA_FILE_RECORD_LEN_1] << 8) +
141                 bytesUSIM[USIM_RESPONSE_DATA_FILE_RECORD_LEN_2];
142         break;
143 
144     default:
145         return false;
146     }
147 
148     bytesSIM[SIM_RESPONSE_DATA_FILE_TYPE] = SIM_TYPE_EF;
149     bytesSIM[SIM_RESPONSE_DATA_FILE_SIZE_1] =
150             bytesUSIM[sizeIndex + USIM_DATA_OFFSET_2];
151     bytesSIM[SIM_RESPONSE_DATA_FILE_SIZE_2] =
152             bytesUSIM[sizeIndex + USIM_DATA_OFFSET_3];
153 
154     *hexSIM = bin2hex(bytesSIM, sizeof(bytesSIM));
155     return true;
156 }
157 
getRemainingRetries(const std::string_view pinType,const AtChannel::RequestPipe requestPipe,AtChannel::Conversation & atConversation)158 std::optional<int> getRemainingRetries(const std::string_view pinType,
159                                        const AtChannel::RequestPipe requestPipe,
160                                        AtChannel::Conversation& atConversation) {
161     using CPINR = AtResponse::CPINR;
162 
163     AtResponsePtr response =
164         atConversation(requestPipe, std::format("AT+CPINR=\"{0:s}\"", pinType),
165                        [](const AtResponse& response) -> bool {
166                           return response.holds<CPINR>();
167                        });
168     if (!response || response->isParseError()) {
169         return FAILURE(std::nullopt);
170     } else if (const CPINR* cpinr = response->get_if<CPINR>()) {
171         return cpinr->remainingRetryTimes;
172     } else {
173         response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
174     }
175 }
176 
enterOrChangeSimPinPuk(const bool change,const std::string_view oldPin,const std::string_view newPin,const std::string_view pinType,const AtChannel::RequestPipe requestPipe,AtChannel::Conversation & atConversation)177 std::pair<RadioError, int> enterOrChangeSimPinPuk(const bool change,
178                                                   const std::string_view oldPin,
179                                                   const std::string_view newPin,
180                                                   const std::string_view pinType,
181                                                   const AtChannel::RequestPipe requestPipe,
182                                                   AtChannel::Conversation& atConversation) {
183     using CmeError = AtResponse::CmeError;
184 
185     std::string request;
186     if (change) {
187         if (pinType.compare("SIM PIN2"sv) == 0) {
188             request = std::format("AT+CPWD=\"{0:s}\",\"{1:s}\",\"{2:s}\"",
189                                   "P2"sv, oldPin, newPin);
190         } else {
191             request = std::format("AT+CPIN={0:s},{1:s}", oldPin, newPin);
192         }
193     } else {
194         request = std::format("AT+CPIN={0:s}", oldPin);
195     }
196 
197     AtResponsePtr response =
198         atConversation(requestPipe, request,
199                        [](const AtResponse& response) -> bool {
200                           return response.holds<CmeError>() || response.isOK();
201                        });
202     if (!response || response->isParseError()) {
203         return {FAILURE(RadioError::INTERNAL_ERR), 0};
204     } else if (response->isOK()) {
205         return {RadioError::NONE, 0};
206     } else if (!response->get_if<CmeError>()) {
207         response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
208     }
209 
210     const std::optional<int> maybeRetries =
211         getRemainingRetries(pinType, requestPipe, atConversation);
212     if (maybeRetries) {
213         return {RadioError::PASSWORD_INCORRECT, maybeRetries.value()};
214     } else {
215         return {FAILURE(RadioError::INTERNAL_ERR), 0};
216     }
217 }
218 
219 // authData64 = base64([randLen][...rand...][authLen][...auth...])
220 std::tuple<RadioError, std::vector<uint8_t>, std::vector<uint8_t>>
parseAuthData(const AuthContext authContext,const std::string_view authData64)221 parseAuthData(const AuthContext authContext, const std::string_view authData64) {
222     auto maybeAuthData = base64decode(authData64.data(), authData64.size());
223     if (!maybeAuthData) {
224         return {FAILURE(RadioError::INVALID_ARGUMENTS), {}, {}};
225     }
226 
227     const std::vector<uint8_t> authData = std::move(maybeAuthData.value());
228     const size_t authDataSize = authData.size();
229     if (authDataSize == 0) {
230         return {FAILURE(RadioError::INVALID_ARGUMENTS), {}, {}};
231     }
232 
233     const size_t randLen = authData[0];
234     if (authDataSize < (1U + randLen)) {
235         return {FAILURE(RadioError::INVALID_ARGUMENTS), {}, {}};
236     }
237 
238     std::vector rand(&authData[1], &authData[1U + randLen]);
239     if (authContext == AuthContext::SIM) {
240         return {RadioError::NONE, std::move(rand), {}};
241     }
242 
243     const size_t authLen = authData[1U + randLen];
244     if (authDataSize < (1U + randLen + 1U + authLen)) {
245         return {FAILURE(RadioError::INVALID_ARGUMENTS), {}, {}};
246     }
247 
248     std::vector auth(&authData[1U + randLen + 1U],
249                      &authData[1U + randLen + 1U + authLen]);
250     if (authContext == AuthContext::AKA) {
251         return {RadioError::NONE, std::move(rand), std::move(auth)};
252     }
253 
254     return {FAILURE(RadioError::REQUEST_NOT_SUPPORTED), {}, {}};
255 }
256 
getSelectResponse(const AtChannel::RequestPipe requestPipe,AtChannel::Conversation & atConversation,const int channel,const int p2)257 std::optional<std::vector<uint8_t>> getSelectResponse(const AtChannel::RequestPipe requestPipe,
258                                                       AtChannel::Conversation& atConversation,
259                                                       const int channel, const int p2) {
260     using CGLA = AtResponse::CGLA;
261     using CmeError = AtResponse::CmeError;
262 
263     const std::string request =
264         std::format("AT+CGLA={0:d},14,00A400{1:02X}023F00", channel, p2);
265     AtResponsePtr response =
266         atConversation(requestPipe, request,
267                        [](const AtResponse& response) -> bool {
268                           return response.holds<CGLA>() || response.holds<CmeError>();
269                        });
270     if (!response || response->isParseError()) {
271         return FAILURE(std::nullopt);
272     } else if (const CGLA* cgla = response->get_if<CGLA>()) {
273         if (cgla->response.size() < 4) {
274             return FAILURE(std::nullopt);
275         }
276 
277         int sw12;
278         const size_t size4 = cgla->response.size() - 4;
279         if (1 != ::sscanf(&cgla->response[size4], "%04x", &sw12)) {
280             return FAILURE(std::nullopt);
281         }
282 
283         if (sw12 != 0x9000) {
284             return FAILURE(std::nullopt);
285         }
286 
287         std::vector<uint8_t> selectResponse;
288         if (!hex2bin(cgla->response, &selectResponse)) {
289             return FAILURE(std::nullopt);
290         }
291 
292         return selectResponse;
293     } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
294         cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, __func__, __LINE__);
295         return FAILURE(std::nullopt);
296     } else {
297         response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
298     }
299 }
300 
301 }  // namespace
302 
RadioSim(std::shared_ptr<AtChannel> atChannel)303 RadioSim::RadioSim(std::shared_ptr<AtChannel> atChannel) : mAtChannel(std::move(atChannel)) {
304 }
305 
areUiccApplicationsEnabled(const int32_t serial)306 ScopedAStatus RadioSim::areUiccApplicationsEnabled(const int32_t serial) {
307     using modem::RadioState;
308 
309     RadioState radioState;
310     {
311         std::lock_guard<std::mutex> lock(mMtx);
312         radioState = mRadioState;
313     }
314 
315     const RadioError status = (radioState == RadioState::ON) ?
316         RadioError::NONE : RadioError::RADIO_NOT_AVAILABLE;
317 
318     NOT_NULL(mRadioSimResponse)->areUiccApplicationsEnabledResponse(
319             makeRadioResponseInfo(serial, status), mUiccApplicationsEnabled);
320     return ScopedAStatus::ok();
321 }
322 
changeIccPin2ForApp(int32_t serial,const std::string & oldPin2,const std::string & newPin2,const std::string &)323 ScopedAStatus RadioSim::changeIccPin2ForApp(int32_t serial,
324                                             const std::string& oldPin2,
325                                             const std::string& newPin2,
326                                             const std::string& /*aid*/) {
327     mAtChannel->queueRequester([this, serial, oldPin2, newPin2]
328                                (const AtChannel::RequestPipe requestPipe) -> bool {
329         const auto [status, remainingRetries] =
330             enterOrChangeSimPinPuk(true, oldPin2, newPin2, "SIM PIN2"sv,
331                                    requestPipe, mAtConversation);
332 
333         NOT_NULL(mRadioSimResponse)->supplyIccPin2ForAppResponse(
334                 makeRadioResponseInfo(serial, status), remainingRetries);
335         return status != RadioError::INTERNAL_ERR;
336     });
337 
338     return ScopedAStatus::ok();
339 }
340 
changeIccPinForApp(const int32_t serial,const std::string & oldPin,const std::string & newPin,const std::string &)341 ScopedAStatus RadioSim::changeIccPinForApp(const int32_t serial,
342                                            const std::string& oldPin,
343                                            const std::string& newPin,
344                                            const std::string& /*aid*/) {
345     mAtChannel->queueRequester([this, serial, oldPin, newPin]
346                                (const AtChannel::RequestPipe requestPipe) -> bool {
347         const auto [status, remainingRetries] =
348             enterOrChangeSimPinPuk(true, oldPin, newPin, "SIM PIN"sv,
349                                    requestPipe, mAtConversation);
350 
351         NOT_NULL(mRadioSimResponse)->changeIccPinForAppResponse(
352                 makeRadioResponseInfo(serial, status), remainingRetries);
353         return status != RadioError::INTERNAL_ERR;
354     });
355 
356     return ScopedAStatus::ok();
357 }
358 
enableUiccApplications(const int32_t serial,const bool enable)359 ScopedAStatus RadioSim::enableUiccApplications(const int32_t serial, const bool enable) {
360     bool changed;
361     {
362         std::lock_guard<std::mutex> lock(mMtx);
363         changed = mUiccApplicationsEnabled != enable;
364         mUiccApplicationsEnabled = enable;
365     }
366 
367     NOT_NULL(mRadioSimResponse)->enableUiccApplicationsResponse(
368             makeRadioResponseInfo(serial));
369 
370     if (changed && mRadioSimIndication) {
371         mRadioSimIndication->uiccApplicationsEnablementChanged(
372                 RadioIndicationType::UNSOLICITED, enable);
373     }
374     return ScopedAStatus::ok();
375 }
376 
getAllowedCarriers(const int32_t serial)377 ScopedAStatus RadioSim::getAllowedCarriers(const int32_t serial) {
378     static const char* const kFunc = __func__;
379     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
380         using sim::CarrierInfo;
381         using sim::CarrierRestrictions;
382         using sim::SimLockMultiSimPolicy;
383         using CmeError = AtResponse::CmeError;
384         using COPS = AtResponse::COPS;
385 
386         RadioError status = RadioError::NONE;
387         CarrierRestrictions carrierRestrictions = {
388             .allowedCarriersPrioritized = true,
389         };
390 
391         const AtResponsePtr response =
392             mAtConversation(requestPipe, atCmds::getOperator,
393                             [](const AtResponse& response) -> bool {
394                                 return response.holds<COPS>() || response.holds<CmeError>();
395                             });
396         if (!response || response->isParseError()) {
397             status = FAILURE(RadioError::INTERNAL_ERR);
398         } else if (const COPS* cops = response->get_if<COPS>()) {
399             if ((cops->operators.size() == 1) && (cops->operators[0].isCurrent())) {
400                 const COPS::OperatorInfo& current = cops->operators[0];
401                 CarrierInfo ci = {
402                     .mcc = current.mcc(),
403                     .mnc = current.mnc(),
404                 };
405 
406                 carrierRestrictions.allowedCarrierInfoList.push_back(std::move(ci));
407             } else {
408                 response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
409             }
410         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
411             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
412         } else {
413             response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
414         }
415 
416         NOT_NULL(mRadioSimResponse)->getAllowedCarriersResponse(
417             makeRadioResponseInfo(serial, status),
418             std::move(carrierRestrictions),
419             SimLockMultiSimPolicy::NO_MULTISIM_POLICY);
420         return status != RadioError::INTERNAL_ERR;
421     });
422 
423     return ScopedAStatus::ok();
424 }
425 
getCdmaSubscription(const int32_t serial)426 ScopedAStatus RadioSim::getCdmaSubscription(const int32_t serial) {
427     NOT_NULL(mRadioSimResponse)->getCdmaSubscriptionResponse(
428         makeRadioResponseInfo(serial),
429         "8587777777",   // mdn
430         "1",            // sid
431         "1",            // nid
432         "8587777777",   // min
433         "1");           // prl
434     return ScopedAStatus::ok();
435 }
436 
getCdmaSubscriptionSource(const int32_t serial)437 ScopedAStatus RadioSim::getCdmaSubscriptionSource(const int32_t serial) {
438     static const char* const kFunc = __func__;
439     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
440         using CCSS = AtResponse::CCSS;
441 
442         AtResponsePtr response =
443             mAtConversation(requestPipe, atCmds::getCdmaSubscriptionSource,
444                             [](const AtResponse& response) -> bool {
445                                return response.holds<CCSS>();
446                             });
447         if (!response || response->isParseError()) {
448             NOT_NULL(mRadioSimResponse)->getCdmaSubscriptionSourceResponse(
449                     makeRadioResponseInfo(serial, RadioError::INTERNAL_ERR), {});
450             return false;
451         } else if (const CCSS* csss = response->get_if<CCSS>()) {
452             NOT_NULL(mRadioSimResponse)->getCdmaSubscriptionSourceResponse(
453                     makeRadioResponseInfo(serial), csss->source);
454         } else {
455             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
456         }
457 
458         return true;
459     });
460 
461     return ScopedAStatus::ok();
462 }
463 
getFacilityLockForApp(const int32_t serial,const std::string & facility,const std::string & password,const int32_t serviceClass,const std::string &)464 ScopedAStatus RadioSim::getFacilityLockForApp(const int32_t serial, const std::string& facility,
465                                               const std::string& password, const int32_t serviceClass,
466                                               const std::string& /*appId*/) {
467     std::string request = std::format("AT+CLCK=\"{0:s}\",{1:d},\"{2:s}\",{3:d}",
468                                       facility, atCmds::kClckQuery, password, serviceClass);
469 
470     static const char* const kFunc = __func__;
471     mAtChannel->queueRequester([this, serial, request = std::move(request)]
472                                (const AtChannel::RequestPipe requestPipe) -> bool {
473         using CmeError = AtResponse::CmeError;
474         using CLCK = AtResponse::CLCK;
475 
476         RadioError status = RadioError::NONE;
477         int lockBitmask = 0;
478 
479         AtResponsePtr response =
480             mAtConversation(requestPipe, request,
481                             [](const AtResponse& response) -> bool {
482                                return response.holds<CLCK>() || response.holds<CmeError>();
483                             });
484         if (!response || response->isParseError()) {
485             status = FAILURE(RadioError::INTERNAL_ERR);
486         } else if (const CLCK* clck = response->get_if<CLCK>()) {
487             lockBitmask = clck->locked ? 7 : 0;
488         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
489             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
490         } else {
491             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
492         }
493 
494         NOT_NULL(mRadioSimResponse)->getFacilityLockForAppResponse(
495                 makeRadioResponseInfo(serial, status), lockBitmask);
496         return status != RadioError::INTERNAL_ERR;
497     });
498 
499     return ScopedAStatus::ok();
500 }
501 
getIccCardStatus(const int32_t serial)502 ScopedAStatus RadioSim::getIccCardStatus(const int32_t serial) {
503     using sim::AppStatus;
504     using sim::PersoSubstate;
505     using sim::PinState;
506 
507     struct AppStatus3 {
508         AppStatus usim;
509         AppStatus ruim;
510         AppStatus isim;
511     };
512 
513     static const std::string kAidPtr = ""; //"A0000000871002FF86FF0389FFFFFFFF";
514     static const std::string kAppLabelPtr = "";
515 
516     static const std::string kATR = ""; //"3BF000818000";
517     // This data is mandatory and applicable only when cardState is
518     // STATE_PRESENT and SIM card supports eUICC.
519     static const std::string kEID = "";
520 
521     static const AppStatus3 kIccStatusReady = {
522         .usim = {
523             AppStatus::APP_TYPE_USIM, AppStatus::APP_STATE_READY, PersoSubstate::READY,
524             kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
525         },
526         .ruim = {
527             AppStatus::APP_TYPE_RUIM, AppStatus::APP_STATE_READY, PersoSubstate::READY,
528             kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
529         },
530         .isim = {
531             AppStatus::APP_TYPE_ISIM, AppStatus::APP_STATE_READY, PersoSubstate::READY,
532             kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
533         }
534     };
535 
536     static const AppStatus3 kIccStatusPIN = {
537         .usim = {
538             AppStatus::APP_TYPE_USIM, AppStatus::APP_STATE_PIN, PersoSubstate::UNKNOWN,
539             kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
540         },
541         .ruim = {
542             AppStatus::APP_TYPE_RUIM, AppStatus::APP_STATE_PIN, PersoSubstate::UNKNOWN,
543             kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
544         },
545         .isim = {
546             AppStatus::APP_TYPE_ISIM, AppStatus::APP_STATE_PIN, PersoSubstate::UNKNOWN,
547             kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
548         }
549     };
550 
551     static const AppStatus3 kIccStatusPUK = {
552         .usim = {
553             AppStatus::APP_TYPE_USIM, AppStatus::APP_STATE_PUK, PersoSubstate::UNKNOWN,
554             kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
555         },
556         .ruim = {
557             AppStatus::APP_TYPE_RUIM, AppStatus::APP_STATE_PUK, PersoSubstate::UNKNOWN,
558             kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
559         },
560         .isim = {
561             AppStatus::APP_TYPE_ISIM, AppStatus::APP_STATE_PUK, PersoSubstate::UNKNOWN,
562             kAidPtr, kAppLabelPtr, false, PinState::ENABLED_NOT_VERIFIED, PinState::ENABLED_NOT_VERIFIED
563         }
564     };
565 
566     static const AppStatus3 kIccStatusBUSY = {
567         .usim = {
568             AppStatus::APP_TYPE_USIM, AppStatus::APP_STATE_DETECTED, PersoSubstate::UNKNOWN,
569             kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
570         },
571         .ruim = {
572             AppStatus::APP_TYPE_RUIM, AppStatus::APP_STATE_DETECTED, PersoSubstate::UNKNOWN,
573             kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
574         },
575         .isim = {
576             AppStatus::APP_TYPE_ISIM, AppStatus::APP_STATE_DETECTED, PersoSubstate::UNKNOWN,
577             kAidPtr, kAppLabelPtr, false, PinState::UNKNOWN, PinState::UNKNOWN
578         }
579     };
580 
581     static const char* const kFunc = __func__;
582     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
583         using sim::CardStatus;
584         using CmeError = AtResponse::CmeError;
585         using CPIN = AtResponse::CPIN;
586 
587         RadioError status = RadioError::NONE;
588         CardStatus cardStatus = {
589             .slotMap = {
590                 .physicalSlotId = -1,  // see ril_service.cpp in CF
591                 .portId = 0,
592             }
593         };
594 
595         const AppStatus3* appStatus = nullptr;
596 
597         AtResponsePtr response =
598             mAtConversation(requestPipe, atCmds::getSimCardStatus,
599                             [](const AtResponse& response) -> bool {
600                                return response.holds<CPIN>() || response.holds<CmeError>();
601                             });
602         if (!response || response->isParseError()) {
603             status = FAILURE(RadioError::INTERNAL_ERR);
604             goto failed;
605         } else if (const CPIN* cpin = response->get_if<CPIN>()) {
606             switch (cpin->state) {
607             case CPIN::State::READY:
608                 cardStatus.cardState = sim::CardStatus::STATE_PRESENT;
609                 cardStatus.universalPinState = sim::PinState::UNKNOWN;
610                 appStatus = &kIccStatusReady;
611                 break;
612 
613             case CPIN::State::PIN:
614                 cardStatus.cardState = sim::CardStatus::STATE_RESTRICTED;
615                 cardStatus.universalPinState = sim::PinState::ENABLED_NOT_VERIFIED;
616                 appStatus = &kIccStatusPIN;
617                 break;
618 
619             case CPIN::State::PUK:
620                 cardStatus.cardState = sim::CardStatus::STATE_RESTRICTED;
621                 cardStatus.universalPinState = sim::PinState::ENABLED_NOT_VERIFIED;
622                 appStatus = &kIccStatusPUK;
623                 break;
624 
625             default:
626                 status = FAILURE(RadioError::INTERNAL_ERR);
627                 goto failed;
628             }
629         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
630             switch (cmeError->error) {
631             case RadioError::SIM_ABSENT:
632                 cardStatus.cardState = sim::CardStatus::STATE_ABSENT;
633                 cardStatus.universalPinState = sim::PinState::UNKNOWN;
634                 break;
635 
636             case RadioError::SIM_BUSY:
637             case RadioError::SIM_ERR:
638                 cardStatus.cardState = sim::CardStatus::STATE_ERROR;
639                 cardStatus.universalPinState = sim::PinState::UNKNOWN;
640                 appStatus = &kIccStatusBUSY;
641                 break;
642 
643             default:
644                 status = cmeError->getErrorAndLog(
645                     FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
646                 goto failed;
647             }
648         } else {
649             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
650         }
651 
652         if (cardStatus.cardState != sim::CardStatus::STATE_ABSENT) {
653             response =
654                 mAtConversation(requestPipe, atCmds::getICCID,
655                                 [](const AtResponse& response) -> bool {
656                                    return response.holds<std::string>();
657                                 });
658             if (!response || response->isParseError()) {
659                 status = FAILURE(RadioError::INTERNAL_ERR);
660                 goto failed;
661             } else if (const std::string* iccid = response->get_if<std::string>()) {
662                 cardStatus.iccid = *iccid;
663             } else {
664                 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
665             }
666 
667             cardStatus.applications.push_back(appStatus->usim);
668             cardStatus.applications.push_back(appStatus->ruim);
669             cardStatus.applications.push_back(appStatus->isim);
670             cardStatus.gsmUmtsSubscriptionAppIndex = 0; // usim
671             cardStatus.cdmaSubscriptionAppIndex = 1;    // ruim
672             cardStatus.imsSubscriptionAppIndex = 2;     // isim
673 
674             cardStatus.atr = kATR;
675             cardStatus.eid = kEID;
676         }
677 
678         if (status == RadioError::NONE) {
679             NOT_NULL(mRadioSimResponse)->getIccCardStatusResponse(
680                     makeRadioResponseInfo(serial), std::move(cardStatus));
681             return true;
682         } else {
683 failed:     NOT_NULL(mRadioSimResponse)->getIccCardStatusResponse(
684                     makeRadioResponseInfo(serial, status), {});
685             return status != RadioError::INTERNAL_ERR;
686         }
687     });
688 
689     return ScopedAStatus::ok();
690 }
691 
getImsiForApp(const int32_t serial,const std::string &)692 ScopedAStatus RadioSim::getImsiForApp(const int32_t serial, const std::string& /*aid*/) {
693     static const char* const kFunc = __func__;
694     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
695         using CmeError = AtResponse::CmeError;
696 
697         RadioError status = RadioError::NONE;
698         std::string imsi;
699 
700         AtResponsePtr response =
701             mAtConversation(requestPipe, atCmds::getIMSI,
702                             [](const AtResponse& response) -> bool {
703                                return response.holds<std::string>() || response.holds<CmeError>();
704                             });
705         if (!response || response->isParseError()) {
706             status = FAILURE(RadioError::INTERNAL_ERR);
707         } else if (const std::string* pImsi = response->get_if<std::string>()) {
708             imsi = *pImsi;
709         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
710             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
711         } else {
712             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
713         }
714 
715         if (status == RadioError::NONE) {
716             NOT_NULL(mRadioSimResponse)->getImsiForAppResponse(
717                     makeRadioResponseInfo(serial), std::move(imsi));
718             return true;
719         } else {
720             NOT_NULL(mRadioSimResponse)->getImsiForAppResponse(
721                     makeRadioResponseInfo(serial, FAILURE(status)), {});
722             return status != RadioError::INTERNAL_ERR;
723         }
724     });
725 
726     return ScopedAStatus::ok();
727 }
728 
getSimPhonebookCapacity(const int32_t serial)729 ScopedAStatus RadioSim::getSimPhonebookCapacity(const int32_t serial) {
730     NOT_NULL(mRadioSimResponse)->getSimPhonebookCapacityResponse(
731         makeRadioResponseInfoUnsupported(  // matches reference-ril.c
732             serial, FAILURE_DEBUG_PREFIX, __func__), {});
733     return ScopedAStatus::ok();
734 }
735 
getSimPhonebookRecords(const int32_t serial)736 ScopedAStatus RadioSim::getSimPhonebookRecords(const int32_t serial) {
737     NOT_NULL(mRadioSimResponse)->getSimPhonebookRecordsResponse(
738         makeRadioResponseInfoUnsupported(  // matches reference-ril.c
739             serial, FAILURE_DEBUG_PREFIX, __func__));
740     return ScopedAStatus::ok();
741 }
742 
iccCloseLogicalChannelWithSessionInfo(const int32_t serial,const sim::SessionInfo & recordInfo)743 ScopedAStatus RadioSim::iccCloseLogicalChannelWithSessionInfo(const int32_t serial,
744                                                               const sim::SessionInfo& recordInfo) {
745     const int32_t sessionId = recordInfo.sessionId;
746 
747     static const char* const kFunc = __func__;
748     mAtChannel->queueRequester([this, serial, sessionId](const AtChannel::RequestPipe requestPipe) -> bool {
749         using CCHC = AtResponse::CCHC;
750         using CmeError = AtResponse::CmeError;
751 
752         RadioError status = RadioError::NONE;
753 
754         const std::string request = std::format("AT+CCHC={0:d}", sessionId);
755         AtResponsePtr response =
756             mAtConversation(requestPipe, request,
757                             [](const AtResponse& response) -> bool {
758                                return response.holds<CCHC>() || response.holds<CmeError>();
759                             });
760         if (!response || response->isParseError()) {
761             status = FAILURE(RadioError::INTERNAL_ERR);
762         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
763             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
764             if (status == RadioError::NO_SUCH_ELEMENT) {
765                 status = RadioError::INVALID_ARGUMENTS;
766             }
767         } else if (!response->get_if<CCHC>()) {
768             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
769         }
770 
771         NOT_NULL(mRadioSimResponse)->iccCloseLogicalChannelWithSessionInfoResponse(
772                 makeRadioResponseInfo(serial, status));
773         return status != RadioError::INTERNAL_ERR;
774     });
775 
776     return ScopedAStatus::ok();
777 }
778 
iccIoForApp(const int32_t serial,const sim::IccIo & iccIo)779 ScopedAStatus RadioSim::iccIoForApp(const int32_t serial, const sim::IccIo& iccIo) {
780     static const char* const kFunc = __func__;
781     mAtChannel->queueRequester([this, serial, iccIo]
782                                (const AtChannel::RequestPipe requestPipe) -> bool {
783         using CRSM = AtResponse::CRSM;
784         using CmeError = AtResponse::CmeError;
785         using sim::IccIoResult;
786 
787         RadioError status = RadioError::NONE;
788         IccIoResult iccIoResult;
789 
790         std::string request;
791         if (iccIo.data.empty()) {
792             request = std::format("AT+CRSM={0:d},{1:d},{2:d},{3:d},{4:d}",
793                     iccIo.command, iccIo.fileId, iccIo.p1, iccIo.p2, iccIo.p3);
794         } else {
795             request = std::format("AT+CRSM={0:d},{1:d},{2:d},{3:d},{4:d},{5:s},{6:s}",
796                     iccIo.command, iccIo.fileId, iccIo.p1, iccIo.p2, iccIo.p3,
797                     iccIo.data, iccIo.aid);
798         }
799 
800         AtResponsePtr response =
801             mAtConversation(requestPipe, request,
802                             [](const AtResponse& response) -> bool {
803                                return response.holds<CRSM>() || response.holds<CmeError>();
804                             });
805         if (!response || response->isParseError()) {
806             status = FAILURE(RadioError::INTERNAL_ERR);
807         } else if (const CRSM* crsm = response->get_if<CRSM>()) {
808             iccIoResult.sw1 = crsm->sw1;
809             iccIoResult.sw2 = crsm->sw2;
810 
811             if (iccIo.command == 192) {  // get
812                 std::vector<uint8_t> bytes;
813                 if (hex2bin(crsm->response, &bytes) && !bytes.empty() && (bytes.front() == 0x62)) {
814                     if (!convertUsimToSim(bytes, &iccIoResult.simResponse)) {
815                         status = FAILURE(RadioError::GENERIC_FAILURE);
816                     }
817                 } else {
818                     iccIoResult.simResponse = crsm->response;
819                 }
820             } else {
821                 iccIoResult.simResponse = crsm->response;
822             }
823         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
824             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
825         } else {
826             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
827         }
828 
829         if (status == RadioError::NONE) {
830             NOT_NULL(mRadioSimResponse)->iccIoForAppResponse(
831                     makeRadioResponseInfo(serial), std::move(iccIoResult));
832             return true;
833         } else {
834             NOT_NULL(mRadioSimResponse)->iccIoForAppResponse(
835                     makeRadioResponseInfo(serial, status), {});
836             return status != RadioError::INTERNAL_ERR;
837         }
838     });
839 
840     return ScopedAStatus::ok();
841 }
842 
iccOpenLogicalChannel(const int32_t serial,const std::string & aid,const int32_t p2)843 ScopedAStatus RadioSim::iccOpenLogicalChannel(const int32_t serial,
844                                               const std::string& aid,
845                                               const int32_t p2) {
846     static const char* const kFunc = __func__;
847     mAtChannel->queueRequester([this, serial, aid, p2](const AtChannel::RequestPipe requestPipe) -> bool {
848         using CSIM = AtResponse::CSIM;
849         using CmeError = AtResponse::CmeError;
850 
851         RadioError status = RadioError::NONE;
852         int channelId = 0;
853         std::vector<uint8_t> selectResponse;
854 
855         if (aid.empty()) {
856             AtResponsePtr response =
857                 mAtConversation(requestPipe, "AT+CSIM=10,\"0070000001\""sv,
858                                 [](const AtResponse& response) -> bool {
859                                    return response.holds<CSIM>() || response.holds<CmeError>();
860                                 });
861             if (!response || response->isParseError()) {
862                 status = FAILURE(RadioError::INTERNAL_ERR);
863             } else if (const CSIM* csim = response->get_if<CSIM>()) {
864                 if (1 == ::sscanf(csim->response.c_str(), "%02x", &channelId)) {
865                     if (p2 >= 0) {
866                         auto maybeSelectResponse =
867                             getSelectResponse(requestPipe, mAtConversation,
868                                               channelId, p2);
869                         if (maybeSelectResponse) {
870                             selectResponse = std::move(maybeSelectResponse.value());
871                         } else {
872                             requestPipe(std::format("AT+CCHC={0:d}", channelId));
873                             status = FAILURE(RadioError::GENERIC_FAILURE);
874                         }
875                     } else {
876                         if (!hex2bin(std::string_view(csim->response).substr(2),
877                                      &selectResponse)) {
878                             status = FAILURE(RadioError::GENERIC_FAILURE);
879                         }
880                     }
881                 } else {
882                     status = FAILURE(RadioError::GENERIC_FAILURE);
883                 }
884             } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
885                 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
886             } else {
887                 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
888             }
889         } else {
890             const std::string request = std::format("AT+CCHO={0:s}", aid);
891             AtResponsePtr response =
892                 mAtConversation(requestPipe, request,
893                                 [](const AtResponse& response) -> bool {
894                                    return response.holds<std::string>() || response.holds<CmeError>();
895                                 });
896             if (!response || response->isParseError()) {
897                 status = FAILURE(RadioError::INTERNAL_ERR);
898             } else if (const std::string* idStr = response->get_if<std::string>()) {
899                 const char* end = idStr->data() + idStr->size();
900 
901                 if (std::from_chars(idStr->data(), end, channelId, 10).ptr != end) {
902                     status = FAILURE(RadioError::INTERNAL_ERR);
903                 }
904             } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
905                 status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
906             } else {
907                 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
908             }
909         }
910 
911         NOT_NULL(mRadioSimResponse)->iccOpenLogicalChannelResponse(
912                 makeRadioResponseInfo(serial, status), channelId, std::move(selectResponse));
913         return status != RadioError::INTERNAL_ERR;
914     });
915 
916     return ScopedAStatus::ok();
917 }
918 
iccTransmitApduBasicChannel(const int32_t serial,const sim::SimApdu & message)919 ScopedAStatus RadioSim::iccTransmitApduBasicChannel(const int32_t serial,
920                                                     const sim::SimApdu& message) {
921     static const char* const kFunc = __func__;
922     mAtChannel->queueRequester([this, serial, message]
923                                (const AtChannel::RequestPipe requestPipe) -> bool {
924         using CSIM = AtResponse::CSIM;
925         using CmeError = AtResponse::CmeError;
926         using sim::IccIoResult;
927 
928         RadioError status = RadioError::NONE;
929         IccIoResult iccIoResult;
930 
931         std::string request;
932         if (message.data.empty()) {
933             if (message.p3 < 0) {
934                 request = std::format(
935                         "AT+CSIM={0:d},\"{1:02x}{2:02x}{3:02x}{4:02x}\"", 8,
936                         message.cla, message.instruction, message.p1, message.p2);
937             } else {
938                 request = std::format(
939                         "AT+CSIM={0:d},\"{1:02x}{2:02x}{3:02x}{4:02x}{5:02x}\"", 10,
940                         message.cla, message.instruction, message.p1, message.p2, message.p3);
941             }
942         } else {
943             const size_t dataSize = 10 + message.data.size();
944             request = std::format(
945                     "AT+CSIM={0:d},\"{1:02x}{2:02x}{3:02x}{4:02x}{5:02x}{6:s}\"",
946                     dataSize, message.cla, message.instruction, message.p1,
947                     message.p2, message.p3, message.data);
948         }
949 
950         AtResponsePtr response =
951             mAtConversation(requestPipe, request,
952                             [](const AtResponse& response) -> bool {
953                                return response.holds<CSIM>() || response.holds<CmeError>();
954                             });
955         if (!response || response->isParseError()) {
956             status = FAILURE(RadioError::INTERNAL_ERR);
957         } else if (const CSIM* csim = response->get_if<CSIM>()) {
958             const std::string& simResponse = csim->response;
959             if (simResponse.size() >= 4) {
960                 if (2 == ::sscanf(&simResponse[simResponse.size() - 4], "%02X%02X",
961                                   &iccIoResult.sw1, &iccIoResult.sw2)) {
962                     iccIoResult.simResponse = simResponse.substr(0, simResponse.size() - 4);
963                 } else {
964                     status = FAILURE(RadioError::GENERIC_FAILURE);
965                 }
966             } else {
967                 status = FAILURE(RadioError::GENERIC_FAILURE);
968             }
969         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
970             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
971         } else {
972             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
973         }
974 
975         if (status == RadioError::NONE) {
976             NOT_NULL(mRadioSimResponse)->iccTransmitApduBasicChannelResponse(
977                 makeRadioResponseInfo(serial), std::move(iccIoResult));
978             return true;
979         } else {
980             NOT_NULL(mRadioSimResponse)->iccTransmitApduBasicChannelResponse(
981                 makeRadioResponseInfo(serial, status), {});
982             return status != RadioError::INTERNAL_ERR;
983         }
984     });
985 
986     return ScopedAStatus::ok();
987 }
988 
iccTransmitApduLogicalChannel(const int32_t serial,const sim::SimApdu & message)989 ScopedAStatus RadioSim::iccTransmitApduLogicalChannel(
990         const int32_t serial, const sim::SimApdu& message) {
991     static const char* const kFunc = __func__;
992     mAtChannel->queueRequester([this, serial, message]
993                                (const AtChannel::RequestPipe requestPipe) -> bool {
994         using CGLA = AtResponse::CGLA;
995         using CmeError = AtResponse::CmeError;
996         using sim::IccIoResult;
997 
998         RadioError status = RadioError::NONE;
999         IccIoResult iccIoResult;
1000 
1001         const size_t dataSize = 10 + message.data.size();
1002         const std::string request = std::format(
1003                 "AT+CGLA={0:d},{1:d},{2:02x}{3:02x}{4:02x}{5:02x}{6:02x}{7:s}",
1004                 message.sessionId, dataSize,
1005                 message.cla, message.instruction, message.p1,
1006                 message.p2, message.p3, message.data);
1007         AtResponsePtr response =
1008             mAtConversation(requestPipe, request,
1009                             [](const AtResponse& response) -> bool {
1010                                return response.holds<CGLA>() || response.holds<CmeError>();
1011                             });
1012         if (!response || response->isParseError()) {
1013             status = FAILURE(RadioError::INTERNAL_ERR);
1014         } else if (const CGLA* cgla = response->get_if<CGLA>()) {
1015             if (cgla->response.size() >= 4) {
1016                 const size_t size4 = cgla->response.size() - 4;
1017                 if (2 == ::sscanf(&cgla->response[size4], "%02x%02x",
1018                                   &iccIoResult.sw1, &iccIoResult.sw2)) {
1019                     iccIoResult.simResponse = cgla->response.substr(0, size4);
1020                 } else {
1021                     status = FAILURE(RadioError::GENERIC_FAILURE);
1022                 }
1023             } else {
1024                 status = FAILURE(RadioError::GENERIC_FAILURE);
1025             }
1026         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
1027             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
1028         } else {
1029             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1030         }
1031 
1032         if (status == RadioError::NONE) {
1033             NOT_NULL(mRadioSimResponse)->iccTransmitApduLogicalChannelResponse(
1034                 makeRadioResponseInfo(serial), std::move(iccIoResult));
1035             return true;
1036         } else {
1037             NOT_NULL(mRadioSimResponse)->iccTransmitApduLogicalChannelResponse(
1038                 makeRadioResponseInfo(serial, status), {});
1039             return status != RadioError::INTERNAL_ERR;
1040         }
1041     });
1042 
1043     return ScopedAStatus::ok();
1044 }
1045 
reportStkServiceIsRunning(const int32_t serial)1046 ScopedAStatus RadioSim::reportStkServiceIsRunning(const int32_t serial) {
1047     decltype(mStkUnsolResponse) stkUnsolResponse;
1048     {
1049         std::lock_guard<std::mutex> lock(mMtx);
1050         mStkServiceRunning = true;
1051         stkUnsolResponse = std::move(mStkUnsolResponse);
1052     }
1053 
1054     if (stkUnsolResponse) {
1055         NOT_NULL(mRadioSimIndication)->stkProactiveCommand(
1056             RadioIndicationType::UNSOLICITED, std::move(stkUnsolResponse.value().cmd));
1057     }
1058 
1059     static const char* const kFunc = __func__;
1060     mAtChannel->queueRequester([this, serial]
1061                                (const AtChannel::RequestPipe requestPipe) -> bool {
1062         using CUSATD = AtResponse::CUSATD;
1063 
1064         RadioError status = RadioError::NONE;
1065 
1066         AtResponsePtr response =
1067             mAtConversation(requestPipe, atCmds::reportStkServiceRunning,
1068                             [](const AtResponse& response) -> bool {
1069                                return response.holds<CUSATD>();
1070                             });
1071         if (!response || response->isParseError()) {
1072             status = FAILURE(RadioError::INTERNAL_ERR);
1073         } else if (!response->get_if<CUSATD>()) {
1074             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1075         }
1076 
1077         NOT_NULL(mRadioSimResponse)->reportStkServiceIsRunningResponse(
1078                 makeRadioResponseInfo(serial, status));
1079         return status != RadioError::INTERNAL_ERR;
1080     });
1081 
1082     return ScopedAStatus::ok();
1083 }
1084 
requestIccSimAuthentication(const int32_t serial,const int32_t authContextInt,const std::string & authData64,const std::string &)1085 ScopedAStatus RadioSim::requestIccSimAuthentication(const int32_t serial,
1086                                                     const int32_t authContextInt,
1087                                                     const std::string& authData64,
1088                                                     const std::string& /*aid*/) {
1089     const AuthContext authContext = static_cast<AuthContext>(authContextInt);
1090 
1091     auto [status, randBin, authBin] = parseAuthData(authContext, authData64);
1092     if (status != RadioError::NONE) {
1093         NOT_NULL(mRadioSimResponse)->requestIccSimAuthenticationResponse(
1094                 makeRadioResponseInfo(serial, status), {});
1095         return ScopedAStatus::ok();
1096     }
1097 
1098     std::string randHex = bin2hex(randBin.data(), randBin.size());
1099     std::string authHex = bin2hex(authBin.data(), authBin.size());
1100 
1101     static const char* const kFunc = __func__;
1102     mAtChannel->queueRequester([this, serial, authContext,
1103                                 randHex = std::move(randHex),
1104                                 authHex = std::move(authHex)]
1105                                (const AtChannel::RequestPipe requestPipe) -> bool {
1106         using CmeError = AtResponse::CmeError;
1107         using MBAU = AtResponse::MBAU;
1108         using sim::IccIoResult;
1109 
1110         RadioError status = RadioError::NONE;
1111         IccIoResult iccIoResult;
1112 
1113         std::string request;
1114         switch (authContext) {
1115         case AuthContext::SIM:
1116             request = std::format("AT^MBAU=\"{0:s}\"", randHex);
1117             break;
1118 
1119         case AuthContext::AKA:
1120             request = std::format("AT^MBAU=\"{0:s},{1:s}\"", randHex, authHex);  // the quotes are interesting here
1121             break;
1122 
1123         default:
1124             return FAILURE(false);
1125         }
1126 
1127         AtResponsePtr response =
1128             mAtConversation(requestPipe, request,
1129                             [](const AtResponse& response) -> bool {
1130                                return response.holds<MBAU>() ||
1131                                       response.holds<CmeError>();
1132                             });
1133         if (!response || response->isParseError()) {
1134             status = FAILURE(RadioError::INTERNAL_ERR);
1135         } else if (const MBAU* mbau = response->get_if<MBAU>()) {
1136             const auto putByte = [](uint8_t* dst, uint8_t b) -> uint8_t* {
1137                 *dst = b;
1138                 return dst + 1;
1139             };
1140 
1141             const auto putRange = [](uint8_t* dst, const uint8_t* src, size_t size) -> uint8_t* {
1142                 memcpy(dst, src, size);
1143                 return dst + size;
1144             };
1145 
1146             const auto putSizedRange = [putByte, putRange](uint8_t* dst, const uint8_t* src, size_t size) -> uint8_t* {
1147                 return putRange(putByte(dst, size), src, size);
1148             };
1149 
1150             std::vector<uint8_t> responseBin;
1151             uint8_t* p;
1152 
1153             switch (authContext) {
1154             case AuthContext::SIM:  // sresLen + sres + kcLen + kc
1155                 responseBin.resize(2 + mbau->sres.size() + mbau->kc.size());
1156                 p = responseBin.data();
1157                 p = putSizedRange(p, mbau->sres.data(), mbau->sres.size());
1158                 p = putSizedRange(p, mbau->kc.data(), mbau->kc.size());
1159                 break;
1160 
1161             case AuthContext::AKA:  // 0xDB + ckLen + ck + ikLen + ik + resAutsLen + resAuts
1162                 responseBin.resize(4 + mbau->ck.size() + mbau->ik.size() + mbau->resAuts.size());
1163                 p = responseBin.data();
1164                 p = putByte(p, 0xDB);
1165                 p = putSizedRange(p, mbau->ck.data(), mbau->ck.size());
1166                 p = putSizedRange(p, mbau->ik.data(), mbau->ik.size());
1167                 p = putSizedRange(p, mbau->resAuts.data(), mbau->resAuts.size());
1168                 break;
1169             }
1170 
1171             iccIoResult.sw1 = 0x90;
1172             iccIoResult.sw2 = 0;
1173             iccIoResult.simResponse = base64encode(responseBin.data(), responseBin.size());
1174         } else if (response->isOK()) {
1175             status = FAILURE(RadioError::GENERIC_FAILURE);
1176         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
1177             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
1178         } else {
1179             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1180         }
1181 
1182         if (status == RadioError::NONE) {
1183             NOT_NULL(mRadioSimResponse)->requestIccSimAuthenticationResponse(
1184                     makeRadioResponseInfo(serial), std::move(iccIoResult));
1185             return true;
1186         } else {
1187             NOT_NULL(mRadioSimResponse)->requestIccSimAuthenticationResponse(
1188                     makeRadioResponseInfo(serial, status), {});
1189             return status != RadioError::INTERNAL_ERR;
1190         }
1191     });
1192 
1193     return ScopedAStatus::ok();
1194 }
1195 
sendEnvelope(const int32_t serial,const std::string & contents)1196 ScopedAStatus RadioSim::sendEnvelope(const int32_t serial,
1197                                      const std::string& contents) {
1198     static const char* const kFunc = __func__;
1199     mAtChannel->queueRequester([this, serial, contents]
1200                                (const AtChannel::RequestPipe requestPipe) -> bool {
1201         using CUSATE = AtResponse::CUSATE;
1202         RadioError status = RadioError::NONE;
1203         std::string commandResponse;
1204 
1205         const std::string request = std::format("AT+CUSATE=\"{0:s}\"", contents);
1206         AtResponsePtr response =
1207             mAtConversation(requestPipe, request,
1208                             [](const AtResponse& response) -> bool {
1209                                return response.holds<CUSATE>();
1210                             });
1211         if (!response || response->isParseError()) {
1212             status = FAILURE(RadioError::INTERNAL_ERR);
1213         } else if (const CUSATE* cusate = response->get_if<CUSATE>()) {
1214             commandResponse = cusate->response;
1215         } else {
1216             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1217         }
1218 
1219         NOT_NULL(mRadioSimResponse)->sendEnvelopeResponse(
1220             makeRadioResponseInfo(serial, status), std::move(commandResponse));
1221         return status != RadioError::INTERNAL_ERR;
1222     });
1223 
1224     return ScopedAStatus::ok();
1225 }
1226 
sendEnvelopeWithStatus(const int32_t serial,const std::string &)1227 ScopedAStatus RadioSim::sendEnvelopeWithStatus(const int32_t serial,
1228                                                const std::string& /*contents*/) {
1229     NOT_NULL(mRadioSimResponse)->sendEnvelopeWithStatusResponse(
1230         makeRadioResponseInfoUnsupported(  // matches reference-ril.c
1231             serial, FAILURE_DEBUG_PREFIX, __func__), {});
1232     return ScopedAStatus::ok();
1233 }
1234 
sendTerminalResponseToSim(const int32_t serial,const std::string & commandResponse)1235 ScopedAStatus RadioSim::sendTerminalResponseToSim(const int32_t serial,
1236                                                   const std::string& commandResponse) {
1237     static const char* const kFunc = __func__;
1238     mAtChannel->queueRequester([this, serial, commandResponse]
1239                                (const AtChannel::RequestPipe requestPipe) -> bool {
1240         using CUSATT = AtResponse::CUSATT;
1241         RadioError status = RadioError::NONE;
1242 
1243         const std::string request = std::format("AT+CUSATT=\"{0:s}\"", commandResponse);
1244         AtResponsePtr response =
1245             mAtConversation(requestPipe, request,
1246                             [](const AtResponse& response) -> bool {
1247                                return response.holds<CUSATT>();
1248                             });
1249         if (!response || response->isParseError()) {
1250             status = FAILURE(RadioError::INTERNAL_ERR);
1251         } else if (!response->get_if<CUSATT>()) {
1252             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1253         }
1254 
1255         NOT_NULL(mRadioSimResponse)->sendTerminalResponseToSimResponse(
1256                 makeRadioResponseInfo(serial, status));
1257         return status != RadioError::INTERNAL_ERR;
1258     });
1259 
1260     return ScopedAStatus::ok();
1261 }
1262 
setAllowedCarriers(const int32_t serial,const sim::CarrierRestrictions &,const sim::SimLockMultiSimPolicy)1263 ScopedAStatus RadioSim::setAllowedCarriers(const int32_t serial,
1264                                            const sim::CarrierRestrictions& /*carriers*/,
1265                                            const sim::SimLockMultiSimPolicy /*multiSimPolicy*/) {
1266     NOT_NULL(mRadioSimResponse)->setAllowedCarriersResponse(
1267         makeRadioResponseInfoNOP(serial));
1268     return ScopedAStatus::ok();
1269 }
1270 
setCarrierInfoForImsiEncryption(const int32_t serial,const sim::ImsiEncryptionInfo &)1271 ScopedAStatus RadioSim::setCarrierInfoForImsiEncryption(const int32_t serial,
1272                                                         const sim::ImsiEncryptionInfo& /*imsiEncryptionInfo*/) {
1273     NOT_NULL(mRadioSimResponse)->setCarrierInfoForImsiEncryptionResponse(
1274         makeRadioResponseInfoUnsupported(  // matches reference-ril.c
1275             serial, FAILURE_DEBUG_PREFIX, __func__));
1276     return ScopedAStatus::ok();
1277 }
1278 
setCdmaSubscriptionSource(const int32_t serial,const sim::CdmaSubscriptionSource cdmaSub)1279 ScopedAStatus RadioSim::setCdmaSubscriptionSource(const int32_t serial,
1280                                                   const sim::CdmaSubscriptionSource cdmaSub) {
1281     static const char* const kFunc = __func__;
1282     mAtChannel->queueRequester([this, serial, cdmaSub]
1283                                (const AtChannel::RequestPipe requestPipe) -> bool {
1284         RadioError status = RadioError::NONE;
1285 
1286         const std::string request =
1287             std::format("AT+CCSS={0:d}", static_cast<unsigned>(cdmaSub));
1288         const AtResponsePtr response =
1289             mAtConversation(requestPipe, request,
1290                             [](const AtResponse& response) -> bool {
1291                                return response.isOK();
1292                             });
1293         if (!response || response->isParseError()) {
1294             status = FAILURE(RadioError::INTERNAL_ERR);
1295         } else if (!response->isOK()) {
1296             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1297         }
1298 
1299         NOT_NULL(mRadioSimResponse)->setCdmaSubscriptionSourceResponse(
1300             makeRadioResponseInfo(serial, status));
1301         if ((status == RadioError::NONE) && mRadioSimIndication) {
1302             mRadioSimIndication->cdmaSubscriptionSourceChanged(
1303                 RadioIndicationType::UNSOLICITED, cdmaSub);
1304         }
1305 
1306         return status != RadioError::INTERNAL_ERR;
1307     });
1308 
1309     return ScopedAStatus::ok();
1310 }
1311 
setFacilityLockForApp(const int32_t serial,const std::string & facility,const bool lockState,const std::string & passwd,const int32_t serviceClass,const std::string &)1312 ScopedAStatus RadioSim::setFacilityLockForApp(const int32_t serial,
1313                                               const std::string& facility,
1314                                               const bool lockState,
1315                                               const std::string& passwd,
1316                                               const int32_t serviceClass,
1317                                               const std::string& /*appId*/) {
1318     static const char* const kFunc = __func__;
1319     mAtChannel->queueRequester([this, serial, facility, lockState,
1320                                 passwd, serviceClass]
1321                                (const AtChannel::RequestPipe requestPipe) -> bool {
1322         using CmeError = AtResponse::CmeError;
1323 
1324         RadioError status = RadioError::NONE;
1325         int retry = 1;
1326         const int lockStateInt = lockState ? 1 : 0;
1327 
1328         std::string request;
1329         if (serviceClass == 0) {
1330             request = std::format("AT+CLCK=\"{0:s}\",{1:d},\"{2:s}\"",
1331                                   facility, lockStateInt, passwd);
1332         } else {
1333             request = std::format("AT+CLCK=\"{0:s}\",{1:d},\"{2:s}\",{3:d}",
1334                                   facility, lockStateInt, passwd, serviceClass);
1335         }
1336 
1337         AtResponsePtr response =
1338             mAtConversation(requestPipe, request,
1339                             [](const AtResponse& response) -> bool {
1340                                return response.isOK() || response.holds<CmeError>();
1341                             });
1342         if (!response || response->isParseError()) {
1343             status = FAILURE(RadioError::INTERNAL_ERR);
1344         } else if (response->get_if<CmeError>()) {
1345             if (facility.compare("SC"sv) == 0) {
1346                 const std::optional<int> maybeRetries =
1347                     getRemainingRetries("SIM PIN"sv, requestPipe, mAtConversation);
1348                 if (maybeRetries) {
1349                     status = FAILURE(RadioError::PASSWORD_INCORRECT);
1350                     retry = maybeRetries.value();
1351                 } else {
1352                     status = FAILURE(RadioError::INTERNAL_ERR);
1353                 }
1354             } else if (facility.compare("FD"sv) == 0) {
1355                 const std::optional<int> maybeRetries =
1356                     getRemainingRetries("SIM PIN2"sv, requestPipe, mAtConversation);
1357                 if (maybeRetries) {
1358                     status = FAILURE(RadioError::PASSWORD_INCORRECT);
1359                     retry = maybeRetries.value();
1360                 } else {
1361                     status = FAILURE(RadioError::INTERNAL_ERR);
1362                 }
1363             } else {
1364                 status = FAILURE(RadioError::INVALID_ARGUMENTS);
1365                 retry = -1;
1366             }
1367         } else if (!response->isOK()) {
1368             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1369         }
1370 
1371         NOT_NULL(mRadioSimResponse)->setFacilityLockForAppResponse(
1372             makeRadioResponseInfo(serial, status), retry);
1373         return status != RadioError::INTERNAL_ERR;
1374     });
1375 
1376     return ScopedAStatus::ok();
1377 }
1378 
setSimCardPower(const int32_t serial,sim::CardPowerState)1379 ScopedAStatus RadioSim::setSimCardPower(const int32_t serial,
1380                                         sim::CardPowerState /*powerUp*/) {
1381     NOT_NULL(mRadioSimResponse)->setSimCardPowerResponse(
1382         makeRadioResponseInfoNOP(serial));
1383     return ScopedAStatus::ok();
1384 }
1385 
setUiccSubscription(const int32_t serial,const sim::SelectUiccSub &)1386 ScopedAStatus RadioSim::setUiccSubscription(const int32_t serial,
1387                                             const sim::SelectUiccSub& /*uiccSub*/) {
1388     NOT_NULL(mRadioSimResponse)->setUiccSubscriptionResponse(
1389         makeRadioResponseInfoUnsupported(  // matches reference-ril.c
1390             serial, FAILURE_DEBUG_PREFIX, __func__));
1391     return ScopedAStatus::ok();
1392 }
1393 
supplyIccPin2ForApp(int32_t serial,const std::string & pin2,const std::string &)1394 ScopedAStatus RadioSim::supplyIccPin2ForApp(int32_t serial,
1395                                             const std::string& pin2,
1396                                             const std::string& /*aid*/) {
1397     mAtChannel->queueRequester([this, serial, pin2]
1398                                (const AtChannel::RequestPipe requestPipe) -> bool {
1399         const auto [status, remainingRetries] =
1400             enterOrChangeSimPinPuk(false, pin2, "", "SIM PIN2"sv,
1401                                    requestPipe, mAtConversation);
1402 
1403         NOT_NULL(mRadioSimResponse)->supplyIccPin2ForAppResponse(
1404                 makeRadioResponseInfo(serial, status), remainingRetries);
1405         return status != RadioError::INTERNAL_ERR;
1406     });
1407 
1408     return ScopedAStatus::ok();
1409 }
1410 
supplyIccPinForApp(int32_t serial,const std::string & pin,const std::string &)1411 ScopedAStatus RadioSim::supplyIccPinForApp(int32_t serial,
1412                                            const std::string& pin,
1413                                            const std::string& /*aid*/) {
1414     mAtChannel->queueRequester([this, serial, pin]
1415                                (const AtChannel::RequestPipe requestPipe) -> bool {
1416         const auto [status, remainingRetries] =
1417             enterOrChangeSimPinPuk(false, pin, "", "SIM PIN"sv,
1418                                    requestPipe, mAtConversation);
1419 
1420         NOT_NULL(mRadioSimResponse)->supplyIccPinForAppResponse(
1421                 makeRadioResponseInfo(serial, status), remainingRetries);
1422         return status != RadioError::INTERNAL_ERR;
1423     });
1424 
1425     return ScopedAStatus::ok();
1426 }
1427 
supplyIccPuk2ForApp(int32_t serial,const std::string & puk2,const std::string & pin2,const std::string &)1428 ScopedAStatus RadioSim::supplyIccPuk2ForApp(int32_t serial,
1429                                             const std::string& puk2,
1430                                             const std::string& pin2,
1431                                             const std::string& /*aid*/) {
1432     mAtChannel->queueRequester([this, serial, puk2, pin2]
1433                                (const AtChannel::RequestPipe requestPipe) -> bool {
1434         const auto [status, remainingRetries] =
1435             enterOrChangeSimPinPuk(true, puk2, pin2, "SIM PUK2"sv,
1436                                    requestPipe, mAtConversation);
1437 
1438         NOT_NULL(mRadioSimResponse)->supplyIccPuk2ForAppResponse(
1439                 makeRadioResponseInfo(serial, status), remainingRetries);
1440         return status != RadioError::INTERNAL_ERR;
1441     });
1442 
1443     return ScopedAStatus::ok();
1444 }
1445 
supplyIccPukForApp(const int32_t serial,const std::string & puk,const std::string & pin,const std::string &)1446 ScopedAStatus RadioSim::supplyIccPukForApp(const int32_t serial,
1447                                            const std::string& puk,
1448                                            const std::string& pin,
1449                                            const std::string& /*aid*/) {
1450     mAtChannel->queueRequester([this, serial, puk, pin]
1451                                (const AtChannel::RequestPipe requestPipe) -> bool {
1452         const auto [status, remainingRetries] =
1453             enterOrChangeSimPinPuk(true, puk, pin, "SIM PUK"sv,
1454                                    requestPipe, mAtConversation);
1455 
1456         NOT_NULL(mRadioSimResponse)->supplyIccPukForAppResponse(
1457                 makeRadioResponseInfo(serial, status), remainingRetries);
1458         return status != RadioError::INTERNAL_ERR;
1459     });
1460 
1461     return ScopedAStatus::ok();
1462 }
1463 
supplySimDepersonalization(const int32_t serial,sim::PersoSubstate,const std::string &)1464 ScopedAStatus RadioSim::supplySimDepersonalization(const int32_t serial,
1465                                                    sim::PersoSubstate /*persoType*/,
1466                                                    const std::string& /*controlKey*/) {
1467     NOT_NULL(mRadioSimResponse)->supplySimDepersonalizationResponse(
1468         makeRadioResponseInfoUnsupported(  // matches reference-ril.c
1469             serial, FAILURE_DEBUG_PREFIX, __func__),
1470         {}, 0);
1471     return ScopedAStatus::ok();
1472 }
1473 
updateSimPhonebookRecords(const int32_t serial,const sim::PhonebookRecordInfo &)1474 ScopedAStatus RadioSim::updateSimPhonebookRecords(const int32_t serial,
1475                                                   const sim::PhonebookRecordInfo& /*recordInfo*/) {
1476     NOT_NULL(mRadioSimResponse)->updateSimPhonebookRecordsResponse(
1477         makeRadioResponseInfoUnsupported(  // matches reference-ril.c
1478             serial, FAILURE_DEBUG_PREFIX, __func__), 0);
1479     return ScopedAStatus::ok();
1480 }
1481 
handleUnsolicited(const AtResponse::CFUN & cfun)1482 void RadioSim::handleUnsolicited(const AtResponse::CFUN& cfun) {
1483     bool changed;
1484     {
1485         std::lock_guard<std::mutex> lock(mMtx);
1486         changed = mRadioState != cfun.state;
1487         mRadioState = cfun.state;
1488     }
1489 
1490     if (changed && mRadioSimIndication) {
1491         mRadioSimIndication->simStatusChanged(
1492             RadioIndicationType::UNSOLICITED);
1493 
1494         mRadioSimIndication->subscriptionStatusChanged(
1495             RadioIndicationType::UNSOLICITED, mRadioState == modem::RadioState::ON);
1496     }
1497 }
1498 
handleUnsolicited(const AtResponse::CUSATP & cusatp)1499 void RadioSim::handleUnsolicited(const AtResponse::CUSATP& cusatp) {
1500     const std::string& cmd = cusatp.cmd;
1501     if (cmd.size() < 3) {
1502         return;
1503     }
1504     const unsigned typeOffset = (cmd[2] <= '7') ? 10 : 12;
1505     if (cmd.size() < (typeOffset + 2)) {
1506         return;
1507     }
1508 
1509     unsigned cmdType = 0;
1510     if (!(std::from_chars(&cmd[typeOffset], &cmd[typeOffset + 2], cmdType, 16).ec == std::errc{})) {
1511         return;
1512     }
1513 
1514     const StkCmdType stkCmdType = static_cast<StkCmdType>(cmdType);
1515 
1516     enum class Action {
1517         NOTHING, NOTIFY, PROACTIVE_CMD
1518     };
1519 
1520     Action action;
1521 
1522     {
1523         std::lock_guard<std::mutex> lock(mMtx);
1524 
1525         switch (stkCmdType) {
1526         case StkCmdType::RUN_AT:
1527         case StkCmdType::SEND_DTMF:
1528         case StkCmdType::SEND_SMS:
1529         case StkCmdType::SEND_SS:
1530         case StkCmdType::SEND_USSD:
1531         case StkCmdType::PLAY_TONE:
1532         case StkCmdType::CLOSE_CHANNEL:
1533             action = Action::NOTIFY;
1534             break;
1535 
1536         case StkCmdType::REFRESH:
1537             if (cmd.size() >= (typeOffset + 4) && !strncmp(&cmd[typeOffset + 2], "04", 2)) {
1538                 // SIM_RESET
1539                 mStkServiceRunning = false;
1540                 action = Action::NOTHING;
1541             } else {
1542                 action = Action::NOTIFY;
1543             }
1544             break;
1545 
1546         default:
1547             action = Action::PROACTIVE_CMD;
1548             break;
1549         }
1550 
1551         if (!mStkServiceRunning) {
1552             mStkUnsolResponse = cusatp;
1553             action = Action::NOTHING;
1554         }
1555     }
1556 
1557     if (mRadioSimIndication) {
1558         switch (action) {
1559         case Action::NOTIFY:
1560             mRadioSimIndication->stkEventNotify(RadioIndicationType::UNSOLICITED, cmd);
1561             break;
1562 
1563         case Action::PROACTIVE_CMD:
1564             mRadioSimIndication->stkProactiveCommand(RadioIndicationType::UNSOLICITED, cmd);
1565             break;
1566 
1567         case Action::NOTHING:
1568             break;
1569         }
1570     }
1571 }
1572 
handleUnsolicited(const AtResponse::CUSATEND &)1573 void RadioSim::handleUnsolicited(const AtResponse::CUSATEND&) {
1574     if (mRadioSimIndication) {
1575         mRadioSimIndication->stkSessionEnd(RadioIndicationType::UNSOLICITED);
1576     }
1577 }
1578 
atResponseSink(const AtResponsePtr & response)1579 void RadioSim::atResponseSink(const AtResponsePtr& response) {
1580     if (!mAtConversation.send(response)) {
1581         response->visit([this](const auto& msg){ handleUnsolicited(msg); });
1582     }
1583 }
1584 
responseAcknowledgement()1585 ScopedAStatus RadioSim::responseAcknowledgement() {
1586     return ScopedAStatus::ok();
1587 }
1588 
setResponseFunctions(const std::shared_ptr<sim::IRadioSimResponse> & radioSimResponse,const std::shared_ptr<sim::IRadioSimIndication> & radioSimIndication)1589 ScopedAStatus RadioSim::setResponseFunctions(
1590         const std::shared_ptr<sim::IRadioSimResponse>& radioSimResponse,
1591         const std::shared_ptr<sim::IRadioSimIndication>& radioSimIndication) {
1592     mRadioSimResponse = NOT_NULL(radioSimResponse);
1593     mRadioSimIndication = NOT_NULL(radioSimIndication);
1594     return ScopedAStatus::ok();
1595 }
1596 
1597 /************************* deprecated *************************/
iccCloseLogicalChannel(const int32_t serial,const int32_t)1598 ScopedAStatus RadioSim::iccCloseLogicalChannel(const int32_t serial,
1599                                                const int32_t /*channelId*/) {
1600     NOT_NULL(mRadioSimResponse)->iccCloseLogicalChannelResponse(
1601         makeRadioResponseInfoDeprecated(serial));
1602     return ScopedAStatus::ok();
1603 }
1604 
1605 }  // namespace implementation
1606 }  // namespace radio
1607 }  // namespace hardware
1608 }  // namespace android
1609 }  // namespace aidl
1610