• 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 "RadioNetwork"
18 
19 #include <chrono>
20 #include <thread>
21 
22 #include <utils/SystemClock.h>
23 
24 #include <aidl/android/hardware/radio/RadioConst.h>
25 
26 #include "RadioNetwork.h"
27 #include "atCmds.h"
28 #include "debug.h"
29 #include "ratUtils.h"
30 #include "makeRadioResponseInfo.h"
31 
32 namespace aidl {
33 namespace android {
34 namespace hardware {
35 namespace radio {
36 namespace implementation {
37 using network::AccessTechnologySpecificInfo;
38 using network::EutranBands;
39 using network::EutranRegistrationInfo;
40 using network::Cdma2000RegistrationInfo;
41 using network::CellConnectionStatus;
42 using network::CellIdentity;
43 using network::CellIdentityCdma;
44 using network::CellIdentityGsm;
45 using network::CellIdentityLte;
46 using network::CellIdentityNr;
47 using network::CellIdentityTdscdma;
48 using network::CellIdentityWcdma;
49 using network::CellInfo;
50 using network::CellInfoCdma;
51 using network::CellInfoGsm;
52 using network::CellInfoLte;
53 using network::CellInfoNr;
54 using network::CellInfoTdscdma;
55 using network::CellInfoWcdma;
56 using network::CellInfoRatSpecificInfo;
57 using network::NgranBands;
58 using network::OperatorInfo;
59 using network::RegStateResult;
60 using network::SignalStrength;
61 
62 namespace {
63 // somehow RadioConst.h does not contain these values
64 constexpr int32_t kRadioConst_VALUE_UNAVAILABLE = 0x7FFFFFFF;  // b/382554555
65 constexpr uint8_t kRadioConst_VALUE_UNAVAILABLE_BYTE = 0xFFU;
66 
makeCellIdentityCdma(OperatorInfo operatorInfo)67 CellIdentityCdma makeCellIdentityCdma(OperatorInfo operatorInfo) {
68     CellIdentityCdma result = {
69         .networkId = kRadioConst_VALUE_UNAVAILABLE,
70         .systemId = kRadioConst_VALUE_UNAVAILABLE,
71         .baseStationId = kRadioConst_VALUE_UNAVAILABLE,
72         .longitude = kRadioConst_VALUE_UNAVAILABLE,
73         .latitude = kRadioConst_VALUE_UNAVAILABLE,
74     };
75 
76     result.operatorNames = std::move(operatorInfo);
77 
78     return result;
79 }
80 
getMcc(const OperatorInfo & operatorInfo)81 std::string getMcc(const OperatorInfo& operatorInfo) {
82     return operatorInfo.operatorNumeric.substr(0, 3);
83 }
84 
getMnc(const OperatorInfo & operatorInfo)85 std::string getMnc(const OperatorInfo& operatorInfo) {
86     return operatorInfo.operatorNumeric.substr(3);
87 }
88 
makeCellIdentityGsm(OperatorInfo operatorInfo,const int areaCode,const int cellId)89 CellIdentityGsm makeCellIdentityGsm(OperatorInfo operatorInfo,
90                                     const int areaCode, const int cellId) {
91     CellIdentityGsm result = {
92         .mcc = getMcc(operatorInfo),
93         .mnc = getMnc(operatorInfo),
94         .lac = areaCode,
95         .cid = cellId,
96         .arfcn = 42,
97         .bsic = 127, // kRadioConst_VALUE_UNAVAILABLE_BYTE, b/382555063
98     };
99 
100     result.additionalPlmns.push_back(operatorInfo.operatorNumeric);
101     result.operatorNames = std::move(operatorInfo);
102 
103     return result;
104 }
105 
makeCellIdentityLte(OperatorInfo operatorInfo,const int areaCode,const int cellId)106 CellIdentityLte makeCellIdentityLte(OperatorInfo operatorInfo,
107                                     const int areaCode, const int cellId) {
108     CellIdentityLte result = {
109         .mcc = getMcc(operatorInfo),
110         .mnc = getMnc(operatorInfo),
111         .ci = cellId,
112         .pci = 0,
113         .tac = areaCode,
114         .earfcn = 103,
115         .bandwidth = 10000,
116     };
117 
118     result.additionalPlmns.push_back(operatorInfo.operatorNumeric);
119     result.operatorNames = std::move(operatorInfo);
120     result.bands.push_back(EutranBands::BAND_42);
121 
122     return result;
123 }
124 
makeCellIdentityNr(OperatorInfo operatorInfo,const int areaCode)125 CellIdentityNr makeCellIdentityNr(OperatorInfo operatorInfo, const int areaCode) {
126     std::string plmn = operatorInfo.operatorNumeric;
127 
128     CellIdentityNr result = {
129         .mcc = getMcc(operatorInfo),
130         .mnc = getMnc(operatorInfo),
131         .nci = 100500,
132         .pci = 555,
133         .tac = areaCode,
134         .nrarfcn = 9000,
135     };
136 
137     result.additionalPlmns.push_back(operatorInfo.operatorNumeric);
138     result.operatorNames = std::move(operatorInfo);
139     result.bands.push_back(NgranBands::BAND_41);
140 
141     return result;
142 }
143 
makeCellIdentityTdscdma(OperatorInfo operatorInfo,const int areaCode,const int cellId)144 CellIdentityTdscdma makeCellIdentityTdscdma(OperatorInfo operatorInfo,
145                                             const int areaCode, const int cellId) {
146     CellIdentityTdscdma result = {
147         .mcc = getMcc(operatorInfo),
148         .mnc = getMnc(operatorInfo),
149         .lac = areaCode,
150         .cid = cellId,
151         .cpid = kRadioConst_VALUE_UNAVAILABLE,
152         .uarfcn = 777,
153     };
154 
155     result.additionalPlmns.push_back(operatorInfo.operatorNumeric);
156     result.operatorNames = std::move(operatorInfo);
157 
158     return result;
159 }
160 
makeCellIdentityWcdma(OperatorInfo operatorInfo,const int areaCode,const int cellId)161 CellIdentityWcdma makeCellIdentityWcdma(OperatorInfo operatorInfo,
162                                         const int areaCode, const int cellId) {
163     CellIdentityWcdma result = {
164         .mcc = getMcc(operatorInfo),
165         .mnc = getMnc(operatorInfo),
166         .lac = areaCode,
167         .cid = cellId,
168         .psc = 222,
169         .uarfcn = 777,
170     };
171 
172     result.additionalPlmns.push_back(operatorInfo.operatorNumeric);
173     result.operatorNames = std::move(operatorInfo);
174 
175     return result;
176 }
177 
toOperatorInfo(AtResponse::COPS::OperatorInfo cops)178 OperatorInfo toOperatorInfo(AtResponse::COPS::OperatorInfo cops) {
179     return {
180         .alphaLong = std::move(cops.longName),
181         .alphaShort = std::move(cops.shortName),
182         .operatorNumeric = std::move(cops.numeric),
183         .status = OperatorInfo::STATUS_CURRENT,
184     };
185 }
186 
187 using CellIdentityResult = std::pair<RadioError, CellIdentity>;
188 
getCellIdentityImpl(OperatorInfo operatorInfo,const ratUtils::ModemTechnology mtech,const int areaCode,const int cellId,std::string * plmn)189 CellIdentityResult getCellIdentityImpl(OperatorInfo operatorInfo,
190                                        const ratUtils::ModemTechnology mtech,
191                                        const int areaCode, const int cellId,
192                                        std::string* plmn) {
193     using ratUtils::ModemTechnology;
194 
195     if (plmn) {
196         *plmn = operatorInfo.operatorNumeric;
197     }
198 
199     CellIdentity cellIdentity;
200 
201     switch (mtech) {
202     case ModemTechnology::GSM:
203         cellIdentity.set<CellIdentity::gsm>(makeCellIdentityGsm(std::move(operatorInfo),
204                                                                 areaCode, cellId));
205         break;
206     case ModemTechnology::WCDMA:
207     case ModemTechnology::EVDO:
208         cellIdentity.set<CellIdentity::wcdma>(makeCellIdentityWcdma(std::move(operatorInfo),
209                                                                     areaCode, cellId));
210         break;
211     case ModemTechnology::CDMA:
212         cellIdentity.set<CellIdentity::cdma>(makeCellIdentityCdma(std::move(operatorInfo)));
213         break;
214     case ModemTechnology::TDSCDMA:
215         cellIdentity.set<CellIdentity::tdscdma>(makeCellIdentityTdscdma(std::move(operatorInfo),
216                                                                         areaCode, cellId));
217         break;
218     case ModemTechnology::LTE:
219         cellIdentity.set<CellIdentity::lte>(makeCellIdentityLte(std::move(operatorInfo),
220                                                                 areaCode, cellId));
221         break;
222     case ModemTechnology::NR:
223         cellIdentity.set<CellIdentity::nr>(makeCellIdentityNr(std::move(operatorInfo), areaCode));
224         break;
225     default:
226         return {FAILURE_V(RadioError::INTERNAL_ERR, "Unexpected radio technology: %u",
227                           static_cast<unsigned>(mtech)), {}};
228     };
229 
230     return {RadioError::NONE, std::move(cellIdentity)};
231 }
232 
getCellIdentityImpl(const int areaCode,const int cellId,std::string * plmn,AtChannel::Conversation & atConversation,const AtChannel::RequestPipe requestPipe)233 CellIdentityResult getCellIdentityImpl(const int areaCode, const int cellId, std::string* plmn,
234                                        AtChannel::Conversation& atConversation,
235                                        const AtChannel::RequestPipe requestPipe) {
236     static const auto fail = [](RadioError e) -> CellIdentityResult { return {e, {}}; };
237 
238     using CmeError = AtResponse::CmeError;
239     using COPS = AtResponse::COPS;
240     using CTEC = AtResponse::CTEC;
241     using ratUtils::ModemTechnology;
242 
243     OperatorInfo operatorInfo;
244     AtResponsePtr response =
245         atConversation(requestPipe, atCmds::getOperator,
246                        [](const AtResponse& response) -> bool {
247                            return response.holds<COPS>() || response.holds<CmeError>();
248                        });
249     if (!response || response->isParseError()) {
250         return FAILURE(fail(RadioError::INTERNAL_ERR));
251     } else if (const COPS* cops = response->get_if<COPS>()) {
252         if ((cops->operators.size() == 1) && (cops->operators[0].isCurrent())) {
253             operatorInfo = toOperatorInfo(cops->operators[0]);
254         } else {
255             response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
256         }
257     } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
258         const RadioError status =
259             (cmeError->error == RadioError::OPERATION_NOT_ALLOWED) ?
260                 RadioError::RADIO_NOT_AVAILABLE : cmeError->error;
261 
262         return fail(FAILURE_V(status, "%s", toString(status).c_str()));
263     } else {
264         response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
265     }
266 
267     ModemTechnology mtech;
268     response =
269         atConversation(requestPipe, atCmds::getCurrentPreferredRadioTechs,
270                        [](const AtResponse& response) -> bool {
271                            return response.holds<CTEC>();
272                        });
273     if (!response || response->isParseError()) {
274         return FAILURE(fail(RadioError::INTERNAL_ERR));
275     } else if (const CTEC* ctec = response->get_if<CTEC>()) {
276         mtech = ctec->getCurrentModemTechnology().value();
277     } else {
278         response->unexpected(FAILURE_DEBUG_PREFIX, __func__);
279     }
280 
281     return getCellIdentityImpl(std::move(operatorInfo), mtech,
282                                areaCode, cellId, plmn);
283 }
284 
buildCellInfo(const bool registered,CellIdentity cellIdentity,SignalStrength signalStrength)285 std::pair<RadioError, CellInfo> buildCellInfo(const bool registered,
286                                               CellIdentity cellIdentity,
287                                               SignalStrength signalStrength) {
288     CellInfo cellInfo = {
289         .registered = registered,
290         .connectionStatus = registered ?
291             CellConnectionStatus::PRIMARY_SERVING : CellConnectionStatus::NONE,
292     };
293 
294     switch (cellIdentity.getTag()) {
295     default:
296         return {FAILURE_V(RadioError::INTERNAL_ERR, "%s",
297                           "unexpected getTag"), {}};
298 
299     case CellIdentity::gsm: {
300             CellInfoGsm cellInfoGsm = {
301                 .cellIdentityGsm = std::move(cellIdentity.get<CellIdentity::gsm>()),
302                 .signalStrengthGsm = std::move(signalStrength.gsm),
303             };
304             cellInfo.ratSpecificInfo.set<CellInfoRatSpecificInfo::gsm>(std::move(cellInfoGsm));
305         }
306         break;
307 
308     case CellIdentity::wcdma: {
309             CellInfoWcdma cellInfoWcdma = {
310                 .cellIdentityWcdma = std::move(cellIdentity.get<CellIdentity::wcdma>()),
311                 .signalStrengthWcdma = std::move(signalStrength.wcdma),
312             };
313             cellInfo.ratSpecificInfo.set<CellInfoRatSpecificInfo::wcdma>(std::move(cellInfoWcdma));
314         }
315         break;
316 
317     case CellIdentity::tdscdma: {
318             CellInfoTdscdma cellInfoTdscdma = {
319                 .cellIdentityTdscdma = std::move(cellIdentity.get<CellIdentity::tdscdma>()),
320                 .signalStrengthTdscdma = std::move(signalStrength.tdscdma),
321             };
322             cellInfo.ratSpecificInfo.set<CellInfoRatSpecificInfo::tdscdma>(std::move(cellInfoTdscdma));
323         }
324         break;
325 
326     case CellIdentity::cdma: {
327             CellInfoCdma cellInfoCdma = {
328                 .cellIdentityCdma = std::move(cellIdentity.get<CellIdentity::cdma>()),
329                 .signalStrengthCdma = std::move(signalStrength.cdma),
330             };
331             cellInfo.ratSpecificInfo.set<CellInfoRatSpecificInfo::cdma>(std::move(cellInfoCdma));
332         }
333         break;
334 
335 
336     case CellIdentity::lte: {
337             CellInfoLte cellInfoLte = {
338                 .cellIdentityLte = std::move(cellIdentity.get<CellIdentity::lte>()),
339                 .signalStrengthLte = std::move(signalStrength.lte),
340             };
341             cellInfo.ratSpecificInfo.set<CellInfoRatSpecificInfo::lte>(std::move(cellInfoLte));
342         }
343         break;
344 
345     case CellIdentity::nr: {
346             CellInfoNr cellInfoNr = {
347                 .cellIdentityNr = std::move(cellIdentity.get<CellIdentity::nr>()),
348                 .signalStrengthNr = std::move(signalStrength.nr),
349             };
350             cellInfo.ratSpecificInfo.set<CellInfoRatSpecificInfo::nr>(std::move(cellInfoNr));
351         }
352         break;
353     }
354 
355     return {RadioError::NONE, std::move(cellInfo)};
356 }
357 
setAccessTechnologySpecificInfo(AccessTechnologySpecificInfo * accessTechnologySpecificInfo,const RadioTechnology rat)358 void setAccessTechnologySpecificInfo(
359         AccessTechnologySpecificInfo* accessTechnologySpecificInfo,
360         const RadioTechnology rat) {
361     switch (rat) {
362     case RadioTechnology::LTE:
363     case RadioTechnology::LTE_CA: {
364             EutranRegistrationInfo eri = {
365                 .lteVopsInfo = {
366                     .isVopsSupported = false,
367                     .isEmcBearerSupported = false,
368                 },
369             };
370 
371             accessTechnologySpecificInfo->set<
372                 AccessTechnologySpecificInfo::eutranInfo>(std::move(eri));
373         }
374         break;
375 
376     case RadioTechnology::NR: {
377             EutranRegistrationInfo eri = {
378                 .nrIndicators = {
379                     .isNrAvailable = true,
380                     .isDcNrRestricted = false,
381                     .isEndcAvailable = false,
382                 },
383             };
384 
385             accessTechnologySpecificInfo->set<
386                 AccessTechnologySpecificInfo::eutranInfo>(std::move(eri));
387         }
388         break;
389 
390     case RadioTechnology::HSUPA:
391     case RadioTechnology::HSDPA:
392     case RadioTechnology::HSPA:
393     case RadioTechnology::HSPAP:
394     case RadioTechnology::UMTS:
395     case RadioTechnology::IS95A:
396     case RadioTechnology::IS95B:
397     case RadioTechnology::ONE_X_RTT:
398     case RadioTechnology::EVDO_0:
399     case RadioTechnology::EVDO_A:
400     case RadioTechnology::EVDO_B:
401     case RadioTechnology::EHRPD:
402     case RadioTechnology::TD_SCDMA: {
403             Cdma2000RegistrationInfo cri = {
404                 .systemIsInPrl = Cdma2000RegistrationInfo::PRL_INDICATOR_IN_PRL,
405             };
406 
407             accessTechnologySpecificInfo->set<
408                 AccessTechnologySpecificInfo::cdmaInfo>(std::move(cri));
409         }
410         break;
411 
412     default:
413         break;
414     }
415 }
416 
417 }  // namespace
418 
RadioNetwork(std::shared_ptr<AtChannel> atChannel)419 RadioNetwork::RadioNetwork(std::shared_ptr<AtChannel> atChannel) : mAtChannel(std::move(atChannel)) {
420 }
421 
getAllowedNetworkTypesBitmap(const int32_t serial)422 ScopedAStatus RadioNetwork::getAllowedNetworkTypesBitmap(const int32_t serial) {
423     static const char* const kFunc = __func__;
424     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
425         using CTEC = AtResponse::CTEC;
426 
427         RadioError status = RadioError::NONE;
428         uint32_t networkTypeBitmap = 0;
429 
430         AtResponsePtr response =
431             mAtConversation(requestPipe, atCmds::getCurrentPreferredRadioTechs,
432                             [](const AtResponse& response) -> bool {
433                                 return response.holds<CTEC>();
434                             });
435         if (!response || response->isParseError()) {
436             status = FAILURE(RadioError::INTERNAL_ERR);
437         } else if (const CTEC* ctec = response->get_if<CTEC>()) {
438             networkTypeBitmap =
439                 ratUtils::supportedRadioTechBitmask(
440                     ctec->getCurrentModemTechnology().value());
441         } else {
442             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
443         }
444 
445         NOT_NULL(mRadioNetworkResponse)->getAllowedNetworkTypesBitmapResponse(
446                 makeRadioResponseInfo(serial, status), networkTypeBitmap);
447         return status != RadioError::INTERNAL_ERR;
448     });
449 
450     return ScopedAStatus::ok();
451 }
452 
getAvailableBandModes(const int32_t serial)453 ScopedAStatus RadioNetwork::getAvailableBandModes(const int32_t serial) {
454     using network::RadioBandMode;
455 
456     NOT_NULL(mRadioNetworkResponse)->getAvailableBandModesResponse(
457         makeRadioResponseInfo(serial), {
458             RadioBandMode::BAND_MODE_UNSPECIFIED,
459             RadioBandMode::BAND_MODE_EURO,
460             RadioBandMode::BAND_MODE_USA,
461             RadioBandMode::BAND_MODE_JPN,
462             RadioBandMode::BAND_MODE_AUS,
463             RadioBandMode::BAND_MODE_USA_2500M,
464         });
465     return ScopedAStatus::ok();
466 }
467 
getAvailableNetworks(const int32_t serial)468 ScopedAStatus RadioNetwork::getAvailableNetworks(const int32_t serial) {
469     NOT_NULL(mRadioNetworkResponse)->getAvailableNetworksResponse(
470         makeRadioResponseInfoUnsupported(  // matches reference-ril.c
471             serial, FAILURE_DEBUG_PREFIX, __func__), {});
472     return ScopedAStatus::ok();
473 }
474 
getBarringInfo(const int32_t serial)475 ScopedAStatus RadioNetwork::getBarringInfo(const int32_t serial) {
476     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
477         int areaCode;
478         int cellId;
479         {
480             std::lock_guard<std::mutex> lock(mMtx);
481             areaCode = mCreg.areaCode;
482             cellId = mCreg.cellId;
483         }
484 
485         CellIdentityResult cellIdentityResult =
486             getCellIdentityImpl(areaCode, cellId, nullptr, mAtConversation, requestPipe);
487         if (cellIdentityResult.first == RadioError::NONE) {
488             using network::BarringInfo;
489 
490             BarringInfo barringInfoCs = {
491                 .serviceType = BarringInfo::SERVICE_TYPE_CS_SERVICE,
492                 .barringType = BarringInfo::BARRING_TYPE_NONE,
493             };
494 
495             BarringInfo barringInfoPs = {
496                 .serviceType = BarringInfo::SERVICE_TYPE_PS_SERVICE,
497                 .barringType = BarringInfo::BARRING_TYPE_NONE,
498             };
499 
500             BarringInfo barringInfoCsVoice = {
501                 .serviceType = BarringInfo::SERVICE_TYPE_CS_VOICE,
502                 .barringType = BarringInfo::BARRING_TYPE_NONE,
503             };
504 
505             BarringInfo barringInfoEmergency = {
506                 .serviceType = BarringInfo::SERVICE_TYPE_EMERGENCY,
507                 .barringType = BarringInfo::BARRING_TYPE_NONE,
508             };
509 
510             NOT_NULL(mRadioNetworkResponse)->getBarringInfoResponse(
511                     makeRadioResponseInfo(serial),
512                     std::move(cellIdentityResult.second),
513                     {
514                         std::move(barringInfoCs),
515                         std::move(barringInfoPs),
516                         std::move(barringInfoCsVoice),
517                         std::move(barringInfoEmergency),
518                     });
519             return true;
520         } else {
521             NOT_NULL(mRadioNetworkResponse)->getBarringInfoResponse(
522                     makeRadioResponseInfo(serial,
523                                           FAILURE_V(cellIdentityResult.first, "%s",
524                                                     toString(cellIdentityResult.first).c_str())),
525                     {}, {});
526             return cellIdentityResult.first != RadioError::INTERNAL_ERR;
527         }
528     });
529 
530     return ScopedAStatus::ok();
531 }
532 
getCdmaRoamingPreference(const int32_t serial)533 ScopedAStatus RadioNetwork::getCdmaRoamingPreference(const int32_t serial) {
534     static const char* const kFunc = __func__;
535     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
536         using WRMP = AtResponse::WRMP;
537         using network::CdmaRoamingType;
538 
539         RadioError status = RadioError::NONE;
540         CdmaRoamingType cdmaRoamingPreference = CdmaRoamingType::HOME_NETWORK;
541 
542         AtResponsePtr response =
543             mAtConversation(requestPipe, atCmds::getCdmaRoamingPreference,
544                             [](const AtResponse& response) -> bool {
545                                return response.holds<WRMP>();
546                             });
547         if (!response || response->isParseError()) {
548             status = FAILURE(RadioError::INTERNAL_ERR);
549         } else if (const WRMP* wrmp = response->get_if<WRMP>()) {
550             cdmaRoamingPreference = wrmp->cdmaRoamingPreference;
551         } else {
552             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
553         }
554 
555         NOT_NULL(mRadioNetworkResponse)->getCdmaRoamingPreferenceResponse(
556             makeRadioResponseInfo(serial, status), cdmaRoamingPreference);
557         return status != RadioError::INTERNAL_ERR;
558     });
559 
560     return ScopedAStatus::ok();
561 }
562 
getCellInfoList(const int32_t serial)563 ScopedAStatus RadioNetwork::getCellInfoList(const int32_t serial) {
564     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
565         SignalStrength signalStrength;
566         int areaCode;
567         int cellId;
568         bool registered;
569         {
570             std::lock_guard<std::mutex> lock(mMtx);
571             signalStrength = mCsq.toSignalStrength();
572             areaCode = mCreg.areaCode;
573             cellId = mCreg.cellId;
574             registered = (mCreg.state == network::RegState::REG_HOME);
575         }
576 
577         RadioError status;
578         CellIdentity cellIdentity;
579         CellInfo cellInfo;
580 
581         std::tie(status, cellIdentity) =
582             getCellIdentityImpl(areaCode, cellId, nullptr, mAtConversation, requestPipe);
583         if (status == RadioError::NONE) {
584             std::tie(status, cellInfo) = buildCellInfo(registered,
585                                                        std::move(cellIdentity),
586                                                        std::move(signalStrength));
587 
588             if (status == RadioError::NONE) {
589                 NOT_NULL(mRadioNetworkResponse)->getCellInfoListResponse(
590                     makeRadioResponseInfo(serial), { std::move(cellInfo) });
591                 return true;
592             }
593         }
594 
595         NOT_NULL(mRadioNetworkResponse)->getCellInfoListResponse(
596             makeRadioResponseInfo(serial, status), {});
597         return status != RadioError::INTERNAL_ERR;
598     });
599 
600     return ScopedAStatus::ok();
601 }
602 
getDataRegistrationState(const int32_t serial)603 ScopedAStatus RadioNetwork::getDataRegistrationState(const int32_t serial) {
604     static const char* const kFunc = __func__;
605     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
606         using CTEC = AtResponse::CTEC;
607 
608         RadioError status = RadioError::NONE;
609         RegStateResult regStateResult;
610         int areaCode;
611         int cellId;
612 
613         {
614             std::lock_guard<std::mutex> lock(mMtx);
615             regStateResult.regState = mCreg.state;
616             areaCode = mCreg.areaCode;
617             cellId = mCreg.cellId;
618         }
619 
620         std::tie(status, regStateResult.cellIdentity) =
621             getCellIdentityImpl(areaCode, cellId, &regStateResult.registeredPlmn,
622                                 mAtConversation, requestPipe);
623         if (status != RadioError::NONE) {
624             goto failed;
625         }
626 
627         {
628             AtResponsePtr response =
629                 mAtConversation(requestPipe, atCmds::getCurrentPreferredRadioTechs,
630                                 [](const AtResponse& response) -> bool {
631                                    return response.holds<CTEC>();
632                                 });
633             if (!response || response->isParseError()) {
634                 status = FAILURE(RadioError::INTERNAL_ERR);
635                 goto failed;
636             } else if (const CTEC* ctec = response->get_if<CTEC>()) {
637                 regStateResult.rat =
638                     ratUtils::currentRadioTechnology(
639                         ctec->getCurrentModemTechnology().value());
640             } else {
641                 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
642             }
643         }
644 
645         setAccessTechnologySpecificInfo(
646             &regStateResult.accessTechnologySpecificInfo,
647             regStateResult.rat);
648 
649         if (status == RadioError::NONE) {
650             NOT_NULL(mRadioNetworkResponse)->getDataRegistrationStateResponse(
651                 makeRadioResponseInfo(serial), std::move(regStateResult));
652             return true;
653         } else {
654 failed:     NOT_NULL(mRadioNetworkResponse)->getDataRegistrationStateResponse(
655                 makeRadioResponseInfo(serial, status), {});
656             return status != RadioError::INTERNAL_ERR;
657         }
658     });
659 
660     return ScopedAStatus::ok();
661 }
662 
getNetworkSelectionMode(const int32_t serial)663 ScopedAStatus RadioNetwork::getNetworkSelectionMode(const int32_t serial) {
664     static const char* const kFunc = __func__;
665     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
666         using CmeError = AtResponse::CmeError;
667         using COPS = AtResponse::COPS;
668 
669         RadioError status = RadioError::NONE;
670         bool manual = true;
671 
672         const AtResponsePtr response =
673             mAtConversation(requestPipe, atCmds::getNetworkSelectionMode,
674                             [](const AtResponse& response) -> bool {
675                                return response.holds<COPS>() || response.holds<CmeError>();
676                             });
677         if (!response || response->isParseError()) {
678             status = FAILURE(RadioError::INTERNAL_ERR);
679         } else if (const COPS* cops = response->get_if<COPS>()) {
680             manual = (cops->networkSelectionMode == COPS::NetworkSelectionMode::MANUAL);
681         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
682             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
683         } else {
684             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
685         }
686 
687         NOT_NULL(mRadioNetworkResponse)->getNetworkSelectionModeResponse(
688                 makeRadioResponseInfo(serial, status), manual);
689         return status != RadioError::INTERNAL_ERR;
690     });
691 
692     return ScopedAStatus::ok();
693 }
694 
getOperator(const int32_t serial)695 ScopedAStatus RadioNetwork::getOperator(const int32_t serial) {
696     static const char* const kFunc = __func__;
697     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
698         using CmeError = AtResponse::CmeError;
699         using COPS = AtResponse::COPS;
700 
701         RadioError status = RadioError::NONE;
702         std::string longName;
703         std::string shortName;
704         std::string numeric;
705 
706         const AtResponsePtr response =
707             mAtConversation(requestPipe, atCmds::getOperator,
708                             [](const AtResponse& response) -> bool {
709                                return response.holds<COPS>() || response.holds<CmeError>();
710                             });
711         if (!response || response->isParseError()) {
712             status = FAILURE(RadioError::INTERNAL_ERR);
713         } else if (const COPS* cops = response->get_if<COPS>()) {
714             if ((cops->operators.size() == 1) && (cops->operators[0].isCurrent())) {
715                 const COPS::OperatorInfo& current = cops->operators[0];
716 
717                 longName = current.longName;
718                 shortName = current.shortName;
719                 numeric = current.numeric;
720             } else {
721                 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
722             }
723         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
724             status = (cmeError->error == RadioError::OPERATION_NOT_ALLOWED) ?
725                     RadioError::RADIO_NOT_AVAILABLE : cmeError->error;
726         } else {
727             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
728         }
729 
730         NOT_NULL(mRadioNetworkResponse)->getOperatorResponse(
731                 makeRadioResponseInfo(serial, status),
732                 std::move(longName), std::move(shortName), std::move(numeric));
733         return status != RadioError::INTERNAL_ERR;
734     });
735 
736     return ScopedAStatus::ok();
737 }
738 
getSignalStrength(const int32_t serial)739 ScopedAStatus RadioNetwork::getSignalStrength(const int32_t serial) {
740     network::SignalStrength signalStrength;
741 
742     RadioError status;
743     {
744         std::lock_guard<std::mutex> lock(mMtx);
745         signalStrength = mCsq.toSignalStrength();
746         status = (mRadioState == modem::RadioState::ON) ?
747             RadioError::NONE : FAILURE(RadioError::RADIO_NOT_AVAILABLE);
748     }
749 
750     NOT_NULL(mRadioNetworkResponse)->getSignalStrengthResponse(
751             makeRadioResponseInfo(serial, status), std::move(signalStrength));
752     return ScopedAStatus::ok();
753 }
754 
getSystemSelectionChannels(const int32_t serial)755 ScopedAStatus RadioNetwork::getSystemSelectionChannels(const int32_t serial) {
756     NOT_NULL(mRadioNetworkResponse)->getSystemSelectionChannelsResponse(
757             makeRadioResponseInfoNOP(serial), {});
758     return ScopedAStatus::ok();
759 }
760 
getVoiceRadioTechnology(const int32_t serial)761 ScopedAStatus RadioNetwork::getVoiceRadioTechnology(const int32_t serial) {
762     static const char* const kFunc = __func__;
763     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
764         using CTEC = AtResponse::CTEC;
765 
766         AtResponsePtr response =
767             mAtConversation(requestPipe, atCmds::getCurrentPreferredRadioTechs,
768                             [](const AtResponse& response) -> bool {
769                                return response.holds<CTEC>();
770                             });
771         if (!response || response->isParseError()) {
772             NOT_NULL(mRadioNetworkResponse)->getVoiceRadioTechnologyResponse(
773                 makeRadioResponseInfo(serial, FAILURE(RadioError::INTERNAL_ERR)), {});
774             return false;
775         } else if (const CTEC* ctec = response->get_if<CTEC>()) {
776             NOT_NULL(mRadioNetworkResponse)->getVoiceRadioTechnologyResponse(
777                 makeRadioResponseInfo(serial),
778                 ratUtils::currentRadioTechnology(
779                     ctec->getCurrentModemTechnology().value()));
780             return true;
781         } else {
782             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
783         }
784     });
785 
786     return ScopedAStatus::ok();
787 }
788 
getVoiceRegistrationState(const int32_t serial)789 ScopedAStatus RadioNetwork::getVoiceRegistrationState(const int32_t serial) {
790     static const char* const kFunc = __func__;
791     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
792         using CTEC = AtResponse::CTEC;
793 
794         RadioError status = RadioError::NONE;
795         RegStateResult regStateResult;
796         int areaCode;
797         int cellId;
798 
799         {
800             std::lock_guard<std::mutex> lock(mMtx);
801             regStateResult.regState = mCreg.state;
802             areaCode = mCreg.areaCode;
803             cellId = mCreg.cellId;
804         }
805 
806         CellIdentityResult cellIdentityResult =
807             getCellIdentityImpl(areaCode, cellId, &regStateResult.registeredPlmn,
808                                 mAtConversation, requestPipe);
809         if (cellIdentityResult.first == RadioError::NONE) {
810             regStateResult.cellIdentity = std::move(cellIdentityResult.second);
811         } else {
812             status = cellIdentityResult.first;
813             goto failed;
814         }
815 
816         {
817             AtResponsePtr response =
818                 mAtConversation(requestPipe, atCmds::getCurrentPreferredRadioTechs,
819                                 [](const AtResponse& response) -> bool {
820                                    return response.holds<CTEC>();
821                                 });
822             if (!response || response->isParseError()) {
823                 status = FAILURE(RadioError::INTERNAL_ERR);
824                 goto failed;
825             } else if (const CTEC* ctec = response->get_if<CTEC>()) {
826                 regStateResult.rat =
827                     ratUtils::currentRadioTechnology(
828                         ctec->getCurrentModemTechnology().value());
829             } else {
830                 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
831             }
832         }
833 
834         setAccessTechnologySpecificInfo(
835             &regStateResult.accessTechnologySpecificInfo,
836             regStateResult.rat);
837 
838         if (status == RadioError::NONE) {
839             NOT_NULL(mRadioNetworkResponse)->getVoiceRegistrationStateResponse(
840                 makeRadioResponseInfo(serial), std::move(regStateResult));
841             return true;
842         } else {
843 failed:     NOT_NULL(mRadioNetworkResponse)->getVoiceRegistrationStateResponse(
844                 makeRadioResponseInfo(serial, status), {});
845             return status != RadioError::INTERNAL_ERR;
846         }
847     });
848 
849     return ScopedAStatus::ok();
850 }
851 
isNrDualConnectivityEnabled(const int32_t serial)852 ScopedAStatus RadioNetwork::isNrDualConnectivityEnabled(const int32_t serial) {
853     bool enabled;
854     {
855         std::lock_guard<std::mutex> lock(mMtx);
856         enabled = mIsNrDualConnectivityEnabled;
857     }
858 
859     NOT_NULL(mRadioNetworkResponse)->isNrDualConnectivityEnabledResponse(
860             makeRadioResponseInfo(serial), enabled);
861     return ScopedAStatus::ok();
862 }
863 
setAllowedNetworkTypesBitmap(const int32_t serial,const int32_t networkTypeBitmap)864 ScopedAStatus RadioNetwork::setAllowedNetworkTypesBitmap(const int32_t serial,
865                                                          const int32_t networkTypeBitmap) {
866     static const char* const kFunc = __func__;
867     mAtChannel->queueRequester([this, serial, networkTypeBitmap]
868                                (const AtChannel::RequestPipe requestPipe) -> bool {
869         using CTEC = AtResponse::CTEC;
870 
871         RadioError status = RadioError::NONE;
872 
873         const ratUtils::ModemTechnology currentTech =
874             ratUtils::modemTechnologyFromRadioTechnologyBitmask(networkTypeBitmap);
875         const uint32_t techBitmask =
876             ratUtils::modemTechnologyBitmaskFromRadioTechnologyBitmask(networkTypeBitmap);
877 
878         const std::string request = std::format("AT+CTEC={0:d},\"{1:X}\"",
879             (1 << static_cast<int>(currentTech)), techBitmask);
880         const AtResponsePtr response =
881             mAtConversation(requestPipe, request,
882                             [](const AtResponse& response) -> bool {
883                                return response.holds<CTEC>();
884                             });
885         if (!response || response->isParseError()) {
886             status = FAILURE(RadioError::INTERNAL_ERR);
887         } else if (!response->get_if<CTEC>()) {
888             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
889         }
890 
891         NOT_NULL(mRadioNetworkResponse)->setAllowedNetworkTypesBitmapResponse(
892             makeRadioResponseInfo(serial, status));
893 
894         if (mRadioNetworkIndication) {
895             mRadioNetworkIndication->voiceRadioTechChanged(
896                 RadioIndicationType::UNSOLICITED,
897                 ratUtils::currentRadioTechnology(currentTech));
898         }
899         return status != RadioError::INTERNAL_ERR;
900     });
901 
902     return ScopedAStatus::ok();
903 }
904 
setBandMode(const int32_t serial,const network::RadioBandMode)905 ScopedAStatus RadioNetwork::setBandMode(const int32_t serial,
906                                         const network::RadioBandMode /*mode*/) {
907     NOT_NULL(mRadioNetworkResponse)->setBandModeResponse(
908         makeRadioResponseInfoNOP(serial));
909     return ScopedAStatus::ok();
910 }
911 
setBarringPassword(const int32_t serial,const std::string & facility,const std::string & oldPassword,const std::string & newPassword)912 ScopedAStatus RadioNetwork::setBarringPassword(const int32_t serial,
913                                                const std::string& facility,
914                                                const std::string& oldPassword,
915                                                const std::string& newPassword) {
916     static const char* const kFunc = __func__;
917     mAtChannel->queueRequester([this, serial, facility, oldPassword, newPassword]
918                                (const AtChannel::RequestPipe requestPipe) -> bool {
919         using CmeError = AtResponse::CmeError;
920         RadioError status = RadioError::NONE;
921 
922         const std::string request =
923             std::format("AT+CPWD=\"{0:s}\",\"{1:s}\",\"{2:s}\"",
924                         facility, oldPassword, newPassword);
925 
926         const AtResponsePtr response =
927             mAtConversation(requestPipe, request,
928                             [](const AtResponse& response) -> bool {
929                                return response.isOK() || response.holds<CmeError>();
930                             });
931         if (!response || response->isParseError()) {
932             status = FAILURE(RadioError::INTERNAL_ERR);
933         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
934             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
935         } else if (!response->isOK()) {
936             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
937         }
938 
939         NOT_NULL(mRadioNetworkResponse)->setBarringPasswordResponse(
940             makeRadioResponseInfo(serial, status));
941         return status != RadioError::INTERNAL_ERR;
942     });
943 
944     return ScopedAStatus::ok();
945 }
946 
setCdmaRoamingPreference(const int32_t serial,const network::CdmaRoamingType type)947 ScopedAStatus RadioNetwork::setCdmaRoamingPreference(const int32_t serial,
948                                                      const network::CdmaRoamingType type) {
949     static const char* const kFunc = __func__;
950     mAtChannel->queueRequester([this, serial, type]
951                                (const AtChannel::RequestPipe requestPipe) -> bool {
952         RadioError status = RadioError::NONE;
953 
954         const std::string request =
955             std::format("AT+WRMP={0:d}", static_cast<unsigned>(type));
956         const AtResponsePtr response =
957             mAtConversation(requestPipe, request,
958                             [](const AtResponse& response) -> bool {
959                                return response.isOK();
960                             });
961         if (!response || response->isParseError()) {
962             status = FAILURE(RadioError::INTERNAL_ERR);
963         } else if (!response->isOK()) {
964             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
965         }
966 
967         NOT_NULL(mRadioNetworkResponse)->setCdmaRoamingPreferenceResponse(
968             makeRadioResponseInfo(serial, status));
969         return status != RadioError::INTERNAL_ERR;
970     });
971 
972     return ScopedAStatus::ok();
973 }
974 
setCellInfoListRate(const int32_t serial,const int32_t)975 ScopedAStatus RadioNetwork::setCellInfoListRate(const int32_t serial,
976                                                 const int32_t /*rate*/) {
977     NOT_NULL(mRadioNetworkResponse)->setCellInfoListRateResponse(
978         makeRadioResponseInfoNOP(serial));
979     return ScopedAStatus::ok();
980 }
981 
setIndicationFilter(const int32_t serial,const int32_t)982 ScopedAStatus RadioNetwork::setIndicationFilter(const int32_t serial,
983                                                 const int32_t /*indicationFilter*/) {
984     NOT_NULL(mRadioNetworkResponse)->setIndicationFilterResponse(
985             makeRadioResponseInfoNOP(serial));
986     return ScopedAStatus::ok();
987 }
988 
setLinkCapacityReportingCriteria(const int32_t serial,const int32_t,const int32_t,const int32_t,const std::vector<int32_t> &,const std::vector<int32_t> &,const AccessNetwork)989 ScopedAStatus RadioNetwork::setLinkCapacityReportingCriteria(const int32_t serial,
990                                                              const int32_t /*hysteresisMs*/,
991                                                              const int32_t /*hysteresisDlKbps*/,
992                                                              const int32_t /*hysteresisUlKbps*/,
993                                                              const std::vector<int32_t>& /*thresholdsDownlinkKbps*/,
994                                                              const std::vector<int32_t>& /*thresholdsUplinkKbps*/,
995                                                              const AccessNetwork /*accessNetwork*/) {
996     NOT_NULL(mRadioNetworkResponse)->setLinkCapacityReportingCriteriaResponse(
997             makeRadioResponseInfoNOP(serial));
998 
999     return ScopedAStatus::ok();
1000 }
1001 
setLocationUpdates(const int32_t serial,const bool)1002 ScopedAStatus RadioNetwork::setLocationUpdates(const int32_t serial,
1003                                                const bool /*enable*/) {
1004     NOT_NULL(mRadioNetworkResponse)->setLocationUpdatesResponse(
1005         makeRadioResponseInfoNOP(serial));
1006     return ScopedAStatus::ok();
1007 }
1008 
setNetworkSelectionModeAutomatic(const int32_t serial)1009 ScopedAStatus RadioNetwork::setNetworkSelectionModeAutomatic(const int32_t serial) {
1010     static const char* const kFunc = __func__;
1011     mAtChannel->queueRequester([this, serial]
1012                                (const AtChannel::RequestPipe requestPipe) -> bool {
1013         RadioError status = RadioError::NONE;
1014 
1015         AtResponsePtr response =
1016             mAtConversation(requestPipe, atCmds::setNetworkSelectionModeAutomatic,
1017                             [](const AtResponse& response) -> bool {
1018                                return response.isOK();
1019                             });
1020         if (!response || response->isParseError()) {
1021             status = FAILURE(RadioError::INTERNAL_ERR);
1022         } else if (!response->isOK()) {
1023             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1024         }
1025 
1026         NOT_NULL(mRadioNetworkResponse)->setNetworkSelectionModeAutomaticResponse(
1027             makeRadioResponseInfo(serial, status));
1028         return status != RadioError::INTERNAL_ERR;
1029     });
1030 
1031     return ScopedAStatus::ok();
1032 }
1033 
setNetworkSelectionModeManual(const int32_t serial,const std::string & operatorNumeric,const radio::AccessNetwork ran)1034 ScopedAStatus RadioNetwork::setNetworkSelectionModeManual(const int32_t serial,
1035                                                           const std::string& operatorNumeric,
1036                                                           const radio::AccessNetwork ran) {
1037     static const char* const kFunc = __func__;
1038     mAtChannel->queueRequester([this, serial, operatorNumeric, ran]
1039                                (const AtChannel::RequestPipe requestPipe) -> bool {
1040         using CmeError = AtResponse::CmeError;
1041 
1042         RadioError status = RadioError::NONE;
1043 
1044         std::string request;
1045         if (ran != radio::AccessNetwork::UNKNOWN) {
1046             request = std::format("AT+COPS={0:d},{1:d},\"{2:s}\",{3:d}",
1047                                   1, 2, operatorNumeric, static_cast<unsigned>(ran));
1048         } else {
1049             request = std::format("AT+COPS={0:d},{1:d},\"{2:s}\"",
1050                                   1, 2, operatorNumeric);
1051         }
1052 
1053         AtResponsePtr response =
1054             mAtConversation(requestPipe, request,
1055                             [](const AtResponse& response) -> bool {
1056                                return response.isOK() || response.holds<CmeError>();
1057                             });
1058         if (!response || response->isParseError()) {
1059             status = FAILURE(RadioError::INTERNAL_ERR);
1060         } else if (response->isOK()) {
1061             // good
1062         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
1063             status = cmeError->getErrorAndLog(FAILURE_DEBUG_PREFIX, kFunc, __LINE__);
1064         } else {
1065             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1066         }
1067 
1068         NOT_NULL(mRadioNetworkResponse)->setNetworkSelectionModeManualResponse(
1069             makeRadioResponseInfo(serial, status));
1070         return status != RadioError::INTERNAL_ERR;
1071     });
1072 
1073     return ScopedAStatus::ok();
1074 }
1075 
setNrDualConnectivityState(const int32_t serial,const network::NrDualConnectivityState nrSt)1076 ScopedAStatus RadioNetwork::setNrDualConnectivityState(const int32_t serial,
1077                                                        const network::NrDualConnectivityState nrSt) {
1078     {
1079         std::lock_guard<std::mutex> lock(mMtx);
1080         mIsNrDualConnectivityEnabled =
1081             (nrSt == network::NrDualConnectivityState::ENABLE);
1082     }
1083 
1084     NOT_NULL(mRadioNetworkResponse)->setNrDualConnectivityStateResponse(
1085             makeRadioResponseInfo(serial));
1086     return ScopedAStatus::ok();
1087 }
1088 
setSignalStrengthReportingCriteria(const int32_t serial,const std::vector<network::SignalThresholdInfo> &)1089 ScopedAStatus RadioNetwork::setSignalStrengthReportingCriteria(const int32_t serial,
1090                                                                const std::vector<network::SignalThresholdInfo>& /*signalThresholdInfos*/) {
1091     NOT_NULL(mRadioNetworkResponse)->setSignalStrengthReportingCriteriaResponse(
1092             makeRadioResponseInfoNOP(serial));
1093     return ScopedAStatus::ok();
1094 }
1095 
setSuppServiceNotifications(const int32_t serial,const bool enable)1096 ScopedAStatus RadioNetwork::setSuppServiceNotifications(const int32_t serial,
1097                                                         const bool enable) {
1098     static const char* const kFunc = __func__;
1099     mAtChannel->queueRequester([this, serial, enable]
1100                                (const AtChannel::RequestPipe requestPipe) -> bool {
1101         RadioError status = RadioError::NONE;
1102 
1103         const int enableInt = enable ? 1 : 0;
1104         const std::string request = std::format("AT+CSSN={0:d},{1:d}",
1105             enableInt, enableInt);
1106 
1107         AtResponsePtr response =
1108             mAtConversation(requestPipe, request,
1109                             [](const AtResponse& response) -> bool {
1110                                return response.isOK();
1111                             });
1112         if (!response || response->isParseError()) {
1113             status = FAILURE(RadioError::INTERNAL_ERR);
1114         } else if (!response->isOK()) {
1115             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
1116         }
1117 
1118         NOT_NULL(mRadioNetworkResponse)->setSuppServiceNotificationsResponse(
1119             makeRadioResponseInfo(serial, status));
1120         return status != RadioError::INTERNAL_ERR;
1121     });
1122 
1123     return ScopedAStatus::ok();
1124 }
1125 
setSystemSelectionChannels(const int32_t serial,const bool,const std::vector<network::RadioAccessSpecifier> &)1126 ScopedAStatus RadioNetwork::setSystemSelectionChannels(const int32_t serial,
1127                                                        const bool /*specifyChannels*/,
1128                                                        const std::vector<network::RadioAccessSpecifier>& /*specifiers*/) {
1129     NOT_NULL(mRadioNetworkResponse)->setSystemSelectionChannelsResponse(
1130             makeRadioResponseInfoNOP(serial));
1131     return ScopedAStatus::ok();
1132 }
1133 
startNetworkScan(const int32_t serial,const network::NetworkScanRequest &)1134 ScopedAStatus RadioNetwork::startNetworkScan(const int32_t serial,
1135                                              const network::NetworkScanRequest& /*request*/) {
1136     using network::NetworkScanResult;
1137 
1138     NOT_NULL(mRadioNetworkResponse)->startNetworkScanResponse(
1139         makeRadioResponseInfoNOP(serial));
1140     if (mRadioNetworkIndication) {
1141         using namespace std::chrono_literals;
1142         std::this_thread::sleep_for(2000ms);
1143 
1144         mRadioNetworkIndication->networkScanResult(
1145             RadioIndicationType::UNSOLICITED,
1146             { .status = NetworkScanResult::SCAN_STATUS_COMPLETE });
1147     }
1148     return ScopedAStatus::ok();
1149 }
1150 
stopNetworkScan(const int32_t serial)1151 ScopedAStatus RadioNetwork::stopNetworkScan(const int32_t serial) {
1152     NOT_NULL(mRadioNetworkResponse)->stopNetworkScanResponse(
1153         makeRadioResponseInfoNOP(serial));
1154     return ScopedAStatus::ok();
1155 }
1156 
supplyNetworkDepersonalization(const int32_t serial,const std::string &)1157 ScopedAStatus RadioNetwork::supplyNetworkDepersonalization(const int32_t serial,
1158                                                            const std::string& /*netPin*/) {
1159     NOT_NULL(mRadioNetworkResponse)->supplyNetworkDepersonalizationResponse(
1160         makeRadioResponseInfoNOP(serial), -1);
1161     return ScopedAStatus::ok();
1162 }
1163 
setUsageSetting(const int32_t serial,const network::UsageSetting)1164 ScopedAStatus RadioNetwork::setUsageSetting(const int32_t serial,
1165                                             const network::UsageSetting /*usageSetting*/) {
1166     NOT_NULL(mRadioNetworkResponse)->setUsageSettingResponse(
1167             makeRadioResponseInfoNOP(serial));
1168     return ScopedAStatus::ok();
1169 }
1170 
getUsageSetting(const int32_t serial)1171 ScopedAStatus RadioNetwork::getUsageSetting(const int32_t serial) {
1172     NOT_NULL(mRadioNetworkResponse)->getUsageSettingResponse(
1173             makeRadioResponseInfo(serial),
1174             network::UsageSetting::VOICE_CENTRIC);
1175     return ScopedAStatus::ok();
1176 }
1177 
setEmergencyMode(const int32_t serial,const network::EmergencyMode)1178 ScopedAStatus RadioNetwork::setEmergencyMode(const int32_t serial,
1179                                              const network::EmergencyMode /*emergencyMode*/) {
1180     using network::Domain;
1181     using network::EmergencyRegResult;
1182     using network::RegState;
1183 
1184     EmergencyRegResult emergencyRegResult = {
1185         .accessNetwork = AccessNetwork::EUTRAN,
1186         .regState = RegState::REG_HOME,
1187         .emcDomain = static_cast<Domain>(
1188             static_cast<uint32_t>(Domain::CS) |
1189             static_cast<uint32_t>(Domain::PS)),
1190     };
1191 
1192     NOT_NULL(mRadioNetworkResponse)->setEmergencyModeResponse(
1193         makeRadioResponseInfo(serial), std::move(emergencyRegResult));
1194     return ScopedAStatus::ok();
1195 }
1196 
triggerEmergencyNetworkScan(const int32_t serial,const network::EmergencyNetworkScanTrigger &)1197 ScopedAStatus RadioNetwork::triggerEmergencyNetworkScan(const int32_t serial,
1198                                                         const network::EmergencyNetworkScanTrigger& /*scanTrigger*/) {
1199     NOT_NULL(mRadioNetworkResponse)->triggerEmergencyNetworkScanResponse(
1200         makeRadioResponseInfoNOP(serial));
1201     return ScopedAStatus::ok();
1202 }
1203 
cancelEmergencyNetworkScan(const int32_t serial,const bool)1204 ScopedAStatus RadioNetwork::cancelEmergencyNetworkScan(const int32_t serial,
1205                                                        const bool /*resetScan*/) {
1206     NOT_NULL(mRadioNetworkResponse)->cancelEmergencyNetworkScanResponse(
1207         makeRadioResponseInfoNOP(serial));
1208     return ScopedAStatus::ok();
1209 }
1210 
exitEmergencyMode(const int32_t serial)1211 ScopedAStatus RadioNetwork::exitEmergencyMode(const int32_t serial) {
1212     NOT_NULL(mRadioNetworkResponse)->exitEmergencyModeResponse(
1213         makeRadioResponseInfoNOP(serial));
1214     return ScopedAStatus::ok();
1215 }
1216 
isN1ModeEnabled(const int32_t serial)1217 ScopedAStatus RadioNetwork::isN1ModeEnabled(const int32_t serial) {
1218     bool enabled;
1219     {
1220         std::lock_guard<std::mutex> lock(mMtx);
1221         enabled = mIsN1ModeEnabled;
1222     }
1223 
1224     NOT_NULL(mRadioNetworkResponse)->isN1ModeEnabledResponse(
1225             makeRadioResponseInfo(serial), enabled);
1226     return ScopedAStatus::ok();
1227 }
1228 
setN1ModeEnabled(const int32_t serial,const bool enable)1229 ScopedAStatus RadioNetwork::setN1ModeEnabled(const int32_t serial,
1230                                              const bool enable) {
1231     {
1232         std::lock_guard<std::mutex> lock(mMtx);
1233         mIsN1ModeEnabled = enable;
1234     }
1235 
1236     NOT_NULL(mRadioNetworkResponse)->setN1ModeEnabledResponse(
1237             makeRadioResponseInfo(serial));
1238     return ScopedAStatus::ok();
1239 }
1240 
setNullCipherAndIntegrityEnabled(const int32_t serial,const bool enabled)1241 ScopedAStatus RadioNetwork::setNullCipherAndIntegrityEnabled(const int32_t serial,
1242                                                              const bool enabled) {
1243     {
1244         std::lock_guard<std::mutex> lock(mMtx);
1245         mNullCipherAndIntegrityEnabled = enabled;
1246     }
1247 
1248     NOT_NULL(mRadioNetworkResponse)->setNullCipherAndIntegrityEnabledResponse(
1249             makeRadioResponseInfo(serial, RadioError::NONE));
1250     return ScopedAStatus::ok();
1251 }
1252 
isNullCipherAndIntegrityEnabled(const int32_t serial)1253 ScopedAStatus RadioNetwork::isNullCipherAndIntegrityEnabled(const int32_t serial) {
1254     NOT_NULL(mRadioNetworkResponse)->isNullCipherAndIntegrityEnabledResponse(
1255             makeRadioResponseInfo(serial), mNullCipherAndIntegrityEnabled);
1256     return ScopedAStatus::ok();
1257 }
1258 
isCellularIdentifierTransparencyEnabled(const int32_t serial)1259 ScopedAStatus RadioNetwork::isCellularIdentifierTransparencyEnabled(const int32_t serial) {
1260     bool enabled;
1261     {
1262         std::lock_guard<std::mutex> lock(mMtx);
1263         enabled = mIsCellularIdentifierTransparencyEnabled;
1264     }
1265 
1266     NOT_NULL(mRadioNetworkResponse)->isCellularIdentifierTransparencyEnabledResponse(
1267             makeRadioResponseInfo(serial), enabled);
1268     return ScopedAStatus::ok();
1269 }
1270 
setCellularIdentifierTransparencyEnabled(const int32_t serial,const bool enabled)1271 ScopedAStatus RadioNetwork::setCellularIdentifierTransparencyEnabled(const int32_t serial,
1272                                                                      const bool enabled) {
1273     {
1274         std::lock_guard<std::mutex> lock(mMtx);
1275         mIsCellularIdentifierTransparencyEnabled = enabled;
1276     }
1277 
1278     NOT_NULL(mRadioNetworkResponse)->setCellularIdentifierTransparencyEnabledResponse(
1279             makeRadioResponseInfo(serial));
1280     return ScopedAStatus::ok();
1281 }
1282 
setSecurityAlgorithmsUpdatedEnabled(const int32_t serial,const bool enabled)1283 ScopedAStatus RadioNetwork::setSecurityAlgorithmsUpdatedEnabled(const int32_t serial,
1284                                                                 const bool enabled) {
1285     {
1286         std::lock_guard<std::mutex> lock(mMtx);
1287         mSecurityAlgorithmsUpdatedEnabled = enabled;
1288     }
1289 
1290     NOT_NULL(mRadioNetworkResponse)->setSecurityAlgorithmsUpdatedEnabledResponse(
1291             makeRadioResponseInfo(serial));
1292     return ScopedAStatus::ok();
1293 }
1294 
isSecurityAlgorithmsUpdatedEnabled(const int32_t serial)1295 ScopedAStatus RadioNetwork::isSecurityAlgorithmsUpdatedEnabled(const int32_t serial) {
1296     bool enabled;
1297     {
1298         std::lock_guard<std::mutex> lock(mMtx);
1299         enabled = mSecurityAlgorithmsUpdatedEnabled;
1300     }
1301 
1302     NOT_NULL(mRadioNetworkResponse)->isSecurityAlgorithmsUpdatedEnabledResponse(
1303             makeRadioResponseInfo(serial), enabled);
1304     return ScopedAStatus::ok();
1305 }
1306 
responseAcknowledgement()1307 ScopedAStatus RadioNetwork::responseAcknowledgement() {
1308     return ScopedAStatus::ok();
1309 }
1310 
atResponseSink(const AtResponsePtr & response)1311 void RadioNetwork::atResponseSink(const AtResponsePtr& response) {
1312     response->visit([this](const auto& msg){ handleUnsolicited(msg); });
1313     mAtConversation.send(response);
1314 }
1315 
handleUnsolicited(const AtResponse::CFUN & cfun)1316 void RadioNetwork::handleUnsolicited(const AtResponse::CFUN& cfun) {
1317     bool changed;
1318 
1319     std::lock_guard<std::mutex> lock(mMtx);
1320     mRadioState = cfun.state;
1321     if (cfun.state == modem::RadioState::OFF) {
1322         changed = mCreg.state != network::RegState::NOT_REG_MT_NOT_SEARCHING_OP;
1323         mCreg.state = network::RegState::NOT_REG_MT_NOT_SEARCHING_OP;
1324         mCgreg.state = network::RegState::NOT_REG_MT_NOT_SEARCHING_OP;
1325     }
1326 
1327     if (changed && mRadioNetworkIndication) {
1328         mRadioNetworkIndication->networkStateChanged(RadioIndicationType::UNSOLICITED);
1329         mRadioNetworkIndication->imsNetworkStateChanged(RadioIndicationType::UNSOLICITED);
1330     }
1331 }
1332 
handleUnsolicited(const AtResponse::CREG & creg)1333 void RadioNetwork::handleUnsolicited(const AtResponse::CREG& creg) {
1334     bool changed;
1335     {
1336         std::lock_guard<std::mutex> lock(mMtx);
1337         changed = mCreg.state != creg.state;
1338         mCreg = creg;
1339     }
1340 
1341     if (changed && mRadioNetworkIndication) {
1342         mRadioNetworkIndication->networkStateChanged(RadioIndicationType::UNSOLICITED);
1343         mRadioNetworkIndication->imsNetworkStateChanged(RadioIndicationType::UNSOLICITED);
1344     }
1345 }
1346 
handleUnsolicited(const AtResponse::CGREG & cgreg)1347 void RadioNetwork::handleUnsolicited(const AtResponse::CGREG& cgreg) {
1348     std::lock_guard<std::mutex> lock(mMtx);
1349     mCgreg = cgreg;
1350 }
1351 
handleUnsolicited(const AtResponse::CSQ & csq)1352 void RadioNetwork::handleUnsolicited(const AtResponse::CSQ& csq) {
1353     SignalStrength signalStrength;
1354     std::vector<CellInfo> cellInfos;
1355 
1356     bool poweredOn;
1357     {
1358         std::lock_guard<std::mutex> lock(mMtx);
1359         mCsq = csq;
1360         poweredOn = (mRadioState == modem::RadioState::ON);
1361 
1362         if (poweredOn) {
1363             signalStrength = csq.toSignalStrength();
1364 
1365             if (mCurrentOperator && mCurrentModemTech) {
1366                 RadioError status;
1367                 CellIdentity cellIdentity;
1368                 std::tie(status, cellIdentity) =
1369                     getCellIdentityImpl(toOperatorInfo(mCurrentOperator.value()),
1370                                         mCurrentModemTech.value(),
1371                                         mCreg.areaCode, mCreg.cellId,
1372                                         nullptr);
1373                 if (status == RadioError::NONE) {
1374                     const bool registered =
1375                         (mCreg.state == network::RegState::REG_HOME);
1376 
1377                     CellInfo cellinfo;
1378                     std::tie(status, cellinfo) =
1379                         buildCellInfo(registered, std::move(cellIdentity),
1380                                       signalStrength);
1381                     if (status == RadioError::NONE) {
1382                         cellInfos.push_back(std::move(cellinfo));
1383                     }
1384                 }
1385             }
1386         }
1387     }
1388 
1389     if (poweredOn && mRadioNetworkIndication) {
1390         mRadioNetworkIndication->currentSignalStrength(
1391             RadioIndicationType::UNSOLICITED, std::move(signalStrength));
1392 
1393         if (!cellInfos.empty()) {
1394             mRadioNetworkIndication->cellInfoList(
1395                 RadioIndicationType::UNSOLICITED, std::move(cellInfos));
1396         }
1397     }
1398 }
1399 
handleUnsolicited(const AtResponse::COPS & cops)1400 void RadioNetwork::handleUnsolicited(const AtResponse::COPS& cops) {
1401     using COPS = AtResponse::COPS;
1402 
1403     if ((cops.operators.size() == 1) && (cops.operators[0].isCurrent())) {
1404         const COPS::OperatorInfo& current = cops.operators[0];
1405 
1406         std::lock_guard<std::mutex> lock(mMtx);
1407         mCurrentOperator = current;
1408     }
1409 }
1410 
handleUnsolicited(const AtResponse::CTEC & ctec)1411 void RadioNetwork::handleUnsolicited(const AtResponse::CTEC& ctec) {
1412     auto currentModemTech = ctec.getCurrentModemTechnology();
1413     if (currentModemTech) {
1414         std::lock_guard<std::mutex> lock(mMtx);
1415         mCurrentModemTech = std::move(currentModemTech.value());
1416     }
1417 }
1418 
handleUnsolicited(const AtResponse::CGFPCCFG & cgfpccfg)1419 void RadioNetwork::handleUnsolicited(const AtResponse::CGFPCCFG& cgfpccfg) {
1420     using network::CellConnectionStatus;
1421     using network::LinkCapacityEstimate;
1422     using network::PhysicalChannelConfig;
1423 
1424     bool registered;
1425     int cellId;
1426     int primaryBandwidth = 0;
1427     int secondaryBandwidth = 0;
1428     {
1429         std::lock_guard<std::mutex> lock(mMtx);
1430         registered = (mRadioState == modem::RadioState::ON) &&
1431             (mCreg.state == network::RegState::REG_HOME);
1432         cellId = mCreg.cellId;
1433         if (cgfpccfg.status == CellConnectionStatus::PRIMARY_SERVING) {
1434             mPrimaryBandwidth = cgfpccfg.bandwidth;
1435         } else {
1436             primaryBandwidth = mPrimaryBandwidth;
1437             secondaryBandwidth = cgfpccfg.bandwidth;
1438             mSecondaryBandwidth = cgfpccfg.bandwidth;
1439         }
1440     }
1441 
1442     if (registered && mRadioNetworkIndication) {
1443         {
1444             PhysicalChannelConfig physicalChannelConfig = {
1445                 .status = cgfpccfg.status,
1446                 .rat = ratUtils::currentRadioTechnology(cgfpccfg.mtech),
1447                 .downlinkChannelNumber = 1,
1448                 .uplinkChannelNumber = 2,
1449                 .cellBandwidthDownlinkKhz = cgfpccfg.bandwidth,
1450                 .cellBandwidthUplinkKhz = cgfpccfg.bandwidth / 2,
1451                 .physicalCellId = cellId,
1452                 // .band - TODO
1453             };
1454 
1455             physicalChannelConfig.contextIds.push_back(cgfpccfg.contextId);
1456 
1457             mRadioNetworkIndication->currentPhysicalChannelConfigs(
1458                 RadioIndicationType::UNSOLICITED,
1459                 { std::move(physicalChannelConfig) });
1460         }
1461 
1462         if (cgfpccfg.status == CellConnectionStatus::SECONDARY_SERVING) {
1463             LinkCapacityEstimate lce = {
1464                 .downlinkCapacityKbps = primaryBandwidth * 3,
1465                 .uplinkCapacityKbps = primaryBandwidth,
1466                 .secondaryDownlinkCapacityKbps = secondaryBandwidth * 3,
1467                 .secondaryUplinkCapacityKbps = secondaryBandwidth,
1468             };
1469 
1470             mRadioNetworkIndication->currentLinkCapacityEstimate(
1471                 RadioIndicationType::UNSOLICITED, std::move(lce));
1472         }
1473     }
1474 }
1475 
handleUnsolicited(const AtResponse::CTZV & ctzv)1476 void RadioNetwork::handleUnsolicited(const AtResponse::CTZV& ctzv) {
1477     const int64_t now = ::android::elapsedRealtime();
1478 
1479     {
1480         std::lock_guard<std::mutex> lock(mMtx);
1481         mCtzv = ctzv;
1482         mCtzvTimestamp = now;
1483     }
1484 
1485     if (mRadioNetworkIndication) {
1486         mRadioNetworkIndication->nitzTimeReceived(
1487             RadioIndicationType::UNSOLICITED, ctzv.nitzString(), now, 0);
1488     }
1489 }
1490 
setResponseFunctions(const std::shared_ptr<network::IRadioNetworkResponse> & radioNetworkResponse,const std::shared_ptr<network::IRadioNetworkIndication> & radioNetworkIndication)1491 ScopedAStatus RadioNetwork::setResponseFunctions(
1492         const std::shared_ptr<network::IRadioNetworkResponse>& radioNetworkResponse,
1493         const std::shared_ptr<network::IRadioNetworkIndication>& radioNetworkIndication) {
1494     mRadioNetworkResponse = NOT_NULL(radioNetworkResponse);
1495     mRadioNetworkIndication = NOT_NULL(radioNetworkIndication);
1496 
1497     AtResponse::CSQ csq;
1498     std::string nitz;
1499     int64_t nitzTs;
1500     bool poweredOn;
1501 
1502     {
1503         std::lock_guard<std::mutex> lock(mMtx);
1504         csq = mCsq;
1505         nitz = mCtzv.nitzString();
1506         nitzTs = mCtzvTimestamp;
1507         poweredOn = (mRadioState == modem::RadioState::ON);
1508     }
1509 
1510     if (poweredOn) {
1511         radioNetworkIndication->networkStateChanged(RadioIndicationType::UNSOLICITED);
1512 
1513         radioNetworkIndication->currentSignalStrength(
1514             RadioIndicationType::UNSOLICITED, csq.toSignalStrength());
1515 
1516         radioNetworkIndication->nitzTimeReceived(
1517             RadioIndicationType::UNSOLICITED, std::move(nitz), nitzTs, 0);
1518     }
1519 
1520     return ScopedAStatus::ok();
1521 }
1522 
1523 /************************* deprecated *************************/
getImsRegistrationState(const int32_t serial)1524 ScopedAStatus RadioNetwork::getImsRegistrationState(const int32_t serial) {
1525     NOT_NULL(mRadioNetworkResponse)->getImsRegistrationStateResponse(
1526         makeRadioResponseInfoDeprecated(serial), {}, {});
1527     return ScopedAStatus::ok();
1528 }
1529 
1530 }  // namespace implementation
1531 }  // namespace radio
1532 }  // namespace hardware
1533 }  // namespace android
1534 }  // namespace aidl
1535