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