• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_event.h"
17 
18 #include <cerrno>
19 #include <fcntl.h>
20 #include <sys/select.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 
24 #include "securec.h"
25 
26 #include "telephony_log_wrapper.h"
27 
28 namespace OHOS {
29 namespace Telephony {
GetNowTime(struct timeval & tv)30 void HRilEvent::GetNowTime(struct timeval &tv)
31 {
32     struct timespec ts;
33     clock_gettime(CLOCK_MONOTONIC, &ts);
34     tv.tv_sec = ts.tv_sec;
35     tv.tv_usec = ts.tv_nsec / TIME_UNIT;
36 }
37 
GetNextTimeOut(struct timeval & tv)38 bool HRilEvent::GetNextTimeOut(struct timeval &tv)
39 {
40     std::list<HRilEventMessage>::iterator eventIt = timerList_.begin();
41     if (eventIt == timerList_.end() || timerList_.empty()) {
42         return false;
43     }
44 
45     struct timeval now;
46     GetNowTime(now);
47     TELEPHONY_LOGD("now = %{public}ds + %{public}dus", (int32_t)now.tv_sec, (int32_t)now.tv_usec);
48     TELEPHONY_LOGD(
49         "next = %{public}ds + %{public}dus", (int32_t)eventIt->timeout.tv_sec, (int32_t)eventIt->timeout.tv_usec);
50     if (timercmp(&eventIt->timeout, &now, >)) {
51         timersub(&eventIt->timeout, &now, &tv);
52     } else {
53         // timer already expired.
54         tv.tv_sec = tv.tv_usec = 0;
55     }
56     return true;
57 }
58 
ProcessTimerList()59 void HRilEvent::ProcessTimerList()
60 {
61     struct timeval now;
62     std::lock_guard<std::mutex> mutexLock(listLock_);
63     std::list<HRilEventMessage>::iterator eventIt = timerList_.begin();
64     GetNowTime(now);
65 
66     TELEPHONY_LOGD("finding for timers <= %{public}ds + %{public}dus", (int32_t)now.tv_sec, (int32_t)now.tv_usec);
67     while ((eventIt != timerList_.end()) && (timercmp(&now, &eventIt->timeout, >))) {
68         HRilEventMessage evMsg = {};
69         evMsg.fd = eventIt->fd;
70         evMsg.func = eventIt->func;
71         evMsg.index = eventIt->index;
72         evMsg.param = eventIt->param;
73         evMsg.timeout = eventIt->timeout;
74         pendingList_.push_back(evMsg);
75         eventIt = timerList_.erase(eventIt);
76     }
77 }
78 
ProcessPendingList()79 void HRilEvent::ProcessPendingList()
80 {
81     std::list<HRilEventMessage>::iterator eventIt = pendingList_.begin();
82     while (eventIt != pendingList_.end()) {
83         if (eventIt->func != nullptr) {
84             eventIt->func(eventIt->fd, 0, eventIt->param);
85         }
86         eventIt = pendingList_.erase(eventIt);
87     }
88 }
89 
EraseListenEvent(HRilEventMessage & eventMsg,int32_t index)90 void HRilEvent::EraseListenEvent(HRilEventMessage &eventMsg, int32_t index)
91 {
92     listenEventTable_[index] = nullptr;
93     eventMsg.index = DEFAULT_INDEX;
94 
95     FD_CLR(eventMsg.fd, &readFds_);
96 
97     if (eventMsg.fd + 1 == nfds_) {
98         int32_t n = 0;
99         for (auto msg : listenEventTable_) {
100             if ((msg != nullptr) && (msg->fd > n)) {
101                 n = msg->fd;
102             }
103         }
104         nfds_ = n + 1;
105         TELEPHONY_LOGD("Updated nfds = %{public}d", nfds_);
106     }
107 }
108 
ProcessEvents(fd_set * rfds,int32_t number)109 void HRilEvent::ProcessEvents(fd_set *rfds, int32_t number)
110 {
111     auto it = listenEventTable_.begin();
112     for (; (it != listenEventTable_.end()) && (number > 0); ++it) {
113         if (*it != nullptr && FD_ISSET((*it)->fd, rfds)) {
114             pendingList_.push_back(*(*it));
115             if ((*it)->isHolding == false) {
116                 EraseListenEvent(*(*it), (*it)->index);
117             }
118             number--;
119         }
120     }
121 }
122 
TimerEventInit()123 void HRilEvent::TimerEventInit()
124 {
125     FD_ZERO(&readFds_);
126     timerList_.clear();
127     pendingList_.clear();
128     listenEventTable_.clear();
129     for (int32_t i = 0; i < LISTEN_FD_EVENTS_MAX; i++) {
130         listenEventTable_.push_back(nullptr);
131     }
132 }
133 
AddTimerEvent(HRilEventMessage & eventMsg,const struct timeval & tv)134 void HRilEvent::AddTimerEvent(HRilEventMessage &eventMsg, const struct timeval &tv)
135 {
136     std::lock_guard<std::mutex> mutexLock(listLock_);
137     struct timeval now;
138     eventMsg.fd = IVNALID_FD; // make sure fd is invalid
139 
140     GetNowTime(now);
141     timeradd(&now, &tv, &eventMsg.timeout);
142 
143     std::list<HRilEventMessage>::iterator it = timerList_.begin();
144     for (; it != timerList_.end(); ++it) {
145         if (timercmp(&it->timeout, &eventMsg.timeout, >)) {
146             timerList_.insert(it, eventMsg);
147             return;
148         }
149     }
150     if (it == timerList_.end()) {
151         timerList_.push_back(eventMsg);
152     }
153 }
154 
SetTimerEvent(HRilEventMessage & eventMsg,int32_t fd,bool isHolding,HRilEventCallback func,std::shared_ptr<void> param)155 void HRilEvent::SetTimerEvent(
156     HRilEventMessage &eventMsg, int32_t fd, bool isHolding, HRilEventCallback func, std::shared_ptr<void> param)
157 {
158     (void)memset_s(&eventMsg, sizeof(HRilEventMessage), 0, sizeof(HRilEventMessage));
159     eventMsg.fd = fd;
160     eventMsg.index = DEFAULT_INDEX;
161     eventMsg.func = func;
162     eventMsg.param = param;
163     eventMsg.isHolding = isHolding;
164     fcntl(fd, F_SETFL, O_NONBLOCK);
165 }
166 
AddEventMessage(const HRilEventMessage & eventMsg)167 void HRilEvent::AddEventMessage(const HRilEventMessage &eventMsg)
168 {
169     std::lock_guard<std::mutex> mutexLock(listLock_);
170     for (int32_t i = 0; i < LISTEN_FD_EVENTS_MAX; i++) {
171         if (listenEventTable_[i] == nullptr) {
172             listenEventTable_[i] = const_cast<HRilEventMessage *>(&eventMsg);
173             listenEventTable_[i]->index = i;
174             FD_SET(eventMsg.fd, &readFds_);
175             if (eventMsg.fd >= nfds_) {
176                 nfds_ = eventMsg.fd + 1;
177             }
178             break;
179         }
180     }
181 }
182 
RemoveEventMessage(HRilEventMessage & eventMsg)183 void HRilEvent::RemoveEventMessage(HRilEventMessage &eventMsg)
184 {
185     std::lock_guard<std::mutex> mutexLock(listLock_);
186     if (eventMsg.index < 0 || eventMsg.index >= LISTEN_FD_EVENTS_MAX) {
187         TELEPHONY_LOGE("Invalid event message! index:%{pubulic}d", eventMsg.index);
188         return;
189     }
190     EraseListenEvent(eventMsg, eventMsg.index);
191 }
192 
EventMessageLoop()193 void HRilEvent::EventMessageLoop()
194 {
195     int32_t ret;
196     fd_set rfds;
197     struct timeval timeout;
198     struct timeval *pTimeOut;
199 
200     TELEPHONY_LOGD("****** EventMessageLoop start ******");
201     while (1) {
202         (void)memcpy_s(&rfds, sizeof(fd_set), &readFds_, sizeof(fd_set));
203         if (!GetNextTimeOut(timeout)) {
204             // Enter blocking wait without setting a timer.
205             TELEPHONY_LOGD("Enter blocking wait without setting a timer.");
206             pTimeOut = nullptr;
207         } else {
208             TELEPHONY_LOGD(
209                 "Setting timeout for %{public}ds + %{public}dus", (int32_t)timeout.tv_sec, (int32_t)timeout.tv_usec);
210             pTimeOut = &timeout;
211         }
212         ret = select(nfds_, &rfds, nullptr, nullptr, pTimeOut);
213         TELEPHONY_LOGD("There are %{public}d events fired, isNormalDestory: %{public}d.", ret, isNormalDestory);
214         if (isNormalDestory) {
215             return;
216         }
217         if (ret < 0) {
218             if (errno == EINTR) {
219                 continue;
220             }
221             TELEPHONY_LOGE("select error (%{public}d)", errno);
222             return;
223         }
224         ProcessTimerList();
225         ProcessEvents(&rfds, ret);
226         ProcessPendingList();
227     }
228 }
229 
SetNormalDestory(bool isDestory)230 void HRilEvent::SetNormalDestory(bool isDestory)
231 {
232     isNormalDestory = isDestory;
233 }
IsNormalDestory()234 bool HRilEvent::IsNormalDestory()
235 {
236     return isNormalDestory;
237 }
238 
239 } // namespace Telephony
240 } // namespace OHOS