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, ®StateResult.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 ®StateResult.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, ®StateResult.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 ®StateResult.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