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 29namespace OHOS { 30namespace Telephony { 31void 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 41void 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 55void 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 68std::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 = 88 [this](int32_t fd, int16_t events, std::shared_ptr<void> param) { this->TimerCallback(fd, events, param); }; 89 event_->SetTimerEvent(eventMsg, event_->IVNALID_FD, false, funcCallback, pCbMsg); 90 event_->AddTimerEvent(eventMsg, timeout); 91 OnTriggerEvent(); 92 return pCbMsg; 93} 94 95void 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 = 114 [this](int32_t fd, int16_t events, std::shared_ptr<void> param) { this->FdTriggerCallback(fd, events, param); }; 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