1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "radio_protocol_controller.h"
16
17 #include "radio_event.h"
18 #include "telephony_log_wrapper.h"
19
20 namespace OHOS {
21 namespace Telephony {
22 static const int64_t COMMUNICATION_TIMEOUT = 45 * 1000; // Set the timeout millisecond for radio protocol communication
23 static const int64_t SET_ACTIVE_OUT_TIME = 10 * 1000;
24 std::mutex RadioProtocolController::ctx_;
25 std::condition_variable RadioProtocolController::cv_;
26
RadioProtocolController(std::shared_ptr<Telephony::ITelRilManager> telRilManager,const std::shared_ptr<AppExecFwk::EventRunner> & runner)27 RadioProtocolController::RadioProtocolController(std::shared_ptr<Telephony::ITelRilManager> telRilManager,
28 const std::shared_ptr<AppExecFwk::EventRunner> &runner)
29 : AppExecFwk::EventHandler(runner), telRilManager_(telRilManager)
30 {
31 if (runner != nullptr) {
32 runner->Run();
33 }
34 }
35
Init()36 void RadioProtocolController::Init()
37 {
38 if (telRilManager_ == nullptr) {
39 TELEPHONY_LOGE("RadioProtocolController::Init telRilManager_ is nullptr");
40 return;
41 }
42
43 slotCount_ = SIM_SLOT_COUNT;
44 InitMemberFunc();
45 // make sure communication is in the initial state
46 CleanUpCommunication();
47 for (int32_t i = 0; i < slotCount_; i++) {
48 RadioProtocol protocol;
49 protocol.slotId = i;
50 protocol.sessionId = 0;
51 protocol.phase = RadioProtocolPhase::RADIO_PROTOCOL_PHASE_INITIAL;
52 protocol.technology = 0xFFFFFFFF;
53 protocol.modemId = 0;
54 protocol.status = RadioProtocolStatus::RADIO_PROTOCOL_STATUS_NONE;
55 radioProtocol_.emplace_back(protocol);
56 telRilManager_->RegisterCoreNotify(i, shared_from_this(), RADIO_SIM_RADIO_PROTOCOL_NOTIFY, nullptr);
57 }
58 }
59
GetRadioProtocolTech(int32_t slotId)60 int32_t RadioProtocolController::GetRadioProtocolTech(int32_t slotId)
61 {
62 return static_cast<int32_t>(radioProtocol_[slotId].technology);
63 }
64
GetRadioProtocol(int32_t slotId)65 void RadioProtocolController::GetRadioProtocol(int32_t slotId)
66 {
67 if (telRilManager_ == nullptr) {
68 TELEPHONY_LOGE("RadioProtocolController::GetRadioProtocol telRilManager_ is nullptr");
69 return;
70 }
71 AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(RADIO_SIM_GET_RADIO_PROTOCOL);
72 if (event == nullptr) {
73 TELEPHONY_LOGE("RadioProtocolController::GetRadioProtocol event is nullptr");
74 return;
75 }
76 event->SetOwner(shared_from_this());
77 telRilManager_->GetRadioProtocol(slotId, event);
78 }
79
SetRadioProtocol(int32_t slotId)80 bool RadioProtocolController::SetRadioProtocol(int32_t slotId)
81 {
82 if (isCommunicating_) {
83 TELEPHONY_LOGE("RadioProtocolController::SetRadioProtocol protocol is communicating, can not set now");
84 return false;
85 }
86
87 std::unique_lock<std::mutex> radioProtocolLock(radioProtocolMutex_);
88 communicationResponseResult_ = false;
89 CleanUpCommunication();
90 ExecuteCheckCommunication();
91 while (isCommunicating_) {
92 TELEPHONY_LOGI("RadioProtocolController::SetRadioProtocol wait for the communication to finish");
93 radioProtocolCv_.wait(radioProtocolLock);
94 }
95 return communicationResponseResult_;
96 }
97
InitMemberFunc()98 void RadioProtocolController::InitMemberFunc()
99 {
100 memberFuncMap_[MSG_SIM_TIME_OUT_ACTIVE] = &RadioProtocolController::ProcessActiveSimTimeOutDone;
101 memberFuncMap_[MSG_SIM_SET_ACTIVE] = &RadioProtocolController::ProcessActiveSimToRilResponse;
102 memberFuncMap_[RADIO_SIM_GET_RADIO_PROTOCOL] = &RadioProtocolController::ProcessGetRadioProtocol;
103 memberFuncMap_[RADIO_SIM_CHECK_RADIO_PROTOCOL] = &RadioProtocolController::ProcessCheckRadioProtocol;
104 memberFuncMap_[RADIO_SIM_UPDATE_RADIO_PROTOCOL] = &RadioProtocolController::ProcessUpdateRadioProtocol;
105 memberFuncMap_[RADIO_SIM_RADIO_PROTOCOL_NOTIFY] = &RadioProtocolController::ProcessRadioProtocolNotify;
106 memberFuncMap_[RADIO_SIM_SET_RADIO_PROTOCOL_COMPLETE] = &RadioProtocolController::ProcessSetRadioProtocolComplete;
107 memberFuncMap_[RADIO_SIM_SET_RADIO_PROTOCOL_TIMEOUT] = &RadioProtocolController::ProcessSetRadioProtocolTimeout;
108 }
109
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)110 void RadioProtocolController::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
111 {
112 if (event == nullptr) {
113 TELEPHONY_LOGE("RadioProtocolController::ProcessEvent event is nullptr");
114 return;
115 }
116 auto id = event->GetInnerEventId();
117 TELEPHONY_LOGI("RadioProtocolController::ProcessEvent id = %{public}d", id);
118 auto itFunc = memberFuncMap_.find(id);
119 if (itFunc != memberFuncMap_.end()) {
120 auto memberFunc = itFunc->second;
121 if (memberFunc == nullptr) {
122 TELEPHONY_LOGE("RadioProtocolController::ProcessEvent memberFunc is nullptr");
123 return;
124 }
125 (this->*memberFunc)(event);
126 }
127 }
128
ProcessGetRadioProtocol(const AppExecFwk::InnerEvent::Pointer & event)129 void RadioProtocolController::ProcessGetRadioProtocol(const AppExecFwk::InnerEvent::Pointer &event)
130 {
131 if (event == nullptr) {
132 TELEPHONY_LOGE("RadioProtocolController::ProcessGetRadioProtocol event is nullptr");
133 return;
134 }
135 std::shared_ptr<RadioProtocol> radioProtocol = event->GetSharedObject<RadioProtocol>();
136 if (radioProtocol == nullptr) {
137 TELEPHONY_LOGE("RadioProtocolController::ProcessGetRadioProtocol radioProtocol is nullptr");
138 return;
139 }
140 UpdateRadioProtocol(radioProtocol);
141 }
142
ProcessCheckRadioProtocol(const AppExecFwk::InnerEvent::Pointer & event)143 void RadioProtocolController::ProcessCheckRadioProtocol(const AppExecFwk::InnerEvent::Pointer &event)
144 {
145 if (!ProcessResponseInfoOfEvent(event)) {
146 TELEPHONY_LOGE("RadioProtocolController::ProcessCheckRadioProtocol failed due to invalid sessionId");
147 return;
148 }
149
150 if (--communicatingSlotCount_ != 0) {
151 TELEPHONY_LOGI("RadioProtocolController::ProcessCheckRadioProtocol wait for all sim to complete check");
152 return;
153 }
154
155 if (communicationFailed_) {
156 ExecuteCompleteCommunication();
157 } else {
158 ExecuteUpdateCommunication();
159 }
160 }
161
ProcessUpdateRadioProtocol(const AppExecFwk::InnerEvent::Pointer & event)162 void RadioProtocolController::ProcessUpdateRadioProtocol(const AppExecFwk::InnerEvent::Pointer &event)
163 {
164 if (!ProcessResponseInfoOfEvent(event)) {
165 TELEPHONY_LOGE("RadioProtocolController::ProcessUpdateRadioProtocol failed due to invalid sessionId");
166 return;
167 }
168 }
169
ProcessRadioProtocolNotify(const AppExecFwk::InnerEvent::Pointer & event)170 void RadioProtocolController::ProcessRadioProtocolNotify(const AppExecFwk::InnerEvent::Pointer &event)
171 {
172 if (event == nullptr) {
173 TELEPHONY_LOGE("RadioProtocolController::ProcessRadioProtocolNotify event is nullptr");
174 return;
175 }
176 std::shared_ptr<RadioProtocol> radioProtocol = event->GetSharedObject<RadioProtocol>();
177 if (radioProtocol == nullptr || radioProtocol->sessionId != sessionId_) {
178 TELEPHONY_LOGE("RadioProtocolController::ProcessRadioProtocolNotify failed due to invalid sessionId");
179 return;
180 }
181
182 if (radioProtocol->status == RadioProtocolStatus::RADIO_PROTOCOL_STATUS_FAIL) {
183 TELEPHONY_LOGE("RadioProtocolController::ProcessRadioProtocolNotify update failed");
184 communicationFailed_ = true;
185 } else {
186 UpdateRadioProtocol(radioProtocol);
187 }
188 if (--communicatingSlotCount_ != 0) {
189 TELEPHONY_LOGI("RadioProtocolController::ProcessRadioProtocolNotify wait for all sim to complete update");
190 return;
191 }
192
193 ExecuteCompleteCommunication();
194 }
195
ProcessSetRadioProtocolComplete(const AppExecFwk::InnerEvent::Pointer & event)196 void RadioProtocolController::ProcessSetRadioProtocolComplete(const AppExecFwk::InnerEvent::Pointer &event)
197 {
198 if (event == nullptr) {
199 TELEPHONY_LOGE("RadioProtocolController::ProcessSetRadioProtocolComplete event is nullptr");
200 return;
201 }
202 if (!ProcessResponseInfoOfEvent(event)) {
203 TELEPHONY_LOGE("RadioProtocolController::ProcessSetRadioProtocolComplete failed due to invalid sessionId");
204 return;
205 }
206
207 if (--communicatingSlotCount_ != 0) {
208 TELEPHONY_LOGI("RadioProtocolController::ProcessSetRadioProtocolComplete wait for all sim to complete");
209 return;
210 }
211
212 ProcessCommunicationResponse(!communicationFailed_);
213 CleanUpCommunication();
214 }
215
ProcessSetRadioProtocolTimeout(const AppExecFwk::InnerEvent::Pointer & event)216 void RadioProtocolController::ProcessSetRadioProtocolTimeout(const AppExecFwk::InnerEvent::Pointer &event)
217 {
218 if (event == nullptr) {
219 TELEPHONY_LOGE("RadioProtocolController::ProcessSetRadioProtocolTimeout event is nullptr");
220 return;
221 }
222 auto sessionId = event->GetParam();
223 if (sessionId != sessionId_) {
224 TELEPHONY_LOGE("RadioProtocolController::ProcessSetRadioProtocolTimeout failed due to invalid sessionId");
225 return;
226 }
227
228 sessionId_++;
229 communicatingSlotCount_ = 0;
230 communicationFailed_ = true;
231 ExecuteCompleteCommunication();
232 }
233
ExecuteCheckCommunication()234 void RadioProtocolController::ExecuteCheckCommunication()
235 {
236 sessionId_++;
237 isCommunicating_ = true;
238 SendEvent(RADIO_SIM_SET_RADIO_PROTOCOL_TIMEOUT, sessionId_, COMMUNICATION_TIMEOUT);
239 BuildRadioProtocolForCommunication(RadioProtocolPhase::RADIO_PROTOCOL_PHASE_CHECK,
240 RadioProtocolStatus::RADIO_PROTOCOL_STATUS_NONE);
241 ResetNextCommunicationSlotCount();
242 SendRadioProtocolEvent(oldRadioProtocol_, RADIO_SIM_CHECK_RADIO_PROTOCOL);
243 }
244
ExecuteUpdateCommunication()245 void RadioProtocolController::ExecuteUpdateCommunication()
246 {
247 BuildRadioProtocolForCommunication(RadioProtocolPhase::RADIO_PROTOCOL_PHASE_UPDATE,
248 RadioProtocolStatus::RADIO_PROTOCOL_STATUS_NONE);
249 ResetNextCommunicationSlotCount();
250 SendRadioProtocolEvent(newRadioProtocol_, RADIO_SIM_UPDATE_RADIO_PROTOCOL);
251 }
252
ExecuteCompleteCommunication()253 void RadioProtocolController::ExecuteCompleteCommunication()
254 {
255 TELEPHONY_LOGI("RadioProtocolController::ExecuteCompleteCommunication failed:%{public}d", communicationFailed_);
256 BuildRadioProtocolForCommunication(RadioProtocolPhase::RADIO_PROTOCOL_PHASE_COMPLETE,
257 communicationFailed_ ? RadioProtocolStatus::RADIO_PROTOCOL_STATUS_FAIL :
258 RadioProtocolStatus::RADIO_PROTOCOL_STATUS_SUCCESS);
259 ResetNextCommunicationSlotCount();
260 SendRadioProtocolEvent(communicationFailed_ ? oldRadioProtocol_ : newRadioProtocol_,
261 RADIO_SIM_SET_RADIO_PROTOCOL_COMPLETE);
262 }
263
ResetNextCommunicationSlotCount()264 void RadioProtocolController::ResetNextCommunicationSlotCount()
265 {
266 communicatingSlotCount_ = slotCount_;
267 }
268
BuildRadioProtocolForCommunication(RadioProtocolPhase phase,RadioProtocolStatus status)269 void RadioProtocolController::BuildRadioProtocolForCommunication(RadioProtocolPhase phase, RadioProtocolStatus status)
270 {
271 switch (phase) {
272 case RadioProtocolPhase::RADIO_PROTOCOL_PHASE_CHECK: {
273 for (int32_t i = 0; i < slotCount_; i++) {
274 RadioProtocol radioProtocol;
275 radioProtocol.slotId = i;
276 radioProtocol.sessionId = sessionId_;
277 radioProtocol.phase = phase;
278 radioProtocol.technology = radioProtocol_[i].technology;
279 radioProtocol.modemId = radioProtocol_[i].modemId;
280 radioProtocol.status = status;
281 oldRadioProtocol_.emplace_back(radioProtocol);
282 newRadioProtocol_.emplace_back(radioProtocol);
283 }
284 // Switch the tech and modemId of main and non-main card
285 for (int32_t i = 0; i < slotCount_; i++) {
286 newRadioProtocol_[i].technology = radioProtocol_[slotCount_ - 1 - i].technology;
287 newRadioProtocol_[i].modemId = radioProtocol_[slotCount_ - 1 - i].modemId;
288 }
289 break;
290 }
291 case RadioProtocolPhase::RADIO_PROTOCOL_PHASE_UPDATE:
292 case RadioProtocolPhase::RADIO_PROTOCOL_PHASE_NOTIFY:
293 case RadioProtocolPhase::RADIO_PROTOCOL_PHASE_COMPLETE: {
294 for (int32_t i = 0; i < slotCount_; i++) {
295 oldRadioProtocol_[i].sessionId = sessionId_;
296 oldRadioProtocol_[i].phase = phase;
297 oldRadioProtocol_[i].status = status;
298 newRadioProtocol_[i].sessionId = sessionId_;
299 newRadioProtocol_[i].phase = phase;
300 newRadioProtocol_[i].status = status;
301 }
302 break;
303 }
304 default:
305 TELEPHONY_LOGE("RadioProtocolController::BuildRadioProtocolForCommunication invalid phase");
306 break;
307 }
308 }
309
SendRadioProtocolEvent(std::vector<RadioProtocol> radioProtocol,uint32_t eventId)310 void RadioProtocolController::SendRadioProtocolEvent(std::vector<RadioProtocol> radioProtocol, uint32_t eventId)
311 {
312 if (telRilManager_ == nullptr || radioProtocol.empty()) {
313 TELEPHONY_LOGE("RadioProtocolController::SendRadioProtocol telRilManager_ or radioProtocol is nullptr");
314 ProcessCommunicationResponse(false);
315 CleanUpCommunication();
316 return;
317 }
318
319 for (int32_t i = 0; i < slotCount_; i++) {
320 AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(eventId);
321 if (event == nullptr) {
322 TELEPHONY_LOGE("RadioProtocolController::SendRadioProtocol event is nullptr");
323 ProcessCommunicationResponse(false);
324 CleanUpCommunication();
325 return;
326 }
327 event->SetOwner(shared_from_this());
328 telRilManager_->SetRadioProtocol(i, radioProtocol[i], event);
329 }
330 }
331
UpdateRadioProtocol(std::shared_ptr<RadioProtocol> radioProtocol)332 void RadioProtocolController::UpdateRadioProtocol(std::shared_ptr<RadioProtocol> radioProtocol)
333 {
334 int32_t slotId = radioProtocol->slotId;
335 if ((slotId >= DEFAULT_SIM_SLOT_ID) && (slotId < SIM_SLOT_COUNT)) {
336 radioProtocol_[slotId].sessionId = radioProtocol->sessionId;
337 radioProtocol_[slotId].phase = radioProtocol->phase;
338 radioProtocol_[slotId].technology = radioProtocol->technology;
339 radioProtocol_[slotId].modemId = radioProtocol->modemId;
340 radioProtocol_[slotId].status = radioProtocol->status;
341 }
342 }
343
ProcessResponseInfoOfEvent(const AppExecFwk::InnerEvent::Pointer & event)344 bool RadioProtocolController::ProcessResponseInfoOfEvent(const AppExecFwk::InnerEvent::Pointer &event)
345 {
346 if (event == nullptr) {
347 TELEPHONY_LOGE("RadioProtocolController::ProcessResponseInfoOfEvent event is nullptr");
348 return false;
349 }
350 std::shared_ptr<HRilRadioResponseInfo> responseInfo = event->GetSharedObject<HRilRadioResponseInfo>();
351 if (responseInfo != nullptr && responseInfo->error != HRilErrType::NONE) {
352 TELEPHONY_LOGE("RadioProtocolController::ProcessResponseInfoOfEvent error:%{public}d", responseInfo->error);
353 communicationFailed_ = true;
354 return true;
355 }
356
357 std::shared_ptr<RadioProtocol> radioProtocol = event->GetSharedObject<RadioProtocol>();
358 return radioProtocol != nullptr && radioProtocol->sessionId == sessionId_;
359 }
360
CleanUpCommunication()361 void RadioProtocolController::CleanUpCommunication()
362 {
363 RemoveEvent(RADIO_SIM_SET_RADIO_PROTOCOL_TIMEOUT);
364 communicationFailed_ = false;
365 std::vector<RadioProtocol>().swap(oldRadioProtocol_);
366 std::vector<RadioProtocol>().swap(newRadioProtocol_);
367 }
368
ProcessCommunicationResponse(bool result)369 void RadioProtocolController::ProcessCommunicationResponse(bool result)
370 {
371 communicationResponseResult_ = result;
372 isCommunicating_ = false;
373 radioProtocolCv_.notify_all();
374 }
375
UnRegisterEvents()376 void RadioProtocolController::UnRegisterEvents()
377 {
378 if (telRilManager_ == nullptr) {
379 TELEPHONY_LOGE("RadioProtocolController::UnRegisterEvents telRilManager_ is nullptr");
380 return;
381 }
382 for (int32_t i = 0; i < slotCount_; i++) {
383 telRilManager_->UnRegisterCoreNotify(i, shared_from_this(), RADIO_SIM_RADIO_PROTOCOL_NOTIFY);
384 }
385 }
386
RadioProtocolControllerWait()387 void RadioProtocolController::RadioProtocolControllerWait()
388 {
389 responseReady_ = false;
390 }
391
RadioProtocolControllerContinue()392 void RadioProtocolController::RadioProtocolControllerContinue()
393 {
394 responseReady_ = true;
395 }
396
RadioProtocolControllerPoll()397 bool RadioProtocolController::RadioProtocolControllerPoll()
398 {
399 return responseReady_;
400 }
401
ProcessActiveSimTimeOutDone(const AppExecFwk::InnerEvent::Pointer & event)402 void RadioProtocolController::ProcessActiveSimTimeOutDone(const AppExecFwk::InnerEvent::Pointer &event)
403 {
404 TELEPHONY_LOGI("RadioProtocolController::ProcessActiveSimTimeOutDone");
405 activeResponse_ = 1;
406 RadioProtocolControllerContinue();
407 cv_.notify_all();
408 }
409
SetActiveSimToRil(int32_t slotId,int32_t type,int32_t enable)410 bool RadioProtocolController::SetActiveSimToRil(int32_t slotId, int32_t type, int32_t enable)
411 {
412 TELEPHONY_LOGI("RadioProtocolController::SetActiveSim(), enable=%{public}d", enable);
413 if (telRilManager_ == nullptr) {
414 TELEPHONY_LOGE("RadioProtocolController::SetActiveSim nullptr");
415 return false;
416 }
417 auto event = AppExecFwk::InnerEvent::Get(MSG_SIM_SET_ACTIVE);
418 if (event == nullptr) {
419 TELEPHONY_LOGE("event is nullptr!");
420 return false;
421 }
422 event->SetOwner(shared_from_this());
423 SendEvent(MSG_SIM_TIME_OUT_ACTIVE, SET_ACTIVE_OUT_TIME, Priority::LOW);
424 telRilManager_->SetActiveSim(slotId, type, enable, event);
425 return true;
426 }
427
ProcessActiveSimToRilResponse(const AppExecFwk::InnerEvent::Pointer & event)428 void RadioProtocolController::ProcessActiveSimToRilResponse(const AppExecFwk::InnerEvent::Pointer &event)
429 {
430 if (event == nullptr) {
431 TELEPHONY_LOGE("RadioProtocolController::ProcessActiveSimToRilResponse event is nullptr");
432 return;
433 }
434 TELEPHONY_LOGI("RadioProtocolController::GetSetActiveSimResult");
435 int32_t result = 0;
436 std::shared_ptr<HRilErrType> param = event->GetSharedObject<HRilErrType>();
437 std::shared_ptr<HRilRadioResponseInfo> response = event->GetSharedObject<HRilRadioResponseInfo>();
438 if ((param == nullptr) && (response == nullptr)) {
439 TELEPHONY_LOGE("RadioProtocolController::GetSetActiveSimResult() fail");
440 RadioProtocolControllerContinue();
441 cv_.notify_all();
442 return;
443 }
444 if (param != nullptr) {
445 result = static_cast<int32_t>(*param);
446 } else {
447 result = static_cast<int32_t>(response->error);
448 }
449 TELEPHONY_LOGI("RadioProtocolController::GetSetActiveSimResult(), activeResponse = %{public}d", result);
450 activeResponse_ = result;
451 RadioProtocolControllerContinue();
452 cv_.notify_all();
453 }
454
GetActiveSimToRilResult()455 int32_t RadioProtocolController::GetActiveSimToRilResult()
456 {
457 RemoveEvent(MSG_SIM_TIME_OUT_ACTIVE);
458 return activeResponse_;
459 }
460 } // namespace Telephony
461 } // namespace OHOS
462