1 /*
2 **
3 ** Copyright 2020, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #define LOG_TAG "RILC"
19 
20 #include <android/hardware/radio/config/1.1/IRadioConfig.h>
21 #include <android/hardware/radio/config/1.2/IRadioConfigResponse.h>
22 #include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
23 #include <android/hardware/radio/1.1/types.h>
24 
25 #include <ril.h>
26 #include <guest/hals/ril/reference-libril/ril_service.h>
27 #include <hidl/HidlTransportSupport.h>
28 
29 using namespace android::hardware::radio::V1_0;
30 using namespace android::hardware::radio::config;
31 using namespace android::hardware::radio::config::V1_0;
32 using ::android::hardware::configureRpcThreadpool;
33 using ::android::hardware::joinRpcThreadpool;
34 using ::android::hardware::Return;
35 using ::android::hardware::hidl_string;
36 using ::android::hardware::hidl_vec;
37 using ::android::hardware::Void;
38 using android::CommandInfo;
39 using android::RequestInfo;
40 using android::requestToString;
41 using android::sp;
42 
43 RIL_RadioFunctions *s_vendorFunctions_config = NULL;
44 static CommandInfo *s_configCommands;
45 struct RadioConfigImpl;
46 sp<RadioConfigImpl> radioConfigService;
47 volatile int32_t mCounterRadioConfig;
48 
49 #if defined (ANDROID_MULTI_SIM)
50 #define RIL_UNSOL_RESPONSE(a, b, c, d) RIL_onUnsolicitedResponse((a), (b), (c), (d))
51 #define CALL_ONREQUEST(a, b, c, d, e) s_vendorFunctions_config->onRequest((a), (b), (c), (d), (e))
52 #define CALL_ONSTATEREQUEST(a) s_vendorFunctions_config->onStateRequest(a)
53 #else
54 #define RIL_UNSOL_RESPONSE(a, b, c, d) RIL_onUnsolicitedResponse((a), (b), (c))
55 #define CALL_ONREQUEST(a, b, c, d, e) s_vendorFunctions_config->onRequest((a), (b), (c), (d))
56 #define CALL_ONSTATEREQUEST(a) s_vendorFunctions_config->onStateRequest()
57 #endif
58 
59 extern void populateResponseInfo(RadioResponseInfo& responseInfo, int serial, int responseType,
60                 RIL_Errno e);
61 extern bool dispatchVoid(int serial, int slotId, int request);
62 extern bool dispatchString(int serial, int slotId, int request, const char * str);
63 extern bool dispatchStrings(int serial, int slotId, int request, bool allowEmpty,
64                 int countStrings, ...);
65 extern bool dispatchInts(int serial, int slotId, int request, int countInts, ...);
66 extern hidl_string convertCharPtrToHidlString(const char *ptr);
67 extern void sendErrorResponse(android::RequestInfo *pRI, RIL_Errno err);
68 extern RadioIndicationType convertIntToRadioIndicationType(int indicationType);
69 
70 extern bool isChangeSlotId(int serviceId, int slotId);
71 
72 struct RadioConfigImpl : public V1_1::IRadioConfig {
73     int32_t mSlotId;
74     sp<V1_0::IRadioConfigResponse> mRadioConfigResponse;
75     sp<V1_0::IRadioConfigIndication> mRadioConfigIndication;
76     sp<V1_1::IRadioConfigResponse> mRadioConfigResponseV1_1;
77     sp<V1_2::IRadioConfigResponse> mRadioConfigResponseV1_2;
78     sp<V1_2::IRadioConfigIndication> mRadioConfigIndicationV1_2;
79 
80     Return<void> setResponseFunctions(
81             const ::android::sp<V1_0::IRadioConfigResponse>& radioConfigResponse,
82             const ::android::sp<V1_0::IRadioConfigIndication>& radioConfigIndication);
83 
84     Return<void> getSimSlotsStatus(int32_t serial);
85 
86     Return<void> setSimSlotsMapping(int32_t serial, const hidl_vec<uint32_t>& slotMap);
87 
88     Return<void> getPhoneCapability(int32_t serial);
89 
90     Return<void> setPreferredDataModem(int32_t serial, uint8_t modemId);
91 
92     Return<void> setModemsConfig(int32_t serial, const V1_1::ModemsConfig& modemsConfig);
93 
94     Return<void> getModemsConfig(int32_t serial);
95 
96     void checkReturnStatus_config(Return<void>& ret);
97 };
setResponseFunctions(const::android::sp<V1_0::IRadioConfigResponse> & radioConfigResponse,const::android::sp<V1_0::IRadioConfigIndication> & radioConfigIndication)98 Return<void> RadioConfigImpl::setResponseFunctions(
99         const ::android::sp<V1_0::IRadioConfigResponse>& radioConfigResponse,
100         const ::android::sp<V1_0::IRadioConfigIndication>& radioConfigIndication) {
101     pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock(RIL_SOCKET_1);
102     int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
103     assert(ret == 0);
104 
105     mRadioConfigResponse = radioConfigResponse;
106     mRadioConfigIndication = radioConfigIndication;
107 
108 
109     mRadioConfigResponseV1_1 =
110         V1_1::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
111     if (mRadioConfigResponseV1_1 == nullptr) {
112         mRadioConfigResponseV1_1 = nullptr;
113     }
114 
115     mRadioConfigResponseV1_2 =
116         V1_2::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
117     mRadioConfigIndicationV1_2 =
118         V1_2::IRadioConfigIndication::castFrom(mRadioConfigIndication).withDefault(nullptr);
119     if (mRadioConfigResponseV1_2 == nullptr || mRadioConfigIndicationV1_2 == nullptr) {
120         mRadioConfigResponseV1_2 = nullptr;
121         mRadioConfigIndicationV1_2 = nullptr;
122     }
123 
124     mCounterRadioConfig++;
125 
126     ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
127     assert(ret == 0);
128 
129     return Void();
130 }
131 
getSimSlotsStatus(int32_t serial)132 Return<void> RadioConfigImpl::getSimSlotsStatus(int32_t serial) {
133 #if VDBG
134     RLOGD("getSimSlotsStatus: serial %d", serial);
135 #endif
136     dispatchVoid(serial, mSlotId, RIL_REQUEST_CONFIG_GET_SLOT_STATUS);
137 
138     return Void();
139 }
140 
setSimSlotsMapping(int32_t serial,const hidl_vec<uint32_t> & slotMap)141 Return<void> RadioConfigImpl::setSimSlotsMapping(int32_t serial, const hidl_vec<uint32_t>& slotMap) {
142 #if VDBG
143     RLOGD("setSimSlotsMapping: serial %d", serial);
144 #endif
145     RequestInfo *pRI = android::addRequestToList(serial, RIL_SOCKET_1,
146         RIL_REQUEST_CONFIG_SET_SLOT_MAPPING);
147     if (pRI == NULL) {
148         return Void();
149     }
150     size_t slotNum = slotMap.size();
151 
152     if (slotNum > RIL_SOCKET_NUM) {
153         RLOGE("setSimSlotsMapping: invalid parameter");
154         sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
155         return Void();
156     }
157 
158     for (size_t socket_id = 0; socket_id < slotNum; socket_id++) {
159         if (slotMap[socket_id] >= RIL_SOCKET_NUM) {
160             RLOGE("setSimSlotsMapping: invalid parameter[%zu]", socket_id);
161             sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
162             return Void();
163         }
164         // confirm logical id is not duplicate
165         for (size_t nextId = socket_id + 1; nextId < slotNum; nextId++) {
166             if (slotMap[socket_id] == slotMap[nextId]) {
167                 RLOGE("setSimSlotsMapping: slot parameter is the same:[%zu] and [%zu]",
168                     socket_id, nextId);
169                 sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
170                 return Void();
171             }
172         }
173     }
174     int *pSlotMap = (int *)calloc(slotNum, sizeof(int));
175 
176     for (size_t socket_id = 0; socket_id < slotNum; socket_id++) {
177         pSlotMap[socket_id] = slotMap[socket_id];
178     }
179 
180     CALL_ONREQUEST(RIL_REQUEST_CONFIG_SET_SLOT_MAPPING, pSlotMap,
181         slotNum * sizeof(int), pRI, pRI->socket_id);
182     if (pSlotMap != NULL) {
183         free(pSlotMap);
184     }
185 
186     return Void();
187 }
188 
getPhoneCapability(int32_t serial)189 Return<void> RadioConfigImpl::getPhoneCapability(int32_t serial) {
190 #if VDBG
191     RLOGD("getPhoneCapability: serial %d", serial);
192 #endif
193     dispatchVoid(serial, mSlotId, RIL_REQUEST_CONFIG_GET_PHONE_CAPABILITY);
194     return Void();
195 }
196 
setPreferredDataModem(int32_t serial,uint8_t modemId)197 Return<void> RadioConfigImpl::setPreferredDataModem(int32_t serial, uint8_t modemId) {
198 #if VDBG
199     RLOGD("setPreferredDataModem: serial %d", serial);
200 #endif
201     dispatchInts(serial, mSlotId, RIL_REQUEST_CONFIG_SET_PREFER_DATA_MODEM, 1, modemId);
202     return Void();
203 }
204 
setModemsConfig(int32_t serial,const V1_1::ModemsConfig & modemsConfig)205 Return<void> RadioConfigImpl::setModemsConfig(int32_t serial, const V1_1::ModemsConfig& modemsConfig) {
206 #if VDBG
207     RLOGD("setModemsConfig: serial %d", serial);
208 #endif
209     RequestInfo *pRI = android::addRequestToList(serial, mSlotId,
210         RIL_REQUEST_CONFIG_SET_MODEM_CONFIG);
211     if (pRI == NULL) {
212         return Void();
213     }
214 
215     RIL_ModemConfig mdConfig = {};
216 
217     mdConfig.numOfLiveModems = modemsConfig.numOfLiveModems;
218 
219 
220     CALL_ONREQUEST(RIL_REQUEST_CONFIG_SET_MODEM_CONFIG, &mdConfig,
221         sizeof(RIL_ModemConfig), pRI, pRI->socket_id);
222 
223     return Void();
224 }
225 
getModemsConfig(int32_t serial)226 Return<void> RadioConfigImpl::getModemsConfig(int32_t serial) {
227 #if VDBG
228     RLOGD("getModemsConfig: serial %d", serial);
229 #endif
230     dispatchVoid(serial, mSlotId, RIL_REQUEST_CONFIG_GET_MODEM_CONFIG);
231     return Void();
232 }
233 
registerConfigService(RIL_RadioFunctions * callbacks,CommandInfo * commands)234 void radio_1_6::registerConfigService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
235     using namespace android::hardware;
236     RLOGD("Entry %s", __FUNCTION__);
237     const char *serviceNames = "default";
238 
239     s_vendorFunctions_config = callbacks;
240     s_configCommands = commands;
241 
242     int slotId = RIL_SOCKET_1;
243 
244     pthread_rwlock_t *radioServiceRwlockPtr = getRadioServiceRwlock(0);
245     int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
246     assert(ret == 0);
247     RLOGD("registerConfigService: starting V1_2::IConfigRadio %s", serviceNames);
248     radioConfigService = new RadioConfigImpl;
249 
250     radioConfigService->mSlotId = slotId;
251     radioConfigService->mRadioConfigResponse = NULL;
252     radioConfigService->mRadioConfigIndication = NULL;
253     radioConfigService->mRadioConfigResponseV1_1 = NULL;
254     radioConfigService->mRadioConfigResponseV1_2 = NULL;
255     radioConfigService->mRadioConfigIndicationV1_2 = NULL;
256     android::status_t status = radioConfigService->registerAsService(serviceNames);
257     RLOGD("registerConfigService registerService: status %d", status);
258     ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
259     assert(ret == 0);
260 }
261 
checkReturnStatus(Return<void> & ret)262 void checkReturnStatus(Return<void>& ret) {
263     if (ret.isOk() == false) {
264         RLOGE("checkReturnStatus_config: unable to call response/indication callback");
265         // Remote process hosting the callbacks must be dead. Reset the callback objects;
266         // there's no other recovery to be done here. When the client process is back up, it will
267         // call setResponseFunctions()
268 
269         // Caller should already hold rdlock, release that first
270         // note the current counter to avoid overwriting updates made by another thread before
271         // write lock is acquired.
272         int counter = mCounterRadioConfig;
273         pthread_rwlock_t *radioServiceRwlockPtr = radio_1_6::getRadioServiceRwlock(0);
274         int ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
275         assert(ret == 0);
276 
277         // acquire wrlock
278         ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
279         assert(ret == 0);
280 
281         // make sure the counter value has not changed
282         if (counter == mCounterRadioConfig) {
283             radioConfigService->mRadioConfigResponse = NULL;
284             radioConfigService->mRadioConfigIndication = NULL;
285             radioConfigService->mRadioConfigResponseV1_1 = NULL;
286             radioConfigService->mRadioConfigResponseV1_2 = NULL;
287             radioConfigService->mRadioConfigIndicationV1_2 = NULL;
288             mCounterRadioConfig++;
289         } else {
290             RLOGE("checkReturnStatus_config: not resetting responseFunctions as they likely "
291                   "got updated on another thread");
292         }
293 
294         // release wrlock
295         ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
296         assert(ret == 0);
297 
298         // Reacquire rdlock
299         ret = pthread_rwlock_rdlock(radioServiceRwlockPtr);
300         assert(ret == 0);
301     }
302 }
303 
checkReturnStatus_config(Return<void> & ret)304 void RadioConfigImpl::checkReturnStatus_config(Return<void>& ret) {
305     ::checkReturnStatus(ret);
306 }
307 
getSimSlotsStatusResponse(int slotId,int responseType,int serial,RIL_Errno e,void * response,size_t responseLen)308 int radio_1_6::getSimSlotsStatusResponse(int slotId, int responseType, int serial,
309                                      RIL_Errno e, void *response, size_t responseLen) {
310 #if VDBG
311     RLOGD("getSimSlotsResponse: serial %d", serial);
312 #endif
313 
314     if (radioConfigService->mRadioConfigResponse != NULL) {
315         RadioResponseInfo responseInfo = {};
316         populateResponseInfo(responseInfo, serial, responseType, e);
317         hidl_vec<SimSlotStatus> simSlotStatus = {};
318 
319         if ((response == NULL) || (responseLen % sizeof(RIL_SimSlotStatus_V1_2) != 0)) {
320             RLOGE("getSimSlotsStatusResponse: Invalid response");
321             if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
322         } else {
323             RIL_SimSlotStatus_V1_2 *psimSlotStatus = ((RIL_SimSlotStatus_V1_2 *) response);
324             int num = responseLen / sizeof(RIL_SimSlotStatus_V1_2);
325             simSlotStatus.resize(num);
326             for (int i = 0; i < num; i++) {
327                 simSlotStatus[i].cardState = (CardState)psimSlotStatus->base.cardState;
328                 simSlotStatus[i].slotState = (SlotState)psimSlotStatus->base.slotState;
329                 simSlotStatus[i].atr = convertCharPtrToHidlString(psimSlotStatus->base.atr);
330                 simSlotStatus[i].logicalSlotId = psimSlotStatus->base.logicalSlotId;
331                 simSlotStatus[i].iccid = convertCharPtrToHidlString(psimSlotStatus->base.iccid);
332                 psimSlotStatus += 1;
333             }
334         }
335         Return<void> retStatus = radioConfigService->mRadioConfigResponse->getSimSlotsStatusResponse(
336                 responseInfo, simSlotStatus);
337         radioConfigService->checkReturnStatus_config(retStatus);
338     } else {
339         RLOGE("getSimSlotsResponse: radioConfigService->mRadioConfigResponse == NULL");
340     }
341 
342     return 0;
343 }
344 
setSimSlotsMappingResponse(int slotId,int responseType,int serial,RIL_Errno e,void * response,size_t responseLen)345 int radio_1_6::setSimSlotsMappingResponse(int slotId, int responseType, int serial,
346                                       RIL_Errno e, void *response, size_t responseLen) {
347 #if VDBG
348     RLOGD("setSimSlotsMappingResponse: serial %d", serial);
349 #endif
350 
351     if (radioConfigService->mRadioConfigResponse != NULL) {
352         RadioResponseInfo responseInfo = {};
353         populateResponseInfo(responseInfo, serial, responseType, e);
354         Return<void> retStatus = radioConfigService->mRadioConfigResponse->setSimSlotsMappingResponse(
355                 responseInfo);
356         radioConfigService->checkReturnStatus_config(retStatus);
357     } else {
358         RLOGE("setSimSlotsMappingResponse: radioConfigService->mRadioConfigResponse == NULL");
359     }
360 
361     return 0;
362 }
363 
getPhoneCapabilityResponse(int slotId,int responseType,int serial,RIL_Errno e,void * response,size_t responseLen)364 int radio_1_6::getPhoneCapabilityResponse(int slotId, int responseType, int serial,
365                                       RIL_Errno e, void *response, size_t responseLen) {
366 #if VDBG
367     RLOGD("getPhoneCapabilityResponse: serial %d", serial);
368 #endif
369 
370     if (radioConfigService->mRadioConfigResponseV1_1 != NULL) {
371         RadioResponseInfo responseInfo = {};
372         populateResponseInfo(responseInfo, serial, responseType, e);
373         V1_1::PhoneCapability phoneCapability = {};
374         if ((response == NULL) || (responseLen % sizeof(RIL_PhoneCapability) != 0)) {
375             RLOGE("getPhoneCapabilityResponse Invalid response: NULL");
376             if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
377         } else {
378             RIL_PhoneCapability *pCapability = (RIL_PhoneCapability *)response;
379             phoneCapability.maxActiveData = pCapability->maxActiveData;
380             phoneCapability.maxActiveInternetData = pCapability->maxActiveInternetData;
381             phoneCapability.isInternetLingeringSupported = pCapability->isInternetLingeringSupported;
382             phoneCapability.logicalModemList.resize(SIM_COUNT);
383             for (int i = 0 ; i < SIM_COUNT; i++) {
384                 RIL_ModemInfo logicalModemInfo = pCapability->logicalModemList[i];
385                 phoneCapability.logicalModemList[i].modemId = logicalModemInfo.modemId;
386             }
387         }
388         Return<void> retStatus = radioConfigService->mRadioConfigResponseV1_1->getPhoneCapabilityResponse(
389                 responseInfo, phoneCapability);
390         radioConfigService->checkReturnStatus_config(retStatus);
391     } else {
392         RLOGE("getPhoneCapabilityResponse: radioConfigService->mRadioConfigResponseV1_1 == NULL");
393     }
394 
395     return 0;
396 }
397 
setPreferredDataModemResponse(int slotId,int responseType,int serial,RIL_Errno e,void * response,size_t responseLen)398 int radio_1_6::setPreferredDataModemResponse(int slotId, int responseType, int serial,
399                                          RIL_Errno e, void *response, size_t responseLen) {
400 #if VDBG
401     RLOGD("setPreferredDataModemResponse: serial %d", serial);
402 #endif
403 
404     if (radioConfigService->mRadioConfigResponseV1_1 != NULL) {
405         RadioResponseInfo responseInfo = {};
406         populateResponseInfo(responseInfo, serial, responseType, e);
407         Return<void> retStatus = radioConfigService->mRadioConfigResponseV1_1->setPreferredDataModemResponse(
408                 responseInfo);
409         radioConfigService->checkReturnStatus_config(retStatus);
410     } else {
411         RLOGE("setPreferredDataModemResponse: radioConfigService->mRadioConfigResponseV1_1 == NULL");
412     }
413 
414     return 0;
415 }
416 
setModemsConfigResponse(int slotId,int responseType,int serial,RIL_Errno e,void * response,size_t responseLen)417 int radio_1_6::setModemsConfigResponse(int slotId, int responseType, int serial,
418                                    RIL_Errno e, void *response, size_t responseLen) {
419 #if VDBG
420     RLOGD("setModemsConfigResponse: serial %d", serial);
421 #endif
422 
423     if (radioConfigService->mRadioConfigResponseV1_1 != NULL) {
424         RadioResponseInfo responseInfo = {};
425         populateResponseInfo(responseInfo, serial, responseType, e);
426         Return<void> retStatus = radioConfigService->mRadioConfigResponseV1_1->setModemsConfigResponse(
427                 responseInfo);
428         radioConfigService->checkReturnStatus_config(retStatus);
429     } else {
430         RLOGE("setModemsConfigResponse: radioConfigService->mRadioConfigResponseV1_1 == NULL");
431     }
432 
433     return 0;
434 }
435 
getModemsConfigResponse(int slotId,int responseType,int serial,RIL_Errno e,void * response,size_t responseLen)436 int radio_1_6::getModemsConfigResponse(int slotId, int responseType, int serial,
437                                    RIL_Errno e, void *response, size_t responseLen) {
438 #if VDBG
439     RLOGD("getModemsConfigResponse: serial %d", serial);
440 #endif
441 
442     if (radioConfigService->mRadioConfigResponseV1_1 != NULL) {
443         RadioResponseInfo responseInfo = {};
444         populateResponseInfo(responseInfo, serial, responseType, e);
445         V1_1::ModemsConfig mdCfg = {};
446         RIL_ModemConfig *pMdCfg = (RIL_ModemConfig *)response;
447         if ((response == NULL) || (responseLen != sizeof(RIL_ModemConfig))) {
448             RLOGE("getModemsConfigResponse Invalid response: NULL");
449             if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
450         } else {
451             mdCfg.numOfLiveModems = pMdCfg->numOfLiveModems;
452         }
453         Return<void> retStatus = radioConfigService->mRadioConfigResponseV1_1->getModemsConfigResponse(
454                 responseInfo, mdCfg);
455         radioConfigService->checkReturnStatus_config(retStatus);
456     } else {
457         RLOGE("getModemsConfigResponse: radioConfigService->mRadioConfigResponseV1_1 == NULL");
458     }
459 
460     return 0;
461 }
462 
simSlotsStatusChanged(int slotId,int indicationType,int token,RIL_Errno e,void * response,size_t responseLen)463 int radio_1_6::simSlotsStatusChanged(int slotId, int indicationType, int token, RIL_Errno e,
464                                  void *response, size_t responseLen) {
465     if (radioConfigService != NULL &&
466         (radioConfigService->mRadioConfigIndication != NULL ||
467          radioConfigService->mRadioConfigIndicationV1_2 != NULL)) {
468         if ((response == NULL) || (responseLen % sizeof(RIL_SimSlotStatus_V1_2) != 0)) {
469             RLOGE("simSlotsStatusChanged: invalid response");
470             return 0;
471         }
472 
473         RIL_SimSlotStatus_V1_2 *psimSlotStatus = ((RIL_SimSlotStatus_V1_2 *)response);
474         int num = responseLen / sizeof(RIL_SimSlotStatus_V1_2);
475         if (radioConfigService->mRadioConfigIndication != NULL) {
476             hidl_vec<SimSlotStatus> simSlotStatus = {};
477             simSlotStatus.resize(num);
478             for (int i = 0; i < num; i++) {
479                 simSlotStatus[i].cardState = (CardState) psimSlotStatus->base.cardState;
480                 simSlotStatus[i].slotState = (SlotState) psimSlotStatus->base.slotState;
481                 simSlotStatus[i].atr = convertCharPtrToHidlString(psimSlotStatus->base.atr);
482                 simSlotStatus[i].logicalSlotId = psimSlotStatus->base.logicalSlotId;
483                 simSlotStatus[i].iccid = convertCharPtrToHidlString(psimSlotStatus->base.iccid);
484 #if VDBG
485                 RLOGD("simSlotsStatusChanged: cardState %d slotState %d", simSlotStatus[i].cardState,
486                         simSlotStatus[i].slotState);
487 #endif
488                 psimSlotStatus += 1;
489             }
490 
491             Return<void> retStatus = radioConfigService->mRadioConfigIndication->simSlotsStatusChanged(
492                     convertIntToRadioIndicationType(indicationType), simSlotStatus);
493             radioConfigService->checkReturnStatus_config(retStatus);
494         } else if (radioConfigService->mRadioConfigIndicationV1_2) {
495             hidl_vec<V1_2::SimSlotStatus> simSlotStatus;
496             simSlotStatus.resize(num);
497             for (int i = 0; i < num; i++) {
498                 simSlotStatus[i].base.cardState = (CardState)(psimSlotStatus->base.cardState);
499                 simSlotStatus[i].base.slotState = (SlotState) psimSlotStatus->base.slotState;
500                 simSlotStatus[i].base.atr = convertCharPtrToHidlString(psimSlotStatus->base.atr);
501                 simSlotStatus[i].base.logicalSlotId = psimSlotStatus->base.logicalSlotId;
502                 simSlotStatus[i].base.iccid = convertCharPtrToHidlString(psimSlotStatus->base.iccid);
503                 simSlotStatus[i].eid = convertCharPtrToHidlString(psimSlotStatus->eid);
504                 psimSlotStatus += 1;
505 #if VDBG
506             RLOGD("simSlotsStatusChanged_1_2: cardState %d slotState %d",
507                     simSlotStatus[i].base.cardState, simSlotStatus[i].base.slotState);
508 #endif
509             }
510 
511             Return<void> retStatus = radioConfigService->mRadioConfigIndicationV1_2->simSlotsStatusChanged_1_2(
512                     convertIntToRadioIndicationType(indicationType), simSlotStatus);
513             radioConfigService->checkReturnStatus_config(retStatus);
514         }
515     } else {
516         RLOGE("simSlotsStatusChanged: radioService->mRadioIndication == NULL");
517     }
518 
519     return 0;
520 }
521