1 /*
2 * Copyright (c) 2021-2025 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 #undef MMI_LOG_TAG
19 #define MMI_LOG_TAG "TimerManager"
20 #undef MMI_LOG_DOMAIN
21 #define MMI_LOG_DOMAIN MMI_LOG_SERVER
22
23 namespace OHOS {
24 namespace MMI {
25 namespace {
26 constexpr int32_t MIN_DELAY { -1 };
27 constexpr int32_t MIN_INTERVAL { 36 };
28 constexpr int32_t MAX_INTERVAL_MS { 10000 };
29 constexpr int32_t MAX_LONG_INTERVAL_MS { 30000 };
30 constexpr int32_t MAX_TIMER_COUNT { 64 };
31 constexpr int32_t NONEXISTENT_ID { -1 };
32 } // namespace
33
TimerManager()34 TimerManager::TimerManager() {}
~TimerManager()35 TimerManager::~TimerManager() {}
36
AddTimer(int32_t intervalMs,int32_t repeatCount,std::function<void ()> callback,const std::string & name)37 int32_t TimerManager::AddTimer(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback,
38 const std::string &name)
39 {
40 if (intervalMs < MIN_INTERVAL) {
41 intervalMs = MIN_INTERVAL;
42 } else if (intervalMs > MAX_INTERVAL_MS) {
43 intervalMs = MAX_INTERVAL_MS;
44 }
45 return AddTimerInternal(intervalMs, repeatCount, callback, name);
46 }
47
AddLongTimer(int32_t intervalMs,int32_t repeatCount,std::function<void ()> callback,const std::string & name)48 int32_t TimerManager::AddLongTimer(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback,
49 const std::string &name)
50 {
51 if (intervalMs < MIN_INTERVAL) {
52 intervalMs = MIN_INTERVAL;
53 } else if (intervalMs > MAX_LONG_INTERVAL_MS) {
54 intervalMs = MAX_INTERVAL_MS;
55 }
56 return AddTimerInternal(intervalMs, repeatCount, callback, name);
57 }
58
RemoveTimer(int32_t timerId,const std::string & name)59 int32_t TimerManager::RemoveTimer(int32_t timerId, const std::string &name)
60 {
61 return RemoveTimerInternal(timerId, name);
62 }
63
ResetTimer(int32_t timerId)64 int32_t TimerManager::ResetTimer(int32_t timerId)
65 {
66 return ResetTimerInternal(timerId);
67 }
68
IsExist(int32_t timerId)69 bool TimerManager::IsExist(int32_t timerId)
70 {
71 return IsExistInternal(timerId);
72 }
73
CalcNextDelay()74 int32_t TimerManager::CalcNextDelay()
75 {
76 return CalcNextDelayInternal();
77 }
78
ProcessTimers()79 void TimerManager::ProcessTimers()
80 {
81 ProcessTimersInternal();
82 }
83
TakeNextTimerId()84 int32_t TimerManager::TakeNextTimerId()
85 {
86 uint64_t timerSlot = 0;
87 uint64_t one = 1;
88 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
89 for (const auto &timer : timers_) {
90 timerSlot |= (one << timer->id);
91 }
92
93 for (int32_t i = 0; i < MAX_TIMER_COUNT; i++) {
94 if ((timerSlot & (one << i)) == 0) {
95 return i;
96 }
97 }
98 return NONEXISTENT_ID;
99 }
100
AddTimerInternal(int32_t intervalMs,int32_t repeatCount,std::function<void ()> callback,const std::string & name)101 int32_t TimerManager::AddTimerInternal(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback,
102 const std::string &name)
103 {
104 if (!callback) {
105 return NONEXISTENT_ID;
106 }
107 auto timer = std::make_unique<TimerItem>();
108 timer->intervalMs = intervalMs;
109 timer->repeatCount = repeatCount;
110 timer->callbackCount = 0;
111 timer->name = name;
112 auto nowTime = GetMillisTime();
113 if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) {
114 MMI_HILOGE("The addition of nextCallTime in TimerItem overflows");
115 return NONEXISTENT_ID;
116 }
117 timer->callback = callback;
118 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
119 int32_t timerId = TakeNextTimerId();
120 if (timerId < 0) {
121 return NONEXISTENT_ID;
122 }
123 timer->id = timerId;
124 InsertTimerInternal(timer);
125 return timerId;
126 }
127
RemoveTimerInternal(int32_t timerId,const std::string & name)128 int32_t TimerManager::RemoveTimerInternal(int32_t timerId, const std::string &name)
129 {
130 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
131 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
132 if ((*it)->id == timerId && (name.empty() || (*it)->name == name)) {
133 timers_.erase(it);
134 return RET_OK;
135 }
136 }
137 return RET_ERR;
138 }
139
ResetTimerInternal(int32_t timerId)140 int32_t TimerManager::ResetTimerInternal(int32_t timerId)
141 {
142 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
143 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
144 if ((*it)->id == timerId) {
145 auto timer = std::move(*it);
146 timers_.erase(it);
147 auto nowTime = GetMillisTime();
148 if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) {
149 MMI_HILOGE("The addition of nextCallTime in TimerItem overflows");
150 return RET_ERR;
151 }
152 timer->callbackCount = 0;
153 InsertTimerInternal(timer);
154 return RET_OK;
155 }
156 }
157 return RET_ERR;
158 }
159
IsExistInternal(int32_t timerId)160 bool TimerManager::IsExistInternal(int32_t timerId)
161 {
162 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
163 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
164 if ((*it)->id == timerId) {
165 return true;
166 }
167 }
168 return false;
169 }
170
InsertTimerInternal(std::unique_ptr<TimerItem> & timer)171 void TimerManager::InsertTimerInternal(std::unique_ptr<TimerItem>& timer)
172 {
173 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
174 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
175 if ((*it)->nextCallTime > timer->nextCallTime) {
176 timers_.insert(it, std::move(timer));
177 return;
178 }
179 }
180 timers_.push_back(std::move(timer));
181 }
182
CalcNextDelayInternal()183 int32_t TimerManager::CalcNextDelayInternal()
184 {
185 auto delay = MIN_DELAY;
186 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
187 if (!timers_.empty()) {
188 auto nowTime = GetMillisTime();
189 const auto& item = *timers_.begin();
190 if (nowTime >= item->nextCallTime) {
191 delay = 0;
192 } else {
193 delay = item->nextCallTime - nowTime;
194 }
195 }
196 return delay;
197 }
198
ProcessTimersInternal()199 void TimerManager::ProcessTimersInternal()
200 {
201 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
202 if (timers_.empty()) {
203 return;
204 }
205 auto nowTime = GetMillisTime();
206 for (;;) {
207 auto it = timers_.begin();
208 if (it == timers_.end()) {
209 break;
210 }
211 if ((*it)->nextCallTime > nowTime) {
212 break;
213 }
214 auto curTimer = std::move(*it);
215 CrashObjDumper dumper((curTimer->name).c_str());
216 timers_.erase(it);
217 ++curTimer->callbackCount;
218 if ((curTimer->repeatCount >= 1) && (curTimer->callbackCount >= curTimer->repeatCount)) {
219 curTimer->callback();
220 continue;
221 }
222 if (!AddInt64(curTimer->nextCallTime, curTimer->intervalMs, curTimer->nextCallTime)) {
223 MMI_HILOGE("The addition of nextCallTime in TimerItem overflows");
224 return;
225 }
226 auto callback = curTimer->callback;
227 InsertTimerInternal(curTimer);
228 callback();
229 }
230 }
231 } // namespace MMI
232 } // namespace OHOS
233