1c29fa5a6Sopenharmony_ci/* 2c29fa5a6Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License. 5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at 6c29fa5a6Sopenharmony_ci * 7c29fa5a6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8c29fa5a6Sopenharmony_ci * 9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and 13c29fa5a6Sopenharmony_ci * limitations under the License. 14c29fa5a6Sopenharmony_ci */ 15c29fa5a6Sopenharmony_ci 16c29fa5a6Sopenharmony_ci#include "timer_manager.h" 17c29fa5a6Sopenharmony_ci 18c29fa5a6Sopenharmony_ci#include <numeric> 19c29fa5a6Sopenharmony_ci 20c29fa5a6Sopenharmony_ci#include <sys/timerfd.h> 21c29fa5a6Sopenharmony_ci 22c29fa5a6Sopenharmony_ci#include "devicestatus_define.h" 23c29fa5a6Sopenharmony_ci#include "fi_log.h" 24c29fa5a6Sopenharmony_ci#include "include/util.h" 25c29fa5a6Sopenharmony_ci 26c29fa5a6Sopenharmony_ci#undef LOG_TAG 27c29fa5a6Sopenharmony_ci#define LOG_TAG "TimerManager" 28c29fa5a6Sopenharmony_ci 29c29fa5a6Sopenharmony_cinamespace OHOS { 30c29fa5a6Sopenharmony_cinamespace Msdp { 31c29fa5a6Sopenharmony_cinamespace DeviceStatus { 32c29fa5a6Sopenharmony_cinamespace { 33c29fa5a6Sopenharmony_ciconstexpr int32_t MIN_DELAY { -1 }; 34c29fa5a6Sopenharmony_ciconstexpr int32_t NONEXISTENT_ID { -1 }; 35c29fa5a6Sopenharmony_ciconstexpr int32_t MIN_INTERVAL { 50 }; 36c29fa5a6Sopenharmony_ciconstexpr int32_t TIME_CONVERSION { 1000 }; 37c29fa5a6Sopenharmony_ciconstexpr int32_t MAX_INTERVAL_MS { 10000 }; 38c29fa5a6Sopenharmony_ciconstexpr size_t MAX_TIMER_COUNT { 64 }; 39c29fa5a6Sopenharmony_ci} // namespace 40c29fa5a6Sopenharmony_ci 41c29fa5a6Sopenharmony_ciint32_t TimerManager::OnInit(IContext *context) 42c29fa5a6Sopenharmony_ci{ 43c29fa5a6Sopenharmony_ci CHKPR(context, RET_ERR); 44c29fa5a6Sopenharmony_ci context_ = context; 45c29fa5a6Sopenharmony_ci 46c29fa5a6Sopenharmony_ci timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); 47c29fa5a6Sopenharmony_ci if (timerFd_ < 0) { 48c29fa5a6Sopenharmony_ci FI_HILOGE("timerfd_create failed"); 49c29fa5a6Sopenharmony_ci return RET_ERR; 50c29fa5a6Sopenharmony_ci } 51c29fa5a6Sopenharmony_ci return RET_OK; 52c29fa5a6Sopenharmony_ci} 53c29fa5a6Sopenharmony_ci 54c29fa5a6Sopenharmony_ciint32_t TimerManager::Init(IContext *context) 55c29fa5a6Sopenharmony_ci{ 56c29fa5a6Sopenharmony_ci CHKPR(context, RET_ERR); 57c29fa5a6Sopenharmony_ci return context->GetDelegateTasks().PostSyncTask([this, context] { 58c29fa5a6Sopenharmony_ci return this->OnInit(context); 59c29fa5a6Sopenharmony_ci }); 60c29fa5a6Sopenharmony_ci} 61c29fa5a6Sopenharmony_ci 62c29fa5a6Sopenharmony_ciint32_t TimerManager::OnAddTimer(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback) 63c29fa5a6Sopenharmony_ci{ 64c29fa5a6Sopenharmony_ci int32_t timerId = AddTimerInternal(intervalMs, repeatCount, callback); 65c29fa5a6Sopenharmony_ci ArmTimer(); 66c29fa5a6Sopenharmony_ci return timerId; 67c29fa5a6Sopenharmony_ci} 68c29fa5a6Sopenharmony_ci 69c29fa5a6Sopenharmony_ciint32_t TimerManager::AddTimer(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback) 70c29fa5a6Sopenharmony_ci{ 71c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 72c29fa5a6Sopenharmony_ci CHKPR(context_, RET_ERR); 73c29fa5a6Sopenharmony_ci return context_->GetDelegateTasks().PostSyncTask([this, intervalMs, repeatCount, callback] { 74c29fa5a6Sopenharmony_ci return this->OnAddTimer(intervalMs, repeatCount, callback); 75c29fa5a6Sopenharmony_ci }); 76c29fa5a6Sopenharmony_ci} 77c29fa5a6Sopenharmony_ci 78c29fa5a6Sopenharmony_ciint32_t TimerManager::OnRemoveTimer(int32_t timerId) 79c29fa5a6Sopenharmony_ci{ 80c29fa5a6Sopenharmony_ci int32_t ret = RemoveTimerInternal(timerId); 81c29fa5a6Sopenharmony_ci if (ret == RET_OK) { 82c29fa5a6Sopenharmony_ci ArmTimer(); 83c29fa5a6Sopenharmony_ci } 84c29fa5a6Sopenharmony_ci return ret; 85c29fa5a6Sopenharmony_ci} 86c29fa5a6Sopenharmony_ci 87c29fa5a6Sopenharmony_ciint32_t TimerManager::RemoveTimer(int32_t timerId) 88c29fa5a6Sopenharmony_ci{ 89c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 90c29fa5a6Sopenharmony_ci CHKPR(context_, RET_ERR); 91c29fa5a6Sopenharmony_ci return context_->GetDelegateTasks().PostSyncTask([this, timerId] { 92c29fa5a6Sopenharmony_ci return this->OnRemoveTimer(timerId); 93c29fa5a6Sopenharmony_ci }); 94c29fa5a6Sopenharmony_ci} 95c29fa5a6Sopenharmony_ci 96c29fa5a6Sopenharmony_ciint32_t TimerManager::OnResetTimer(int32_t timerId) 97c29fa5a6Sopenharmony_ci{ 98c29fa5a6Sopenharmony_ci int32_t ret = ResetTimerInternal(timerId); 99c29fa5a6Sopenharmony_ci ArmTimer(); 100c29fa5a6Sopenharmony_ci return ret; 101c29fa5a6Sopenharmony_ci} 102c29fa5a6Sopenharmony_ci 103c29fa5a6Sopenharmony_ciint32_t TimerManager::ResetTimer(int32_t timerId) 104c29fa5a6Sopenharmony_ci{ 105c29fa5a6Sopenharmony_ci CALL_INFO_TRACE; 106c29fa5a6Sopenharmony_ci CHKPR(context_, RET_ERR); 107c29fa5a6Sopenharmony_ci return context_->GetDelegateTasks().PostSyncTask([this, timerId] { 108c29fa5a6Sopenharmony_ci return this->OnResetTimer(timerId); 109c29fa5a6Sopenharmony_ci }); 110c29fa5a6Sopenharmony_ci} 111c29fa5a6Sopenharmony_ci 112c29fa5a6Sopenharmony_cibool TimerManager::OnIsExist(int32_t timerId) const 113c29fa5a6Sopenharmony_ci{ 114c29fa5a6Sopenharmony_ci for (auto iter = timers_.begin(); iter != timers_.end(); ++iter) { 115c29fa5a6Sopenharmony_ci if ((*iter)->id == timerId) { 116c29fa5a6Sopenharmony_ci return true; 117c29fa5a6Sopenharmony_ci } 118c29fa5a6Sopenharmony_ci } 119c29fa5a6Sopenharmony_ci return false; 120c29fa5a6Sopenharmony_ci} 121c29fa5a6Sopenharmony_ci 122c29fa5a6Sopenharmony_cibool TimerManager::IsExist(int32_t timerId) const 123c29fa5a6Sopenharmony_ci{ 124c29fa5a6Sopenharmony_ci CHKPR(context_, false); 125c29fa5a6Sopenharmony_ci std::packaged_task<bool(int32_t)> task { [this](int32_t timerId) { 126c29fa5a6Sopenharmony_ci return this->OnIsExist(timerId); 127c29fa5a6Sopenharmony_ci } }; 128c29fa5a6Sopenharmony_ci auto fu = task.get_future(); 129c29fa5a6Sopenharmony_ci 130c29fa5a6Sopenharmony_ci int32_t ret = context_->GetDelegateTasks().PostSyncTask([this, &task, timerId] { 131c29fa5a6Sopenharmony_ci return this->RunIsExist(std::ref(task), timerId); 132c29fa5a6Sopenharmony_ci }); 133c29fa5a6Sopenharmony_ci if (ret != RET_OK) { 134c29fa5a6Sopenharmony_ci FI_HILOGE("Post task failed"); 135c29fa5a6Sopenharmony_ci return false; 136c29fa5a6Sopenharmony_ci } 137c29fa5a6Sopenharmony_ci return fu.get(); 138c29fa5a6Sopenharmony_ci} 139c29fa5a6Sopenharmony_ci 140c29fa5a6Sopenharmony_ciint32_t TimerManager::OnProcessTimers() 141c29fa5a6Sopenharmony_ci{ 142c29fa5a6Sopenharmony_ci ProcessTimersInternal(); 143c29fa5a6Sopenharmony_ci ArmTimer(); 144c29fa5a6Sopenharmony_ci return RET_OK; 145c29fa5a6Sopenharmony_ci} 146c29fa5a6Sopenharmony_ci 147c29fa5a6Sopenharmony_civoid TimerManager::ProcessTimers() 148c29fa5a6Sopenharmony_ci{ 149c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 150c29fa5a6Sopenharmony_ci CHKPV(context_); 151c29fa5a6Sopenharmony_ci context_->GetDelegateTasks().PostAsyncTask([this] { 152c29fa5a6Sopenharmony_ci return this->OnProcessTimers(); 153c29fa5a6Sopenharmony_ci }); 154c29fa5a6Sopenharmony_ci} 155c29fa5a6Sopenharmony_ci 156c29fa5a6Sopenharmony_ciint32_t TimerManager::RunIsExist(std::packaged_task<bool(int32_t)> &task, int32_t timerId) const 157c29fa5a6Sopenharmony_ci{ 158c29fa5a6Sopenharmony_ci task(timerId); 159c29fa5a6Sopenharmony_ci return RET_OK; 160c29fa5a6Sopenharmony_ci} 161c29fa5a6Sopenharmony_ci 162c29fa5a6Sopenharmony_ciint32_t TimerManager::TakeNextTimerId() 163c29fa5a6Sopenharmony_ci{ 164c29fa5a6Sopenharmony_ci uint64_t timerSlot = std::accumulate(timers_.cbegin(), timers_.cend(), uint64_t(0U), 165c29fa5a6Sopenharmony_ci [] (uint64_t s, const auto &timer) { 166c29fa5a6Sopenharmony_ci return (s |= (uint64_t(1U) << timer->id)); 167c29fa5a6Sopenharmony_ci }); 168c29fa5a6Sopenharmony_ci for (size_t tmpCount = 0; tmpCount < MAX_TIMER_COUNT; ++tmpCount) { 169c29fa5a6Sopenharmony_ci if ((timerSlot & (uint64_t(1U) << tmpCount)) == 0) { 170c29fa5a6Sopenharmony_ci return tmpCount; 171c29fa5a6Sopenharmony_ci } 172c29fa5a6Sopenharmony_ci } 173c29fa5a6Sopenharmony_ci return NONEXISTENT_ID; 174c29fa5a6Sopenharmony_ci} 175c29fa5a6Sopenharmony_ci 176c29fa5a6Sopenharmony_ciint32_t TimerManager::AddTimerInternal(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback) 177c29fa5a6Sopenharmony_ci{ 178c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 179c29fa5a6Sopenharmony_ci if (intervalMs < MIN_INTERVAL) { 180c29fa5a6Sopenharmony_ci intervalMs = MIN_INTERVAL; 181c29fa5a6Sopenharmony_ci } else if (intervalMs > MAX_INTERVAL_MS) { 182c29fa5a6Sopenharmony_ci intervalMs = MAX_INTERVAL_MS; 183c29fa5a6Sopenharmony_ci } 184c29fa5a6Sopenharmony_ci if (!callback) { 185c29fa5a6Sopenharmony_ci return NONEXISTENT_ID; 186c29fa5a6Sopenharmony_ci } 187c29fa5a6Sopenharmony_ci int32_t nextTimerId = TakeNextTimerId(); 188c29fa5a6Sopenharmony_ci if (nextTimerId < 0) { 189c29fa5a6Sopenharmony_ci return NONEXISTENT_ID; 190c29fa5a6Sopenharmony_ci } 191c29fa5a6Sopenharmony_ci auto timer = std::make_unique<TimerItem>(); 192c29fa5a6Sopenharmony_ci timer->id = nextTimerId; 193c29fa5a6Sopenharmony_ci timer->repeatCount = repeatCount; 194c29fa5a6Sopenharmony_ci timer->intervalMs = intervalMs; 195c29fa5a6Sopenharmony_ci timer->callbackCount = 0; 196c29fa5a6Sopenharmony_ci int64_t nowTime = GetMillisTime(); 197c29fa5a6Sopenharmony_ci if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) { 198c29fa5a6Sopenharmony_ci FI_HILOGE("The addition of nextCallTime in TimerItem overflows"); 199c29fa5a6Sopenharmony_ci return NONEXISTENT_ID; 200c29fa5a6Sopenharmony_ci } 201c29fa5a6Sopenharmony_ci timer->callback = callback; 202c29fa5a6Sopenharmony_ci InsertTimerInternal(timer); 203c29fa5a6Sopenharmony_ci return nextTimerId; 204c29fa5a6Sopenharmony_ci} 205c29fa5a6Sopenharmony_ci 206c29fa5a6Sopenharmony_ciint32_t TimerManager::RemoveTimerInternal(int32_t timerId) 207c29fa5a6Sopenharmony_ci{ 208c29fa5a6Sopenharmony_ci for (auto iter = timers_.begin(); iter != timers_.end(); ++iter) { 209c29fa5a6Sopenharmony_ci if ((*iter)->id == timerId) { 210c29fa5a6Sopenharmony_ci timers_.erase(iter); 211c29fa5a6Sopenharmony_ci return RET_OK; 212c29fa5a6Sopenharmony_ci } 213c29fa5a6Sopenharmony_ci } 214c29fa5a6Sopenharmony_ci return RET_ERR; 215c29fa5a6Sopenharmony_ci} 216c29fa5a6Sopenharmony_ci 217c29fa5a6Sopenharmony_ciint32_t TimerManager::ResetTimerInternal(int32_t timerId) 218c29fa5a6Sopenharmony_ci{ 219c29fa5a6Sopenharmony_ci for (auto iter = timers_.begin(); iter!= timers_.end(); ++iter) { 220c29fa5a6Sopenharmony_ci if ((*iter)->id == timerId) { 221c29fa5a6Sopenharmony_ci auto timer = std::move(*iter); 222c29fa5a6Sopenharmony_ci timers_.erase(iter); 223c29fa5a6Sopenharmony_ci int64_t nowTime = GetMillisTime(); 224c29fa5a6Sopenharmony_ci if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) { 225c29fa5a6Sopenharmony_ci FI_HILOGE("The addition of nextCallTime in TimerItem overflows"); 226c29fa5a6Sopenharmony_ci return RET_ERR; 227c29fa5a6Sopenharmony_ci } 228c29fa5a6Sopenharmony_ci timer->callbackCount = 0; 229c29fa5a6Sopenharmony_ci InsertTimerInternal(timer); 230c29fa5a6Sopenharmony_ci return RET_OK; 231c29fa5a6Sopenharmony_ci } 232c29fa5a6Sopenharmony_ci } 233c29fa5a6Sopenharmony_ci return RET_ERR; 234c29fa5a6Sopenharmony_ci} 235c29fa5a6Sopenharmony_ci 236c29fa5a6Sopenharmony_civoid TimerManager::InsertTimerInternal(std::unique_ptr<TimerItem> &timer) 237c29fa5a6Sopenharmony_ci{ 238c29fa5a6Sopenharmony_ci for (auto iter = timers_.begin(); iter != timers_.end(); ++iter) { 239c29fa5a6Sopenharmony_ci if ((*iter)->nextCallTime > timer->nextCallTime) { 240c29fa5a6Sopenharmony_ci timers_.insert(iter, std::move(timer)); 241c29fa5a6Sopenharmony_ci return; 242c29fa5a6Sopenharmony_ci } 243c29fa5a6Sopenharmony_ci } 244c29fa5a6Sopenharmony_ci timers_.push_back(std::move(timer)); 245c29fa5a6Sopenharmony_ci} 246c29fa5a6Sopenharmony_ci 247c29fa5a6Sopenharmony_ciint64_t TimerManager::CalcNextDelayInternal() 248c29fa5a6Sopenharmony_ci{ 249c29fa5a6Sopenharmony_ci int64_t delayTime = MIN_DELAY; 250c29fa5a6Sopenharmony_ci if (!timers_.empty()) { 251c29fa5a6Sopenharmony_ci int64_t nowTime = GetMillisTime(); 252c29fa5a6Sopenharmony_ci const auto &items = *timers_.begin(); 253c29fa5a6Sopenharmony_ci if (nowTime >= items->nextCallTime) { 254c29fa5a6Sopenharmony_ci delayTime = 0; 255c29fa5a6Sopenharmony_ci } else { 256c29fa5a6Sopenharmony_ci delayTime = items->nextCallTime - nowTime; 257c29fa5a6Sopenharmony_ci } 258c29fa5a6Sopenharmony_ci } 259c29fa5a6Sopenharmony_ci return delayTime; 260c29fa5a6Sopenharmony_ci} 261c29fa5a6Sopenharmony_ci 262c29fa5a6Sopenharmony_civoid TimerManager::ProcessTimersInternal() 263c29fa5a6Sopenharmony_ci{ 264c29fa5a6Sopenharmony_ci if (timers_.empty()) { 265c29fa5a6Sopenharmony_ci return; 266c29fa5a6Sopenharmony_ci } 267c29fa5a6Sopenharmony_ci int64_t presentTime = GetMillisTime(); 268c29fa5a6Sopenharmony_ci for (;;) { 269c29fa5a6Sopenharmony_ci auto tIter = timers_.begin(); 270c29fa5a6Sopenharmony_ci if (tIter == timers_.end()) { 271c29fa5a6Sopenharmony_ci break; 272c29fa5a6Sopenharmony_ci } 273c29fa5a6Sopenharmony_ci if ((*tIter)->nextCallTime > presentTime) { 274c29fa5a6Sopenharmony_ci break; 275c29fa5a6Sopenharmony_ci } 276c29fa5a6Sopenharmony_ci auto currentTimer = std::move(*tIter); 277c29fa5a6Sopenharmony_ci timers_.erase(tIter); 278c29fa5a6Sopenharmony_ci ++currentTimer->callbackCount; 279c29fa5a6Sopenharmony_ci if ((currentTimer->repeatCount >= 1) && (currentTimer->callbackCount >= currentTimer->repeatCount)) { 280c29fa5a6Sopenharmony_ci currentTimer->callback(); 281c29fa5a6Sopenharmony_ci continue; 282c29fa5a6Sopenharmony_ci } 283c29fa5a6Sopenharmony_ci if (!AddInt64(currentTimer->nextCallTime, currentTimer->intervalMs, currentTimer->nextCallTime)) { 284c29fa5a6Sopenharmony_ci FI_HILOGE("The addition of nextCallTime in TimerItem overflows"); 285c29fa5a6Sopenharmony_ci return; 286c29fa5a6Sopenharmony_ci } 287c29fa5a6Sopenharmony_ci auto callback = currentTimer->callback; 288c29fa5a6Sopenharmony_ci InsertTimerInternal(currentTimer); 289c29fa5a6Sopenharmony_ci callback(); 290c29fa5a6Sopenharmony_ci } 291c29fa5a6Sopenharmony_ci} 292c29fa5a6Sopenharmony_ci 293c29fa5a6Sopenharmony_ciint32_t TimerManager::ArmTimer() 294c29fa5a6Sopenharmony_ci{ 295c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 296c29fa5a6Sopenharmony_ci if (timerFd_ < 0) { 297c29fa5a6Sopenharmony_ci FI_HILOGE("TimerManager is not initialized"); 298c29fa5a6Sopenharmony_ci return RET_ERR; 299c29fa5a6Sopenharmony_ci } 300c29fa5a6Sopenharmony_ci struct itimerspec tspec {}; 301c29fa5a6Sopenharmony_ci int64_t expire = CalcNextDelayInternal(); 302c29fa5a6Sopenharmony_ci FI_HILOGI("The next expire %{public}" PRId64, expire); 303c29fa5a6Sopenharmony_ci 304c29fa5a6Sopenharmony_ci if (expire == 0) { 305c29fa5a6Sopenharmony_ci expire = 1; 306c29fa5a6Sopenharmony_ci } 307c29fa5a6Sopenharmony_ci if (expire > 0) { 308c29fa5a6Sopenharmony_ci tspec.it_value.tv_sec = expire / TIME_CONVERSION; 309c29fa5a6Sopenharmony_ci tspec.it_value.tv_nsec = (expire % TIME_CONVERSION) * TIME_CONVERSION * TIME_CONVERSION; 310c29fa5a6Sopenharmony_ci } 311c29fa5a6Sopenharmony_ci 312c29fa5a6Sopenharmony_ci if (timerfd_settime(timerFd_, 0, &tspec, NULL) != 0) { 313c29fa5a6Sopenharmony_ci FI_HILOGE("Timer: the timerfd_settime is error"); 314c29fa5a6Sopenharmony_ci return RET_ERR; 315c29fa5a6Sopenharmony_ci } 316c29fa5a6Sopenharmony_ci return RET_OK; 317c29fa5a6Sopenharmony_ci} 318c29fa5a6Sopenharmony_ci} // namespace DeviceStatus 319c29fa5a6Sopenharmony_ci} // namespace Msdp 320c29fa5a6Sopenharmony_ci} // namespace OHOS 321