111fccf17Sopenharmony_ci/*
211fccf17Sopenharmony_ci * Copyright (C) 2021 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_timer_callback.h"
1711fccf17Sopenharmony_ci
1811fccf17Sopenharmony_ci#include <cerrno>
1911fccf17Sopenharmony_ci#include <fcntl.h>
2011fccf17Sopenharmony_ci#include <csignal>
2111fccf17Sopenharmony_ci#include <sys/select.h>
2211fccf17Sopenharmony_ci#include <sys/types.h>
2311fccf17Sopenharmony_ci#include <unistd.h>
2411fccf17Sopenharmony_ci
2511fccf17Sopenharmony_ci#include "securec.h"
2611fccf17Sopenharmony_ci
2711fccf17Sopenharmony_ci#include "telephony_log_wrapper.h"
2811fccf17Sopenharmony_ci
2911fccf17Sopenharmony_cinamespace OHOS {
3011fccf17Sopenharmony_cinamespace Telephony {
3111fccf17Sopenharmony_civoid HRilTimerCallback::FdTriggerCallback(int32_t fd, int16_t events, std::shared_ptr<void> param)
3211fccf17Sopenharmony_ci{
3311fccf17Sopenharmony_ci    int32_t ret;
3411fccf17Sopenharmony_ci    int8_t buff[READ_FD_BUFF_SIZE];
3511fccf17Sopenharmony_ci
3611fccf17Sopenharmony_ci    do {
3711fccf17Sopenharmony_ci        ret = read(triggerReadFd_, &buff, sizeof(buff));
3811fccf17Sopenharmony_ci    } while (ret > 0 || (ret < 0 && errno == EINTR));
3911fccf17Sopenharmony_ci}
4011fccf17Sopenharmony_ci
4111fccf17Sopenharmony_civoid HRilTimerCallback::TimerCallback(int32_t fd, int16_t events, std::shared_ptr<void> param)
4211fccf17Sopenharmony_ci{
4311fccf17Sopenharmony_ci    HRilTimerCallbackMessage *pCbMsg = (HRilTimerCallbackMessage *)(param.get());
4411fccf17Sopenharmony_ci    if (pCbMsg == nullptr) {
4511fccf17Sopenharmony_ci        TELEPHONY_LOGE("Argument conversion failed. pCbMsg is nullptr!");
4611fccf17Sopenharmony_ci        return;
4711fccf17Sopenharmony_ci    }
4811fccf17Sopenharmony_ci    if (pCbMsg->func != nullptr) {
4911fccf17Sopenharmony_ci        pCbMsg->func(pCbMsg->param);
5011fccf17Sopenharmony_ci    } else {
5111fccf17Sopenharmony_ci        TELEPHONY_LOGE("HRilTimerCallbackMessage func is nullptr");
5211fccf17Sopenharmony_ci    }
5311fccf17Sopenharmony_ci}
5411fccf17Sopenharmony_ci
5511fccf17Sopenharmony_civoid HRilTimerCallback::OnTriggerEvent()
5611fccf17Sopenharmony_ci{
5711fccf17Sopenharmony_ci    if (std::this_thread::get_id() == eventLoopTid_) {
5811fccf17Sopenharmony_ci        // Write operations are prohibited in read threads.
5911fccf17Sopenharmony_ci        TELEPHONY_LOGE("Currently in a read thread.");
6011fccf17Sopenharmony_ci        return;
6111fccf17Sopenharmony_ci    }
6211fccf17Sopenharmony_ci    int ret;
6311fccf17Sopenharmony_ci    do {
6411fccf17Sopenharmony_ci        ret = write(triggerWriteFd_, " ", 1);
6511fccf17Sopenharmony_ci    } while (ret < 0 && errno == EINTR);
6611fccf17Sopenharmony_ci}
6711fccf17Sopenharmony_ci
6811fccf17Sopenharmony_cistd::shared_ptr<HRilTimerCallbackMessage> HRilTimerCallback::HRilSetTimerCallbackInfo(
6911fccf17Sopenharmony_ci    HRilCallbackFun func, uint8_t *param, const struct timeval *tv)
7011fccf17Sopenharmony_ci{
7111fccf17Sopenharmony_ci    struct timeval timeout;
7211fccf17Sopenharmony_ci    std::shared_ptr<HRilTimerCallbackMessage> pCbMsg = std::make_shared<HRilTimerCallbackMessage>();
7311fccf17Sopenharmony_ci    if (event_ == nullptr || pCbMsg == nullptr) {
7411fccf17Sopenharmony_ci        TELEPHONY_LOGE("HRilSetTimerCallbackInfo event_ or pCbMsg is nullptr");
7511fccf17Sopenharmony_ci        return nullptr;
7611fccf17Sopenharmony_ci    }
7711fccf17Sopenharmony_ci    pCbMsg->func = func;
7811fccf17Sopenharmony_ci    pCbMsg->param = param;
7911fccf17Sopenharmony_ci
8011fccf17Sopenharmony_ci    if (tv == NULL) {
8111fccf17Sopenharmony_ci        (void)memset_s(&timeout, sizeof(timeout), 0, sizeof(timeout));
8211fccf17Sopenharmony_ci    } else {
8311fccf17Sopenharmony_ci        (void)memcpy_s(&timeout, sizeof(timeout), tv, sizeof(timeout));
8411fccf17Sopenharmony_ci    }
8511fccf17Sopenharmony_ci
8611fccf17Sopenharmony_ci    HRilEventMessage eventMsg = { 0 };
8711fccf17Sopenharmony_ci    auto funcCallback =
8811fccf17Sopenharmony_ci        [this](int32_t fd, int16_t events, std::shared_ptr<void> param) { this->TimerCallback(fd, events, param); };
8911fccf17Sopenharmony_ci    event_->SetTimerEvent(eventMsg, event_->IVNALID_FD, false, funcCallback, pCbMsg);
9011fccf17Sopenharmony_ci    event_->AddTimerEvent(eventMsg, timeout);
9111fccf17Sopenharmony_ci    OnTriggerEvent();
9211fccf17Sopenharmony_ci    return pCbMsg;
9311fccf17Sopenharmony_ci}
9411fccf17Sopenharmony_ci
9511fccf17Sopenharmony_civoid HRilTimerCallback::EventLoop()
9611fccf17Sopenharmony_ci{
9711fccf17Sopenharmony_ci    TELEPHONY_LOGI("EventLoop start");
9811fccf17Sopenharmony_ci    eventLoopTid_ = std::this_thread::get_id();
9911fccf17Sopenharmony_ci    event_ = std::make_unique<HRilEvent>();
10011fccf17Sopenharmony_ci    event_->TimerEventInit();
10111fccf17Sopenharmony_ci
10211fccf17Sopenharmony_ci    int32_t pipedes[PIPE_SIZE_MAX];
10311fccf17Sopenharmony_ci    int32_t ret = pipe(pipedes);
10411fccf17Sopenharmony_ci    if (ret < 0) {
10511fccf17Sopenharmony_ci        TELEPHONY_LOGE("Call pipe() is failed, errno:%{public}d", errno);
10611fccf17Sopenharmony_ci        return;
10711fccf17Sopenharmony_ci    }
10811fccf17Sopenharmony_ci
10911fccf17Sopenharmony_ci    triggerReadFd_ = pipedes[0];
11011fccf17Sopenharmony_ci    triggerWriteFd_ = pipedes[1];
11111fccf17Sopenharmony_ci
11211fccf17Sopenharmony_ci    fcntl(triggerReadFd_, F_SETFL, O_NONBLOCK);
11311fccf17Sopenharmony_ci    auto func =
11411fccf17Sopenharmony_ci        [this](int32_t fd, int16_t events, std::shared_ptr<void> param) { this->FdTriggerCallback(fd, events, param); };
11511fccf17Sopenharmony_ci    event_->SetTimerEvent(fdTriggerEvent_, triggerReadFd_, true, func, NULL);
11611fccf17Sopenharmony_ci    event_->AddEventMessage(fdTriggerEvent_);
11711fccf17Sopenharmony_ci    event_->EventMessageLoop();
11811fccf17Sopenharmony_ci    TELEPHONY_LOGE("error in EventMessageLoop errno:%{public}d, isNormalDestory:%{public}d",
11911fccf17Sopenharmony_ci        errno, event_->IsNormalDestory());
12011fccf17Sopenharmony_ci    if (!event_->IsNormalDestory()) {
12111fccf17Sopenharmony_ci        EventLoop();
12211fccf17Sopenharmony_ci    }
12311fccf17Sopenharmony_ci}
12411fccf17Sopenharmony_ci} // namespace Telephony
12511fccf17Sopenharmony_ci} // namespace OHOS