111fccf17Sopenharmony_ci/*
211fccf17Sopenharmony_ci * Copyright (C) 2021-2024 Huawei Device Co., Ltd.
311fccf17Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
411fccf17Sopenharmony_ci * you may not use this file except in compliance with the License.
511fccf17Sopenharmony_ci * You may obtain a copy of the License at
611fccf17Sopenharmony_ci *
711fccf17Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
811fccf17Sopenharmony_ci *
911fccf17Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1011fccf17Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1111fccf17Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1211fccf17Sopenharmony_ci * See the License for the specific language governing permissions and
1311fccf17Sopenharmony_ci * limitations under the License.
1411fccf17Sopenharmony_ci */
1511fccf17Sopenharmony_ci
1611fccf17Sopenharmony_ci#include "hril_event.h"
1711fccf17Sopenharmony_ci
1811fccf17Sopenharmony_ci#include <cerrno>
1911fccf17Sopenharmony_ci#include <fcntl.h>
2011fccf17Sopenharmony_ci#include <sys/select.h>
2111fccf17Sopenharmony_ci#include <sys/types.h>
2211fccf17Sopenharmony_ci#include <unistd.h>
2311fccf17Sopenharmony_ci
2411fccf17Sopenharmony_ci#include "securec.h"
2511fccf17Sopenharmony_ci
2611fccf17Sopenharmony_ci#include "telephony_log_wrapper.h"
2711fccf17Sopenharmony_ci
2811fccf17Sopenharmony_cinamespace OHOS {
2911fccf17Sopenharmony_cinamespace Telephony {
3011fccf17Sopenharmony_civoid HRilEvent::GetNowTime(struct timeval &tv)
3111fccf17Sopenharmony_ci{
3211fccf17Sopenharmony_ci    struct timespec ts;
3311fccf17Sopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &ts);
3411fccf17Sopenharmony_ci    tv.tv_sec = ts.tv_sec;
3511fccf17Sopenharmony_ci    tv.tv_usec = ts.tv_nsec / TIME_UNIT;
3611fccf17Sopenharmony_ci}
3711fccf17Sopenharmony_ci
3811fccf17Sopenharmony_cibool HRilEvent::GetNextTimeOut(struct timeval &tv)
3911fccf17Sopenharmony_ci{
4011fccf17Sopenharmony_ci    std::lock_guard<std::mutex> mutexLock(listLock_);
4111fccf17Sopenharmony_ci    std::list<HRilEventMessage>::iterator eventIt = timerList_.begin();
4211fccf17Sopenharmony_ci    if (eventIt == timerList_.end() || timerList_.empty()) {
4311fccf17Sopenharmony_ci        return false;
4411fccf17Sopenharmony_ci    }
4511fccf17Sopenharmony_ci
4611fccf17Sopenharmony_ci    struct timeval now;
4711fccf17Sopenharmony_ci    GetNowTime(now);
4811fccf17Sopenharmony_ci    TELEPHONY_LOGD("now = %{public}ds + %{public}dus", (int32_t)now.tv_sec, (int32_t)now.tv_usec);
4911fccf17Sopenharmony_ci    TELEPHONY_LOGD(
5011fccf17Sopenharmony_ci        "next = %{public}ds + %{public}dus", (int32_t)eventIt->timeout.tv_sec, (int32_t)eventIt->timeout.tv_usec);
5111fccf17Sopenharmony_ci    if (timercmp(&eventIt->timeout, &now, >)) {
5211fccf17Sopenharmony_ci        timersub(&eventIt->timeout, &now, &tv);
5311fccf17Sopenharmony_ci    } else {
5411fccf17Sopenharmony_ci        // timer already expired.
5511fccf17Sopenharmony_ci        tv.tv_sec = tv.tv_usec = 0;
5611fccf17Sopenharmony_ci    }
5711fccf17Sopenharmony_ci    return true;
5811fccf17Sopenharmony_ci}
5911fccf17Sopenharmony_ci
6011fccf17Sopenharmony_civoid HRilEvent::ProcessTimerList()
6111fccf17Sopenharmony_ci{
6211fccf17Sopenharmony_ci    struct timeval now;
6311fccf17Sopenharmony_ci    std::lock_guard<std::mutex> mutexLock(listLock_);
6411fccf17Sopenharmony_ci    std::list<HRilEventMessage>::iterator eventIt = timerList_.begin();
6511fccf17Sopenharmony_ci    GetNowTime(now);
6611fccf17Sopenharmony_ci
6711fccf17Sopenharmony_ci    TELEPHONY_LOGD("finding for timers <= %{public}ds + %{public}dus", (int32_t)now.tv_sec, (int32_t)now.tv_usec);
6811fccf17Sopenharmony_ci    while ((eventIt != timerList_.end()) && (timercmp(&now, &eventIt->timeout, >))) {
6911fccf17Sopenharmony_ci        HRilEventMessage evMsg = {};
7011fccf17Sopenharmony_ci        evMsg.fd = eventIt->fd;
7111fccf17Sopenharmony_ci        evMsg.func = eventIt->func;
7211fccf17Sopenharmony_ci        evMsg.index = eventIt->index;
7311fccf17Sopenharmony_ci        evMsg.param = eventIt->param;
7411fccf17Sopenharmony_ci        evMsg.timeout = eventIt->timeout;
7511fccf17Sopenharmony_ci        pendingList_.push_back(evMsg);
7611fccf17Sopenharmony_ci        eventIt = timerList_.erase(eventIt);
7711fccf17Sopenharmony_ci    }
7811fccf17Sopenharmony_ci}
7911fccf17Sopenharmony_ci
8011fccf17Sopenharmony_cibool HRilEvent::HasEventMessageFromPendingList(HRilEventMessage *eventMsg)
8111fccf17Sopenharmony_ci{
8211fccf17Sopenharmony_ci    std::lock_guard<std::mutex> mutexLock(listLock_);
8311fccf17Sopenharmony_ci    std::list<HRilEventMessage>::iterator eventIt = pendingList_.begin();
8411fccf17Sopenharmony_ci    if (eventIt == pendingList_.end()) {
8511fccf17Sopenharmony_ci        return false;
8611fccf17Sopenharmony_ci    }
8711fccf17Sopenharmony_ci    eventMsg->fd = eventIt->fd;
8811fccf17Sopenharmony_ci    eventMsg->func = eventIt->func;
8911fccf17Sopenharmony_ci    eventMsg->index = eventIt->index;
9011fccf17Sopenharmony_ci    eventMsg->param = eventIt->param;
9111fccf17Sopenharmony_ci    eventMsg->timeout = eventIt->timeout;
9211fccf17Sopenharmony_ci    pendingList_.erase(eventIt);
9311fccf17Sopenharmony_ci    return true;
9411fccf17Sopenharmony_ci}
9511fccf17Sopenharmony_ci
9611fccf17Sopenharmony_civoid HRilEvent::ProcessPendingList()
9711fccf17Sopenharmony_ci{
9811fccf17Sopenharmony_ci    HRilEventMessage evMsg = {};
9911fccf17Sopenharmony_ci    while (HasEventMessageFromPendingList(&evMsg)) {
10011fccf17Sopenharmony_ci        if (evMsg.func != nullptr) {
10111fccf17Sopenharmony_ci            evMsg.func(evMsg.fd, 0, evMsg.param);
10211fccf17Sopenharmony_ci        }
10311fccf17Sopenharmony_ci    }
10411fccf17Sopenharmony_ci}
10511fccf17Sopenharmony_ci
10611fccf17Sopenharmony_civoid HRilEvent::EraseListenEvent(HRilEventMessage &eventMsg, int32_t index)
10711fccf17Sopenharmony_ci{
10811fccf17Sopenharmony_ci    listenEventTable_[index] = nullptr;
10911fccf17Sopenharmony_ci    eventMsg.index = DEFAULT_INDEX;
11011fccf17Sopenharmony_ci
11111fccf17Sopenharmony_ci    FD_CLR(eventMsg.fd, &readFds_);
11211fccf17Sopenharmony_ci
11311fccf17Sopenharmony_ci    if (eventMsg.fd + 1 == nfds_) {
11411fccf17Sopenharmony_ci        int32_t n = 0;
11511fccf17Sopenharmony_ci        for (auto msg : listenEventTable_) {
11611fccf17Sopenharmony_ci            if ((msg != nullptr) && (msg->fd > n)) {
11711fccf17Sopenharmony_ci                n = msg->fd;
11811fccf17Sopenharmony_ci            }
11911fccf17Sopenharmony_ci        }
12011fccf17Sopenharmony_ci        nfds_ = n + 1;
12111fccf17Sopenharmony_ci        TELEPHONY_LOGD("Updated nfds = %{public}d", nfds_);
12211fccf17Sopenharmony_ci    }
12311fccf17Sopenharmony_ci}
12411fccf17Sopenharmony_ci
12511fccf17Sopenharmony_civoid HRilEvent::ProcessEvents(fd_set *rfds, int32_t number)
12611fccf17Sopenharmony_ci{
12711fccf17Sopenharmony_ci    if (rfds == nullptr) {
12811fccf17Sopenharmony_ci        return;
12911fccf17Sopenharmony_ci    }
13011fccf17Sopenharmony_ci    std::lock_guard<std::mutex> mutexLock(listLock_);
13111fccf17Sopenharmony_ci    auto it = listenEventTable_.begin();
13211fccf17Sopenharmony_ci    for (; (it != listenEventTable_.end()) && (number > 0); ++it) {
13311fccf17Sopenharmony_ci        if (*it != nullptr && FD_ISSET((*it)->fd, rfds)) {
13411fccf17Sopenharmony_ci            pendingList_.push_back(*(*it));
13511fccf17Sopenharmony_ci            if ((*it)->isHolding == false) {
13611fccf17Sopenharmony_ci                EraseListenEvent(*(*it), (*it)->index);
13711fccf17Sopenharmony_ci            }
13811fccf17Sopenharmony_ci            number--;
13911fccf17Sopenharmony_ci        }
14011fccf17Sopenharmony_ci    }
14111fccf17Sopenharmony_ci}
14211fccf17Sopenharmony_ci
14311fccf17Sopenharmony_civoid HRilEvent::TimerEventInit()
14411fccf17Sopenharmony_ci{
14511fccf17Sopenharmony_ci    std::lock_guard<std::mutex> mutexLock(listLock_);
14611fccf17Sopenharmony_ci    FD_ZERO(&readFds_);
14711fccf17Sopenharmony_ci    timerList_.clear();
14811fccf17Sopenharmony_ci    pendingList_.clear();
14911fccf17Sopenharmony_ci    listenEventTable_.clear();
15011fccf17Sopenharmony_ci    for (int32_t i = 0; i < LISTEN_FD_EVENTS_MAX; i++) {
15111fccf17Sopenharmony_ci        listenEventTable_.push_back(nullptr);
15211fccf17Sopenharmony_ci    }
15311fccf17Sopenharmony_ci}
15411fccf17Sopenharmony_ci
15511fccf17Sopenharmony_civoid HRilEvent::AddTimerEvent(HRilEventMessage &eventMsg, const struct timeval &tv)
15611fccf17Sopenharmony_ci{
15711fccf17Sopenharmony_ci    std::lock_guard<std::mutex> mutexLock(listLock_);
15811fccf17Sopenharmony_ci    struct timeval now;
15911fccf17Sopenharmony_ci    eventMsg.fd = IVNALID_FD; // make sure fd is invalid
16011fccf17Sopenharmony_ci
16111fccf17Sopenharmony_ci    GetNowTime(now);
16211fccf17Sopenharmony_ci    timeradd(&now, &tv, &eventMsg.timeout);
16311fccf17Sopenharmony_ci
16411fccf17Sopenharmony_ci    std::list<HRilEventMessage>::iterator it = timerList_.begin();
16511fccf17Sopenharmony_ci    for (; it != timerList_.end(); ++it) {
16611fccf17Sopenharmony_ci        if (timercmp(&it->timeout, &eventMsg.timeout, >)) {
16711fccf17Sopenharmony_ci            timerList_.insert(it, eventMsg);
16811fccf17Sopenharmony_ci            return;
16911fccf17Sopenharmony_ci        }
17011fccf17Sopenharmony_ci    }
17111fccf17Sopenharmony_ci    if (it == timerList_.end()) {
17211fccf17Sopenharmony_ci        timerList_.push_back(eventMsg);
17311fccf17Sopenharmony_ci    }
17411fccf17Sopenharmony_ci}
17511fccf17Sopenharmony_ci
17611fccf17Sopenharmony_civoid HRilEvent::SetTimerEvent(
17711fccf17Sopenharmony_ci    HRilEventMessage &eventMsg, int32_t fd, bool isHolding, HRilEventCallback func, std::shared_ptr<void> param)
17811fccf17Sopenharmony_ci{
17911fccf17Sopenharmony_ci    (void)memset_s(&eventMsg, sizeof(HRilEventMessage), 0, sizeof(HRilEventMessage));
18011fccf17Sopenharmony_ci    eventMsg.fd = fd;
18111fccf17Sopenharmony_ci    eventMsg.index = DEFAULT_INDEX;
18211fccf17Sopenharmony_ci    eventMsg.func = func;
18311fccf17Sopenharmony_ci    eventMsg.param = param;
18411fccf17Sopenharmony_ci    eventMsg.isHolding = isHolding;
18511fccf17Sopenharmony_ci    fcntl(fd, F_SETFL, O_NONBLOCK);
18611fccf17Sopenharmony_ci}
18711fccf17Sopenharmony_ci
18811fccf17Sopenharmony_civoid HRilEvent::AddEventMessage(const HRilEventMessage &eventMsg)
18911fccf17Sopenharmony_ci{
19011fccf17Sopenharmony_ci    std::lock_guard<std::mutex> mutexLock(listLock_);
19111fccf17Sopenharmony_ci    for (int32_t i = 0; i < LISTEN_FD_EVENTS_MAX; i++) {
19211fccf17Sopenharmony_ci        if (listenEventTable_[i] == nullptr) {
19311fccf17Sopenharmony_ci            listenEventTable_[i] = const_cast<HRilEventMessage *>(&eventMsg);
19411fccf17Sopenharmony_ci            listenEventTable_[i]->index = i;
19511fccf17Sopenharmony_ci            FD_SET(eventMsg.fd, &readFds_);
19611fccf17Sopenharmony_ci            if (eventMsg.fd >= nfds_) {
19711fccf17Sopenharmony_ci                nfds_ = eventMsg.fd + 1;
19811fccf17Sopenharmony_ci            }
19911fccf17Sopenharmony_ci            break;
20011fccf17Sopenharmony_ci        }
20111fccf17Sopenharmony_ci    }
20211fccf17Sopenharmony_ci}
20311fccf17Sopenharmony_ci
20411fccf17Sopenharmony_civoid HRilEvent::RemoveEventMessage(HRilEventMessage &eventMsg)
20511fccf17Sopenharmony_ci{
20611fccf17Sopenharmony_ci    std::lock_guard<std::mutex> mutexLock(listLock_);
20711fccf17Sopenharmony_ci    if (eventMsg.index < 0 || eventMsg.index >= LISTEN_FD_EVENTS_MAX) {
20811fccf17Sopenharmony_ci        TELEPHONY_LOGE("Invalid event message! index:%{pubulic}d", eventMsg.index);
20911fccf17Sopenharmony_ci        return;
21011fccf17Sopenharmony_ci    }
21111fccf17Sopenharmony_ci    EraseListenEvent(eventMsg, eventMsg.index);
21211fccf17Sopenharmony_ci}
21311fccf17Sopenharmony_ci
21411fccf17Sopenharmony_civoid HRilEvent::CopyReadFds(fd_set *rfds)
21511fccf17Sopenharmony_ci{
21611fccf17Sopenharmony_ci    std::lock_guard<std::mutex> mutexLock(listLock_);
21711fccf17Sopenharmony_ci    (void)memcpy_s(rfds, sizeof(fd_set), &readFds_, sizeof(fd_set));
21811fccf17Sopenharmony_ci}
21911fccf17Sopenharmony_ci
22011fccf17Sopenharmony_civoid HRilEvent::EventMessageLoop()
22111fccf17Sopenharmony_ci{
22211fccf17Sopenharmony_ci    int32_t ret;
22311fccf17Sopenharmony_ci    fd_set rfds;
22411fccf17Sopenharmony_ci    struct timeval timeout;
22511fccf17Sopenharmony_ci    struct timeval *pTimeOut;
22611fccf17Sopenharmony_ci
22711fccf17Sopenharmony_ci    TELEPHONY_LOGD("****** EventMessageLoop start ******");
22811fccf17Sopenharmony_ci    while (1) {
22911fccf17Sopenharmony_ci        CopyReadFds(&rfds);
23011fccf17Sopenharmony_ci        if (!GetNextTimeOut(timeout)) {
23111fccf17Sopenharmony_ci            // Enter blocking wait without setting a timer.
23211fccf17Sopenharmony_ci            TELEPHONY_LOGD("Enter blocking wait without setting a timer.");
23311fccf17Sopenharmony_ci            pTimeOut = nullptr;
23411fccf17Sopenharmony_ci        } else {
23511fccf17Sopenharmony_ci            TELEPHONY_LOGD(
23611fccf17Sopenharmony_ci                "Setting timeout for %{public}ds + %{public}dus", (int32_t)timeout.tv_sec, (int32_t)timeout.tv_usec);
23711fccf17Sopenharmony_ci            pTimeOut = &timeout;
23811fccf17Sopenharmony_ci        }
23911fccf17Sopenharmony_ci        ret = select(nfds_, &rfds, nullptr, nullptr, pTimeOut);
24011fccf17Sopenharmony_ci        TELEPHONY_LOGD("There are %{public}d events fired, isNormalDestory: %{public}d.", ret, isNormalDestory);
24111fccf17Sopenharmony_ci        if (isNormalDestory) {
24211fccf17Sopenharmony_ci            return;
24311fccf17Sopenharmony_ci        }
24411fccf17Sopenharmony_ci        if (ret < 0) {
24511fccf17Sopenharmony_ci            if (errno == EINTR) {
24611fccf17Sopenharmony_ci                continue;
24711fccf17Sopenharmony_ci            }
24811fccf17Sopenharmony_ci            TELEPHONY_LOGE("select error (%{public}d)", errno);
24911fccf17Sopenharmony_ci            return;
25011fccf17Sopenharmony_ci        }
25111fccf17Sopenharmony_ci        ProcessTimerList();
25211fccf17Sopenharmony_ci        ProcessEvents(&rfds, ret);
25311fccf17Sopenharmony_ci        ProcessPendingList();
25411fccf17Sopenharmony_ci    }
25511fccf17Sopenharmony_ci}
25611fccf17Sopenharmony_ci
25711fccf17Sopenharmony_civoid HRilEvent::SetNormalDestory(bool isDestory)
25811fccf17Sopenharmony_ci{
25911fccf17Sopenharmony_ci    isNormalDestory = isDestory;
26011fccf17Sopenharmony_ci}
26111fccf17Sopenharmony_cibool HRilEvent::IsNormalDestory()
26211fccf17Sopenharmony_ci{
26311fccf17Sopenharmony_ci    return isNormalDestory;
26411fccf17Sopenharmony_ci}
26511fccf17Sopenharmony_ci
26611fccf17Sopenharmony_ci} // namespace Telephony
26711fccf17Sopenharmony_ci} // namespace OHOS
268