• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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