• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "timer_manager.h"
17 
18 #include <numeric>
19 
20 #include <sys/timerfd.h>
21 
22 #include "devicestatus_define.h"
23 #include "fi_log.h"
24 #include "include/util.h"
25 
26 #undef LOG_TAG
27 #define LOG_TAG "TimerManager"
28 
29 namespace OHOS {
30 namespace Msdp {
31 namespace DeviceStatus {
32 namespace {
33 constexpr int32_t MIN_DELAY { -1 };
34 constexpr int32_t NONEXISTENT_ID { -1 };
35 constexpr int32_t MIN_INTERVAL { 50 };
36 constexpr int32_t TIME_CONVERSION { 1000 };
37 constexpr int32_t MAX_INTERVAL_MS { 600000 };
38 constexpr size_t MAX_TIMER_COUNT { 64 };
39 } // namespace
40 
OnInit(IContext * context)41 int32_t TimerManager::OnInit(IContext *context)
42 {
43     CHKPR(context, RET_ERR);
44     context_ = context;
45 
46     timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
47     if (timerFd_ < 0) {
48         FI_HILOGE("timerfd_create failed");
49         return RET_ERR;
50     }
51     return RET_OK;
52 }
53 
Init(IContext * context)54 int32_t TimerManager::Init(IContext *context)
55 {
56     CHKPR(context, RET_ERR);
57     return context->GetDelegateTasks().PostSyncTask([this, context] {
58         return this->OnInit(context);
59     });
60 }
61 
OnAddTimer(int32_t intervalMs,int32_t repeatCount,std::function<void ()> callback)62 int32_t TimerManager::OnAddTimer(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback)
63 {
64     int32_t timerId = AddTimerInternal(intervalMs, repeatCount, callback);
65     ArmTimer();
66     return timerId;
67 }
68 
AddTimer(int32_t intervalMs,int32_t repeatCount,std::function<void ()> callback)69 int32_t TimerManager::AddTimer(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback)
70 {
71     CALL_DEBUG_ENTER;
72     CHKPR(context_, RET_ERR);
73     return context_->GetDelegateTasks().PostSyncTask([this, intervalMs, repeatCount, callback] {
74         return this->OnAddTimer(intervalMs, repeatCount, callback);
75     });
76 }
77 
AddTimerAsync(int32_t intervalMs,int32_t repeatCount,std::function<void ()> callback)78 int32_t TimerManager::AddTimerAsync(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback)
79 {
80     CALL_DEBUG_ENTER;
81     CHKPR(context_, RET_ERR);
82     return context_->GetDelegateTasks().PostAsyncTask([this, intervalMs, repeatCount, callback] {
83         return this->OnAddTimer(intervalMs, repeatCount, callback);
84     });
85 }
86 
OnRemoveTimer(int32_t timerId)87 int32_t TimerManager::OnRemoveTimer(int32_t timerId)
88 {
89     int32_t ret = RemoveTimerInternal(timerId);
90     if (ret == RET_OK) {
91         ArmTimer();
92     }
93     return ret;
94 }
95 
RemoveTimer(int32_t timerId)96 int32_t TimerManager::RemoveTimer(int32_t timerId)
97 {
98     CALL_DEBUG_ENTER;
99     CHKPR(context_, RET_ERR);
100     return context_->GetDelegateTasks().PostSyncTask([this, timerId] {
101         return this->OnRemoveTimer(timerId);
102     });
103 }
104 
RemoveTimerAsync(int32_t timerId)105 int32_t TimerManager::RemoveTimerAsync(int32_t timerId)
106 {
107     CALL_DEBUG_ENTER;
108     CHKPR(context_, RET_ERR);
109     return context_->GetDelegateTasks().PostAsyncTask([this, timerId] {
110         return this->OnRemoveTimer(timerId);
111     });
112 }
113 
OnResetTimer(int32_t timerId)114 int32_t TimerManager::OnResetTimer(int32_t timerId)
115 {
116     int32_t ret = ResetTimerInternal(timerId);
117     ArmTimer();
118     return ret;
119 }
120 
ResetTimer(int32_t timerId)121 int32_t TimerManager::ResetTimer(int32_t timerId)
122 {
123     CALL_INFO_TRACE;
124     CHKPR(context_, RET_ERR);
125     return context_->GetDelegateTasks().PostSyncTask([this, timerId] {
126         return this->OnResetTimer(timerId);
127     });
128 }
129 
OnIsExist(int32_t timerId) const130 bool TimerManager::OnIsExist(int32_t timerId) const
131 {
132     for (auto iter = timers_.begin(); iter != timers_.end(); ++iter) {
133         if ((*iter)->id == timerId) {
134             return true;
135         }
136     }
137     return false;
138 }
139 
IsExist(int32_t timerId) const140 bool TimerManager::IsExist(int32_t timerId) const
141 {
142     CHKPR(context_, false);
143     std::packaged_task<bool(int32_t)> task { [this](int32_t timerId) {
144         return this->OnIsExist(timerId);
145     } };
146     auto fu = task.get_future();
147 
148     int32_t ret = context_->GetDelegateTasks().PostSyncTask([this, &task, timerId] {
149         return this->RunIsExist(std::ref(task), timerId);
150     });
151     if (ret != RET_OK) {
152         FI_HILOGE("Post task failed");
153         return false;
154     }
155     return fu.get();
156 }
157 
OnProcessTimers()158 int32_t TimerManager::OnProcessTimers()
159 {
160     ProcessTimersInternal();
161     ArmTimer();
162     return RET_OK;
163 }
164 
ProcessTimers()165 void TimerManager::ProcessTimers()
166 {
167     CALL_DEBUG_ENTER;
168     CHKPV(context_);
169     context_->GetDelegateTasks().PostAsyncTask([this] {
170         return this->OnProcessTimers();
171     });
172 }
173 
RunIsExist(std::packaged_task<bool (int32_t)> & task,int32_t timerId) const174 int32_t TimerManager::RunIsExist(std::packaged_task<bool(int32_t)> &task, int32_t timerId) const
175 {
176     task(timerId);
177     return RET_OK;
178 }
179 
TakeNextTimerId()180 int32_t TimerManager::TakeNextTimerId()
181 {
182     uint64_t timerSlot = std::accumulate(timers_.cbegin(), timers_.cend(), uint64_t(0U),
183         [] (uint64_t s, const auto &timer) {
184             return (s |= (uint64_t(1U) << timer->id));
185         });
186     for (size_t tmpCount = 0; tmpCount < MAX_TIMER_COUNT; ++tmpCount) {
187         if ((timerSlot & (uint64_t(1U) << tmpCount)) == 0) {
188             return tmpCount;
189         }
190     }
191     return NONEXISTENT_ID;
192 }
193 
AddTimerInternal(int32_t intervalMs,int32_t repeatCount,std::function<void ()> callback)194 int32_t TimerManager::AddTimerInternal(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback)
195 {
196     CALL_DEBUG_ENTER;
197     if (intervalMs < MIN_INTERVAL) {
198         intervalMs = MIN_INTERVAL;
199     } else if (intervalMs > MAX_INTERVAL_MS) {
200         intervalMs = MAX_INTERVAL_MS;
201     }
202     if (!callback) {
203         return NONEXISTENT_ID;
204     }
205     int32_t nextTimerId = TakeNextTimerId();
206     if (nextTimerId < 0) {
207         return NONEXISTENT_ID;
208     }
209     auto timer = std::make_unique<TimerItem>();
210     timer->id = nextTimerId;
211     timer->repeatCount = repeatCount;
212     timer->intervalMs = intervalMs;
213     timer->callbackCount = 0;
214     int64_t nowTime = GetMillisTime();
215     if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) {
216         FI_HILOGE("The addition of nextCallTime in TimerItem overflows");
217         return NONEXISTENT_ID;
218     }
219     timer->callback = callback;
220     InsertTimerInternal(timer);
221     return nextTimerId;
222 }
223 
RemoveTimerInternal(int32_t timerId)224 int32_t TimerManager::RemoveTimerInternal(int32_t timerId)
225 {
226     for (auto iter = timers_.begin(); iter != timers_.end(); ++iter) {
227         if ((*iter)->id == timerId) {
228             timers_.erase(iter);
229             return RET_OK;
230         }
231     }
232     return RET_ERR;
233 }
234 
ResetTimerInternal(int32_t timerId)235 int32_t TimerManager::ResetTimerInternal(int32_t timerId)
236 {
237     for (auto iter = timers_.begin(); iter!= timers_.end(); ++iter) {
238         if ((*iter)->id == timerId) {
239             auto timer = std::move(*iter);
240             timers_.erase(iter);
241             int64_t nowTime = GetMillisTime();
242             if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) {
243                 FI_HILOGE("The addition of nextCallTime in TimerItem overflows");
244                 return RET_ERR;
245             }
246             timer->callbackCount = 0;
247             InsertTimerInternal(timer);
248             return RET_OK;
249         }
250     }
251     return RET_ERR;
252 }
253 
InsertTimerInternal(std::unique_ptr<TimerItem> & timer)254 void TimerManager::InsertTimerInternal(std::unique_ptr<TimerItem> &timer)
255 {
256     for (auto iter = timers_.begin(); iter != timers_.end(); ++iter) {
257         if ((*iter)->nextCallTime > timer->nextCallTime) {
258             timers_.insert(iter, std::move(timer));
259             return;
260         }
261     }
262     timers_.push_back(std::move(timer));
263 }
264 
CalcNextDelayInternal()265 int64_t TimerManager::CalcNextDelayInternal()
266 {
267     int64_t delayTime = MIN_DELAY;
268     if (!timers_.empty()) {
269         int64_t nowTime = GetMillisTime();
270         const auto &items = *timers_.begin();
271         if (nowTime >= items->nextCallTime) {
272             delayTime = 0;
273         } else {
274             delayTime = items->nextCallTime - nowTime;
275         }
276     }
277     return delayTime;
278 }
279 
ProcessTimersInternal()280 void TimerManager::ProcessTimersInternal()
281 {
282     if (timers_.empty()) {
283         return;
284     }
285     int64_t presentTime = GetMillisTime();
286     for (;;) {
287         auto tIter = timers_.begin();
288         if (tIter == timers_.end()) {
289             break;
290         }
291         if ((*tIter)->nextCallTime > presentTime) {
292             break;
293         }
294         auto currentTimer = std::move(*tIter);
295         timers_.erase(tIter);
296         ++currentTimer->callbackCount;
297         if ((currentTimer->repeatCount >= 1) && (currentTimer->callbackCount >= currentTimer->repeatCount)) {
298             currentTimer->callback();
299             continue;
300         }
301         if (!AddInt64(currentTimer->nextCallTime, currentTimer->intervalMs, currentTimer->nextCallTime)) {
302             FI_HILOGE("The addition of nextCallTime in TimerItem overflows");
303             return;
304         }
305         auto callback = currentTimer->callback;
306         InsertTimerInternal(currentTimer);
307         callback();
308     }
309 }
310 
ArmTimer()311 int32_t TimerManager::ArmTimer()
312 {
313     CALL_DEBUG_ENTER;
314     if (timerFd_ < 0) {
315         FI_HILOGE("TimerManager is not initialized");
316         return RET_ERR;
317     }
318     struct itimerspec tspec {};
319     int64_t expire = CalcNextDelayInternal();
320     FI_HILOGD("The next expire %{public}" PRId64, expire);
321 
322     if (expire == 0) {
323         expire = 1;
324     }
325     if (expire > 0) {
326         tspec.it_value.tv_sec = expire / TIME_CONVERSION;
327         tspec.it_value.tv_nsec = (expire % TIME_CONVERSION) * TIME_CONVERSION * TIME_CONVERSION;
328     }
329 
330     if (timerfd_settime(timerFd_, 0, &tspec, NULL) != 0) {
331         FI_HILOGE("Timer: the timerfd_settime is error");
332         return RET_ERR;
333     }
334     return RET_OK;
335 }
336 } // namespace DeviceStatus
337 } // namespace Msdp
338 } // namespace OHOS
339