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