1 /*
2 * Copyright (C) 2021 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
16 #include "hril_timer_callback.h"
17
18 #include <cerrno>
19 #include <fcntl.h>
20 #include <csignal>
21 #include <sys/select.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include "securec.h"
26
27 #include "telephony_log_wrapper.h"
28
29 namespace OHOS {
30 namespace Telephony {
FdTriggerCallback(int32_t fd,int16_t events,std::shared_ptr<void> param)31 void HRilTimerCallback::FdTriggerCallback(int32_t fd, int16_t events, std::shared_ptr<void> param)
32 {
33 int32_t ret;
34 int8_t buff[READ_FD_BUFF_SIZE];
35
36 do {
37 ret = read(triggerReadFd_, &buff, sizeof(buff));
38 } while (ret > 0 || (ret < 0 && errno == EINTR));
39 }
40
TimerCallback(int32_t fd,int16_t events,std::shared_ptr<void> param)41 void HRilTimerCallback::TimerCallback(int32_t fd, int16_t events, std::shared_ptr<void> param)
42 {
43 HRilTimerCallbackMessage *pCbMsg = (HRilTimerCallbackMessage *)(param.get());
44 if (pCbMsg == nullptr) {
45 TELEPHONY_LOGE("Argument conversion failed. pCbMsg is nullptr!");
46 return;
47 }
48 if (pCbMsg->func != nullptr) {
49 pCbMsg->func(pCbMsg->param);
50 } else {
51 TELEPHONY_LOGE("HRilTimerCallbackMessage func is nullptr");
52 }
53 }
54
OnTriggerEvent()55 void HRilTimerCallback::OnTriggerEvent()
56 {
57 if (std::this_thread::get_id() == eventLoopTid_) {
58 // Write operations are prohibited in read threads.
59 TELEPHONY_LOGE("Currently in a read thread.");
60 return;
61 }
62 int ret;
63 do {
64 ret = write(triggerWriteFd_, " ", 1);
65 } while (ret < 0 && errno == EINTR);
66 }
67
HRilSetTimerCallbackInfo(HRilCallbackFun func,uint8_t * param,const struct timeval * tv)68 std::shared_ptr<HRilTimerCallbackMessage> HRilTimerCallback::HRilSetTimerCallbackInfo(
69 HRilCallbackFun func, uint8_t *param, const struct timeval *tv)
70 {
71 struct timeval timeout;
72 std::shared_ptr<HRilTimerCallbackMessage> pCbMsg = std::make_shared<HRilTimerCallbackMessage>();
73 if (event_ == nullptr || pCbMsg == nullptr) {
74 TELEPHONY_LOGE("HRilSetTimerCallbackInfo event_ or pCbMsg is nullptr");
75 return nullptr;
76 }
77 pCbMsg->func = func;
78 pCbMsg->param = param;
79
80 if (tv == NULL) {
81 (void)memset_s(&timeout, sizeof(timeout), 0, sizeof(timeout));
82 } else {
83 (void)memcpy_s(&timeout, sizeof(timeout), tv, sizeof(timeout));
84 }
85
86 HRilEventMessage eventMsg = { 0 };
87 auto funcCallback = std::bind(
88 &HRilTimerCallback::TimerCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
89 event_->SetTimerEvent(eventMsg, event_->IVNALID_FD, false, funcCallback, pCbMsg);
90 event_->AddTimerEvent(eventMsg, timeout);
91 OnTriggerEvent();
92 return pCbMsg;
93 }
94
EventLoop()95 void HRilTimerCallback::EventLoop()
96 {
97 TELEPHONY_LOGI("EventLoop start");
98 eventLoopTid_ = std::this_thread::get_id();
99 event_ = std::make_unique<HRilEvent>();
100 event_->TimerEventInit();
101
102 int32_t pipedes[PIPE_SIZE_MAX];
103 int32_t ret = pipe(pipedes);
104 if (ret < 0) {
105 TELEPHONY_LOGE("Call pipe() is failed, errno:%{public}d", errno);
106 return;
107 }
108
109 triggerReadFd_ = pipedes[0];
110 triggerWriteFd_ = pipedes[1];
111
112 fcntl(triggerReadFd_, F_SETFL, O_NONBLOCK);
113 auto func = std::bind(&HRilTimerCallback::FdTriggerCallback, this, std::placeholders::_1, std::placeholders::_2,
114 std::placeholders::_3);
115 event_->SetTimerEvent(fdTriggerEvent_, triggerReadFd_, true, func, NULL);
116 event_->AddEventMessage(fdTriggerEvent_);
117 event_->EventMessageLoop();
118 TELEPHONY_LOGE("error in EventMessageLoop errno:%{public}d, isNormalDestory:%{public}d",
119 errno, event_->IsNormalDestory());
120 if (!event_->IsNormalDestory()) {
121 EventLoop();
122 }
123 }
124 } // namespace Telephony
125 } // namespace OHOS