• 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 "RadioConfig"
18 
19 #include <aidl/android/hardware/radio/sim/CardStatus.h>
20 
21 #include "RadioConfig.h"
22 
23 #include "atCmds.h"
24 #include "debug.h"
25 #include "makeRadioResponseInfo.h"
26 
27 namespace aidl {
28 namespace android {
29 namespace hardware {
30 namespace radio {
31 namespace implementation {
32 constexpr int8_t kLogicalModemId = 0;
33 
RadioConfig(std::shared_ptr<AtChannel> atChannel)34 RadioConfig::RadioConfig(std::shared_ptr<AtChannel> atChannel) : mAtChannel(std::move(atChannel)) {
35 }
36 
getHalDeviceCapabilities(const int32_t serial)37 ScopedAStatus RadioConfig::getHalDeviceCapabilities(const int32_t serial) {
38     NOT_NULL(mRadioConfigResponse)->getHalDeviceCapabilitiesResponse(
39             makeRadioResponseInfo(serial), false);
40     return ScopedAStatus::ok();
41 }
42 
getNumOfLiveModems(const int32_t serial)43 ScopedAStatus RadioConfig::getNumOfLiveModems(const int32_t serial) {
44     NOT_NULL(mRadioConfigResponse)->getNumOfLiveModemsResponse(
45             makeRadioResponseInfo(serial), 1);
46     return ScopedAStatus::ok();
47 }
48 
getPhoneCapability(const int32_t serial)49 ScopedAStatus RadioConfig::getPhoneCapability(const int32_t serial) {
50     config::PhoneCapability capability = {
51         .maxActiveData = 1,
52         .maxActiveInternetData = 1,
53         .isInternetLingeringSupported = false,
54         .logicalModemIds = { kLogicalModemId },
55         .maxActiveVoice = 1,
56     };
57     NOT_NULL(mRadioConfigResponse)->getPhoneCapabilityResponse(
58             makeRadioResponseInfo(serial), std::move(capability));
59     return ScopedAStatus::ok();
60 }
61 
getSimultaneousCallingSupport(const int32_t serial)62 ScopedAStatus RadioConfig::getSimultaneousCallingSupport(const int32_t serial) {
63     NOT_NULL(mRadioConfigResponse)->getSimultaneousCallingSupportResponse(
64             makeRadioResponseInfoNOP(serial), {});
65     return ScopedAStatus::ok();
66 }
67 
getSimSlotsStatus(const int32_t serial)68 ScopedAStatus RadioConfig::getSimSlotsStatus(const int32_t serial) {
69     static const char* const kFunc = __func__;
70     mAtChannel->queueRequester([this, serial](const AtChannel::RequestPipe requestPipe) -> bool {
71         using config::SimSlotStatus;
72         using config::SimPortInfo;
73         using CmeError = AtResponse::CmeError;
74         using CPIN = AtResponse::CPIN;
75 
76         SimSlotStatus simSlotStatus;
77 
78         AtResponsePtr response =
79             mAtConversation(requestPipe, atCmds::getSimCardStatus,
80                             [](const AtResponse& response) -> bool {
81                                return response.holds<CPIN>() || response.holds<CmeError>();
82                             });
83         if (!response || response->isParseError()) {
84 failed:     NOT_NULL(mRadioConfigResponse)->getSimSlotsStatusResponse(
85                 makeRadioResponseInfo(serial, FAILURE(RadioError::INTERNAL_ERR)), {});
86             return false;
87         } else if (const CPIN* cpin = response->get_if<CPIN>()) {
88             switch (cpin->state) {
89             case CPIN::State::READY:
90                 simSlotStatus.cardState = sim::CardStatus::STATE_PRESENT;
91                 simSlotStatus.atr = "";  // TODO 3BF000818000
92                 simSlotStatus.eid = "";  // TODO
93                 break;
94 
95             case CPIN::State::PIN:
96             case CPIN::State::PUK:
97                 simSlotStatus.cardState = sim::CardStatus::STATE_RESTRICTED;
98                 break;
99 
100             default:
101                 goto failed;
102             }
103         } else if (const CmeError* cmeError = response->get_if<CmeError>()) {
104             switch (cmeError->error) {
105             case RadioError::SIM_ABSENT:
106                 simSlotStatus.cardState = sim::CardStatus::STATE_ABSENT;
107                 break;
108             case RadioError::SIM_BUSY:
109             case RadioError::SIM_ERR:
110                 simSlotStatus.cardState = sim::CardStatus::STATE_ERROR;
111                 break;
112 
113             default:
114                 RLOGE("%s:%s:%s:%d unexpected error: '%s'",
115                       FAILURE_DEBUG_PREFIX, kFunc, "CPIN", __LINE__,
116                       toString(cmeError->error).c_str());
117                 goto failed;
118             }
119         } else {
120             response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
121         }
122 
123         if (simSlotStatus.cardState != sim::CardStatus::STATE_ABSENT) {
124             SimPortInfo simPortInfo = {
125                 .logicalSlotId = 0,
126                 .portActive = true,
127             };
128 
129             response =
130                 mAtConversation(requestPipe, atCmds::getICCID,
131                                 [](const AtResponse& response) -> bool {
132                                    return response.holds<std::string>();
133                                 });
134             if (!response || response->isParseError()) {
135                 goto failed;
136             } else if (const std::string* iccid = response->get_if<std::string>()) {
137                 simPortInfo.iccId = *iccid;
138             } else {
139                 response->unexpected(FAILURE_DEBUG_PREFIX, kFunc);
140             }
141 
142             simSlotStatus.portInfo.push_back(std::move(simPortInfo));
143         }
144 
145         NOT_NULL(mRadioConfigResponse)->getSimSlotsStatusResponse(
146                 makeRadioResponseInfo(serial), { std::move(simSlotStatus) });
147         return true;
148     });
149 
150     return ScopedAStatus::ok();
151 }
152 
setNumOfLiveModems(const int32_t serial,const int8_t numOfLiveModems)153 ScopedAStatus RadioConfig::setNumOfLiveModems(const int32_t serial,
154                                               const int8_t numOfLiveModems) {
155     const RadioError result = (numOfLiveModems == 1) ?
156         RadioError::NONE : FAILURE_V(RadioError::INVALID_ARGUMENTS,
157                                      "numOfLiveModems=%d", numOfLiveModems);
158 
159     NOT_NULL(mRadioConfigResponse)->setNumOfLiveModemsResponse(
160             makeRadioResponseInfo(serial, result));
161     return ScopedAStatus::ok();
162 }
163 
setPreferredDataModem(const int32_t serial,const int8_t modemId)164 ScopedAStatus RadioConfig::setPreferredDataModem(const int32_t serial,
165                                                  const int8_t modemId) {
166     const RadioError result = (modemId == kLogicalModemId) ?
167         RadioError::NONE : FAILURE_V(RadioError::INVALID_ARGUMENTS,
168                                      "modemId=%d", modemId);
169 
170     NOT_NULL(mRadioConfigResponse)->setPreferredDataModemResponse(
171         makeRadioResponseInfo(serial, result));
172     return ScopedAStatus::ok();
173 }
174 
setSimSlotsMapping(const int32_t serial,const std::vector<config::SlotPortMapping> &)175 ScopedAStatus RadioConfig::setSimSlotsMapping(
176         const int32_t serial, const std::vector<config::SlotPortMapping>& /*slotMap*/) {
177     NOT_NULL(mRadioConfigResponse)->setSimSlotsMappingResponse(
178         makeRadioResponseInfoNOP(serial));
179     return ScopedAStatus::ok();
180 }
181 
atResponseSink(const AtResponsePtr & response)182 void RadioConfig::atResponseSink(const AtResponsePtr& response) {
183     if (!mAtConversation.send(response)) {
184         response->visit([this](const auto& msg){ handleUnsolicited(msg); });
185     }
186 }
187 
setResponseFunctions(const std::shared_ptr<config::IRadioConfigResponse> & radioConfigResponse,const std::shared_ptr<config::IRadioConfigIndication> & radioConfigIndication)188 ScopedAStatus RadioConfig::setResponseFunctions(
189         const std::shared_ptr<config::IRadioConfigResponse>& radioConfigResponse,
190         const std::shared_ptr<config::IRadioConfigIndication>& radioConfigIndication) {
191     mRadioConfigResponse = NOT_NULL(radioConfigResponse);
192     mRadioConfigIndication = NOT_NULL(radioConfigIndication);
193     return ScopedAStatus::ok();
194 }
195 
196 }  // namespace implementation
197 }  // namespace radio
198 }  // namespace hardware
199 }  // namespace android
200 }  // namespace aidl
201