1 /*
2 * Copyright (C) 2022 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 #include <utility>
18 #include <vector>
19 #include <algorithm>
20 #include <ctime>
21 #include <iostream>
22 #include <sys/time.h>
23 #include "if_system_ability_manager.h"
24 #include "system_ability_definition.h"
25 #include "iservice_registry.h"
26
27 namespace OHOS {
28 namespace MiscServices {
29 using namespace std::chrono;
30 using namespace OHOS::AppExecFwk;
31 namespace {
32 static int TIME_CHANGED_BITS = 16;
33 static uint32_t TIME_CHANGED_MASK = 1 << TIME_CHANGED_BITS;
34 const int ONE_THOUSAND = 1000;
35 const float_t BATCH_WINDOW_COE = 0.75;
36 const auto ZERO_FUTURITY = seconds(0);
37 const auto MIN_INTERVAL_ONE_SECONDS = seconds(1);
38 const auto MAX_INTERVAL = hours(24 * 365);
39 const auto INTERVAL_HOUR = hours(1);
40 const auto INTERVAL_HALF_DAY = hours(12);
41 const auto MIN_FUZZABLE_INTERVAL = milliseconds(10000);
42 const int NANO_TO_SECOND = 1000000000;
43 const int WANTAGENT_CODE_ELEVEN = 11;
44 }
45
46 extern bool AddBatchLocked(std::vector<std::shared_ptr<Batch>> &list, const std::shared_ptr<Batch> &batch);
47 extern steady_clock::time_point MaxTriggerTime(steady_clock::time_point now,
48 steady_clock::time_point triggerAtTime,
49 milliseconds interval);
50
Create()51 std::shared_ptr<TimerManager> TimerManager::Create()
52 {
53 auto impl = TimerHandler::Create();
54 if (impl == nullptr) {
55 TIME_HILOGE(TIME_MODULE_SERVICE, "Create Timer handle failed.");
56 return nullptr;
57 }
58 return std::shared_ptr<TimerManager>(new TimerManager(impl));
59 }
60
TimerManager(std::shared_ptr<TimerHandler> impl)61 TimerManager::TimerManager(std::shared_ptr<TimerHandler> impl)
62 : random_ {static_cast<uint64_t>(time(nullptr))},
63 runFlag_ {false},
64 handler_ {std::move(impl)},
65 lastTimeChangeClockTime_ {system_clock::time_point::min()},
66 lastTimeChangeRealtime_ {steady_clock::time_point::min()}
67 {
68 runFlag_ = true;
69 alarmThread_.reset(new std::thread(&TimerManager::TimerLooper, this));
70 }
71
CreateTimer(TimerPara & paras,std::function<void (const uint64_t)> callback,std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent,int uid,uint64_t & timerId)72 int32_t TimerManager::CreateTimer(TimerPara ¶s,
73 std::function<void (const uint64_t)> callback,
74 std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent,
75 int uid,
76 uint64_t &timerId)
77 {
78 TIME_HILOGI(TIME_MODULE_SERVICE,
79 "Create timer: %{public}d windowLength:%{public}" PRId64 "interval:%{public}" PRId64 "flag:%{public}d",
80 paras.timerType,
81 paras.windowLength,
82 paras.interval,
83 paras.flag);
84 while (timerId == 0) {
85 timerId = random_();
86 }
87 auto timerInfo = std::make_shared<TimerEntry>(TimerEntry {
88 timerId,
89 paras.timerType,
90 static_cast<uint64_t>(paras.windowLength),
91 paras.interval,
92 paras.flag,
93 std::move(callback),
94 wantAgent,
95 uid
96 });
97 std::lock_guard<std::mutex> lock(entryMapMutex_);
98 timerEntryMap_.insert(std::make_pair(timerId, timerInfo));
99 return E_TIME_OK;
100 }
101
StartTimer(uint64_t timerId,uint64_t triggerTime)102 int32_t TimerManager::StartTimer(uint64_t timerId, uint64_t triggerTime)
103 {
104 std::lock_guard<std::mutex> lock(entryMapMutex_);
105 auto it = timerEntryMap_.find(timerId);
106 if (it == timerEntryMap_.end()) {
107 TIME_HILOGE(TIME_MODULE_SERVICE, "Timer id not found: %{public}" PRId64 "", timerId);
108 return E_TIME_NOT_FOUND;
109 }
110 TIME_HILOGI(TIME_MODULE_SERVICE, "Start timer : %{public}" PRId64 "", timerId);
111 TIME_HILOGI(TIME_MODULE_SERVICE, "TriggerTime : %{public}" PRId64 "", triggerTime);
112 auto timerInfo = it->second;
113 SetHandler(timerInfo->id,
114 timerInfo->type,
115 triggerTime,
116 timerInfo->windowLength,
117 timerInfo->interval,
118 timerInfo->flag,
119 timerInfo->callback,
120 timerInfo->wantAgent,
121 timerInfo->uid);
122 return E_TIME_OK;
123 }
124
StopTimer(uint64_t timerId)125 int32_t TimerManager::StopTimer(uint64_t timerId)
126 {
127 return StopTimerInner(timerId, false) ? E_TIME_OK : E_TIME_DEAL_FAILED;
128 }
129
DestroyTimer(uint64_t timerId)130 int32_t TimerManager::DestroyTimer(uint64_t timerId)
131 {
132 return StopTimerInner(timerId, true) ? E_TIME_OK : E_TIME_DEAL_FAILED;
133 }
134
StopTimerInner(uint64_t timerNumber,bool needDestroy)135 bool TimerManager::StopTimerInner(uint64_t timerNumber, bool needDestroy)
136 {
137 TIME_HILOGD(TIME_MODULE_SERVICE, "start id: %{public}" PRId64 ", needDestroy: %{public}d",
138 timerNumber, needDestroy);
139 std::lock_guard<std::mutex> lock(entryMapMutex_);
140 auto it = timerEntryMap_.find(timerNumber);
141 if (it == timerEntryMap_.end()) {
142 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
143 return false;
144 }
145 RemoveHandler(timerNumber);
146 if (it->second) {
147 int32_t uid = it->second->uid;
148 RemoveProxy(timerNumber, uid);
149 }
150 if (needDestroy) {
151 timerEntryMap_.erase(it);
152 }
153 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
154 return true;
155 }
156
RemoveProxy(uint64_t timerNumber,int32_t uid)157 void TimerManager::RemoveProxy(uint64_t timerNumber, int32_t uid)
158 {
159 std::lock_guard<std::mutex> lock(proxyMutex_);
160 auto itMap = proxyMap_.find(uid);
161 if (itMap != proxyMap_.end()) {
162 auto alarms = itMap->second;
163 for (auto itAlarm = alarms.begin(); itAlarm != alarms.end();) {
164 if ((*itAlarm)->id == timerNumber) {
165 alarms.erase(itAlarm);
166 } else {
167 itAlarm++;
168 }
169 }
170 if (alarms.empty()) {
171 proxyMap_.erase(uid);
172 }
173 }
174 }
175
SetHandler(uint64_t id,int type,uint64_t triggerAtTime,uint64_t windowLength,uint64_t interval,int flag,std::function<void (const uint64_t)> callback,std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent,int uid)176 void TimerManager::SetHandler(uint64_t id,
177 int type,
178 uint64_t triggerAtTime,
179 uint64_t windowLength,
180 uint64_t interval,
181 int flag,
182 std::function<void (const uint64_t)> callback,
183 std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent,
184 int uid)
185 {
186 TIME_HILOGI(TIME_MODULE_SERVICE, "start id: %{public}" PRId64 "", id);
187 TIME_HILOGI(TIME_MODULE_SERVICE,
188 "start type:%{public}d windowLength:%{public}" PRId64"interval:%{public}" PRId64"flag:%{public}d",
189 type, windowLength, interval, flag);
190 auto windowLengthDuration = milliseconds(windowLength);
191 if (windowLengthDuration > INTERVAL_HALF_DAY) {
192 windowLengthDuration = INTERVAL_HOUR;
193 }
194 auto minInterval = MIN_INTERVAL_ONE_SECONDS;
195 auto intervalDuration = milliseconds(interval);
196 if (intervalDuration > milliseconds::zero() && intervalDuration < minInterval) {
197 intervalDuration = minInterval;
198 } else if (intervalDuration > MAX_INTERVAL) {
199 intervalDuration = MAX_INTERVAL;
200 }
201
202 auto nowElapsed = GetBootTimeNs();
203 auto nominalTrigger = ConvertToElapsed(milliseconds(triggerAtTime), type);
204 if (nominalTrigger < nowElapsed) {
205 TIME_HILOGI(TIME_MODULE_SERVICE, "invalid trigger time end.");
206 return;
207 }
208 auto minTrigger = nowElapsed + ZERO_FUTURITY;
209 auto triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
210
211 steady_clock::time_point maxElapsed;
212 if (windowLengthDuration == milliseconds::zero()) {
213 maxElapsed = triggerElapsed;
214 } else if (windowLengthDuration < milliseconds::zero()) {
215 maxElapsed = MaxTriggerTime(nominalTrigger, triggerElapsed, intervalDuration);
216 windowLengthDuration = duration_cast<milliseconds>(maxElapsed - triggerElapsed);
217 } else {
218 maxElapsed = triggerElapsed + windowLengthDuration;
219 }
220 TIME_HILOGI(TIME_MODULE_SERVICE, "Try get lock");
221 std::lock_guard<std::mutex> lockGuard(mutex_);
222 TIME_HILOGI(TIME_MODULE_SERVICE, "Lock guard");
223 SetHandlerLocked(id,
224 type,
225 milliseconds(triggerAtTime),
226 triggerElapsed,
227 windowLengthDuration,
228 maxElapsed,
229 intervalDuration,
230 std::move(callback),
231 wantAgent,
232 static_cast<uint32_t>(flag),
233 true,
234 uid);
235 }
236
SetHandlerLocked(uint64_t id,int type,std::chrono::milliseconds when,std::chrono::steady_clock::time_point whenElapsed,std::chrono::milliseconds windowLength,std::chrono::steady_clock::time_point maxWhen,std::chrono::milliseconds interval,std::function<void (const uint64_t)> callback,std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent,uint32_t flags,bool doValidate,uint64_t callingUid)237 void TimerManager::SetHandlerLocked(uint64_t id, int type,
238 std::chrono::milliseconds when,
239 std::chrono::steady_clock::time_point whenElapsed,
240 std::chrono::milliseconds windowLength,
241 std::chrono::steady_clock::time_point maxWhen,
242 std::chrono::milliseconds interval,
243 std::function<void (const uint64_t)> callback,
244 std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent,
245 uint32_t flags,
246 bool doValidate,
247 uint64_t callingUid)
248 {
249 TIME_HILOGI(TIME_MODULE_SERVICE, "start id: %{public}" PRId64 "", id);
250 auto alarm = std::make_shared<TimerInfo>(id, type, when, whenElapsed, windowLength, maxWhen,
251 interval, std::move(callback), wantAgent, flags, callingUid);
252 SetHandlerLocked(alarm, false, doValidate);
253 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
254 }
255
RemoveHandler(uint64_t id)256 void TimerManager::RemoveHandler(uint64_t id)
257 {
258 TIME_HILOGI(TIME_MODULE_SERVICE, "start");
259 std::lock_guard<std::mutex> lock(mutex_);
260 RemoveLocked(id);
261 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
262 }
263
RemoveLocked(uint64_t id)264 void TimerManager::RemoveLocked(uint64_t id)
265 {
266 TIME_HILOGI(TIME_MODULE_SERVICE, "start id: %{public}" PRId64 "", id);
267 auto whichAlarms = [id](const TimerInfo &timer) {
268 return timer.id == id;
269 };
270
271 bool didRemove = false;
272 for (auto it = alarmBatches_.begin(); it != alarmBatches_.end();) {
273 auto batch = *it;
274 didRemove = batch->Remove(whichAlarms);
275 if (batch->Size() == 0) {
276 TIME_HILOGD(TIME_MODULE_SERVICE, "erase");
277 it = alarmBatches_.erase(it);
278 } else {
279 ++it;
280 }
281 }
282
283 if (didRemove) {
284 ReBatchAllTimersLocked(true);
285 }
286 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
287 }
288
SetHandlerLocked(std::shared_ptr<TimerInfo> alarm,bool rebatching,bool doValidate)289 void TimerManager::SetHandlerLocked(std::shared_ptr<TimerInfo> alarm, bool rebatching, bool doValidate)
290 {
291 TIME_HILOGI(TIME_MODULE_SERVICE, "start rebatching= %{public}d, doValidate= %{public}d", rebatching, doValidate);
292 InsertAndBatchTimerLocked(std::move(alarm));
293 if (!rebatching) {
294 RescheduleKernelTimerLocked();
295 }
296 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
297 }
298
ReBatchAllTimers()299 void TimerManager::ReBatchAllTimers()
300 {
301 TIME_HILOGI(TIME_MODULE_SERVICE, "start");
302 ReBatchAllTimersLocked(true);
303 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
304 }
305
ReBatchAllTimersLocked(bool doValidate)306 void TimerManager::ReBatchAllTimersLocked(bool doValidate)
307 {
308 TIME_HILOGI(TIME_MODULE_SERVICE, "start");
309 auto oldSet = alarmBatches_;
310 alarmBatches_.clear();
311 auto nowElapsed = GetBootTimeNs();
312 for (const auto &batch : oldSet) {
313 auto n = batch->Size();
314 for (unsigned int i = 0; i < n; i++) {
315 ReAddTimerLocked(batch->Get(i), nowElapsed, doValidate);
316 }
317 }
318 RescheduleKernelTimerLocked();
319 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
320 }
321
ReAddTimerLocked(std::shared_ptr<TimerInfo> timer,std::chrono::steady_clock::time_point nowElapsed,bool doValidate)322 void TimerManager::ReAddTimerLocked(std::shared_ptr<TimerInfo> timer,
323 std::chrono::steady_clock::time_point nowElapsed,
324 bool doValidate)
325 {
326 TIME_HILOGI(TIME_MODULE_SERVICE, "start");
327 timer->when = timer->origWhen;
328 auto whenElapsed = ConvertToElapsed(timer->when, timer->type);
329 if (whenElapsed < nowElapsed) {
330 TIME_HILOGI(TIME_MODULE_SERVICE, "invalid timer end.");
331 return;
332 }
333 steady_clock::time_point maxElapsed;
334 if (timer->windowLength == milliseconds::zero()) {
335 maxElapsed = whenElapsed;
336 } else {
337 maxElapsed = (timer->windowLength > milliseconds::zero()) ?
338 (whenElapsed + timer->windowLength) :
339 MaxTriggerTime(nowElapsed, whenElapsed, timer->repeatInterval);
340 }
341 timer->whenElapsed = whenElapsed;
342 timer->maxWhenElapsed = maxElapsed;
343 SetHandlerLocked(timer, true, doValidate);
344 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
345 }
346
ConvertToElapsed(std::chrono::milliseconds when,int type)347 std::chrono::steady_clock::time_point TimerManager::ConvertToElapsed(std::chrono::milliseconds when, int type)
348 {
349 auto bootTimePoint = GetBootTimeNs();
350 TIME_HILOGI(TIME_MODULE_SERVICE, "start");
351 if (type == RTC || type == RTC_WAKEUP) {
352 auto systemTimeNow = system_clock::now().time_since_epoch();
353 auto offset = when - systemTimeNow;
354 TIME_HILOGI(TIME_MODULE_SERVICE, "systemTimeNow : %{public}lld", systemTimeNow.count());
355 TIME_HILOGI(TIME_MODULE_SERVICE, "offset : %{public}lld", offset.count());
356 return bootTimePoint + offset;
357 }
358 auto bootTimeNow = bootTimePoint.time_since_epoch();
359 auto offset = when - bootTimeNow;
360 TIME_HILOGI(TIME_MODULE_SERVICE, "bootTimeNow : %{public}lld", bootTimeNow.count());
361 TIME_HILOGI(TIME_MODULE_SERVICE, "offset : %{public}lld", offset.count());
362 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
363 return bootTimePoint + offset;
364 }
365
TimerLooper()366 void TimerManager::TimerLooper()
367 {
368 TIME_HILOGI(TIME_MODULE_SERVICE, "Start timer wait loop");
369 std::vector<std::shared_ptr<TimerInfo>> triggerList;
370 while (runFlag_) {
371 uint32_t result = 0;
372 do {
373 result = handler_->WaitForAlarm();
374 } while (result < 0 && errno == EINTR);
375
376 auto nowRtc = std::chrono::system_clock::now();
377 auto nowElapsed = GetBootTimeNs();
378 triggerList.clear();
379
380 if ((result & TIME_CHANGED_MASK) != 0) {
381 system_clock::time_point lastTimeChangeClockTime;
382 system_clock::time_point expectedClockTime;
383 std::lock_guard<std::mutex> lock(mutex_);
384 lastTimeChangeClockTime = lastTimeChangeClockTime_;
385 expectedClockTime = lastTimeChangeClockTime +
386 (duration_cast<milliseconds>(nowElapsed.time_since_epoch()) -
387 duration_cast<milliseconds>(lastTimeChangeRealtime_.time_since_epoch()));
388 if (lastTimeChangeClockTime == system_clock::time_point::min()
389 || nowRtc < (expectedClockTime - milliseconds(ONE_THOUSAND))
390 || nowRtc > (expectedClockTime + milliseconds(ONE_THOUSAND))) {
391 ReBatchAllTimers();
392 lastTimeChangeClockTime_ = nowRtc;
393 lastTimeChangeRealtime_ = nowElapsed;
394 }
395 }
396
397 if (result != TIME_CHANGED_MASK) {
398 std::lock_guard<std::mutex> lock(mutex_);
399 TriggerTimersLocked(triggerList, nowElapsed);
400 DeliverTimersLocked(triggerList, nowElapsed);
401 RescheduleKernelTimerLocked();
402 } else {
403 std::lock_guard<std::mutex> lock(mutex_);
404 RescheduleKernelTimerLocked();
405 }
406 }
407 }
408
~TimerManager()409 TimerManager::~TimerManager()
410 {
411 if (alarmThread_ && alarmThread_->joinable()) {
412 alarmThread_->join();
413 }
414 }
415
GetBootTimeNs()416 steady_clock::time_point TimerManager::GetBootTimeNs()
417 {
418 int64_t timeNow = -1;
419 struct timespec tv {};
420 if (clock_gettime(CLOCK_BOOTTIME, &tv) < 0) {
421 return steady_clock::now();
422 }
423 timeNow = tv.tv_sec * NANO_TO_SECOND + tv.tv_nsec;
424 steady_clock::time_point tp_epoch ((nanoseconds(timeNow)));
425 return tp_epoch;
426 }
427
TriggerTimersLocked(std::vector<std::shared_ptr<TimerInfo>> & triggerList,std::chrono::steady_clock::time_point nowElapsed)428 bool TimerManager::TriggerTimersLocked(std::vector<std::shared_ptr<TimerInfo>> &triggerList,
429 std::chrono::steady_clock::time_point nowElapsed)
430 {
431 bool hasWakeup = false;
432 while (!alarmBatches_.empty()) {
433 auto batch = alarmBatches_.at(0);
434 if (batch->GetStart() > nowElapsed) {
435 break;
436 }
437 alarmBatches_.erase(alarmBatches_.begin());
438 TIME_HILOGI(TIME_MODULE_SERVICE, "after erase alarmBatches_.size= %{public}d",
439 static_cast<int>(alarmBatches_.size()));
440
441 const auto n = batch->Size();
442 for (unsigned int i = 0; i < n; ++i) {
443 auto alarm = batch->Get(i);
444 alarm->count = 1;
445 triggerList.push_back(alarm);
446 TIME_HILOGI(TIME_MODULE_SERVICE, "alarm uid= %{public}d", alarm->uid);
447 if (alarm->repeatInterval > milliseconds::zero()) {
448 alarm->count += duration_cast<milliseconds>(nowElapsed -
449 alarm->expectedWhenElapsed) / alarm->repeatInterval;
450 auto delta = alarm->count * alarm->repeatInterval;
451 auto nextElapsed = alarm->whenElapsed + delta;
452 SetHandlerLocked(alarm->id, alarm->type, alarm->when + delta, nextElapsed, alarm->windowLength,
453 MaxTriggerTime(nowElapsed, nextElapsed, alarm->repeatInterval), alarm->repeatInterval,
454 alarm->callback, alarm->wantAgent, alarm->flags, true, alarm->uid);
455 }
456 if (alarm->wakeup) {
457 hasWakeup = true;
458 }
459 }
460 }
461 std::sort(triggerList.begin(),
462 triggerList.end(),
463 [] (const std::shared_ptr<TimerInfo> &l, const std::shared_ptr<TimerInfo> &r) {
464 return l->whenElapsed < r->whenElapsed;
465 });
466
467 return hasWakeup;
468 }
469
RescheduleKernelTimerLocked()470 void TimerManager::RescheduleKernelTimerLocked()
471 {
472 auto nextNonWakeup = std::chrono::steady_clock::time_point::min();
473 if (!alarmBatches_.empty()) {
474 auto firstWakeup = FindFirstWakeupBatchLocked();
475 auto firstBatch = alarmBatches_.front();
476 if (firstWakeup != nullptr) {
477 auto alarmPtr = firstWakeup->Get(0);
478 SetLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup->GetStart().time_since_epoch());
479 }
480 if (firstBatch != firstWakeup) {
481 auto alarmPtr = firstBatch->Get(0);
482 nextNonWakeup = firstBatch->GetStart();
483 }
484 }
485
486 if (nextNonWakeup != std::chrono::steady_clock::time_point::min()) {
487 SetLocked(ELAPSED_REALTIME, nextNonWakeup.time_since_epoch());
488 }
489 }
490
FindFirstWakeupBatchLocked()491 std::shared_ptr<Batch> TimerManager::FindFirstWakeupBatchLocked()
492 {
493 auto it = std::find_if(alarmBatches_.begin(),
494 alarmBatches_.end(),
495 [](const std::shared_ptr<Batch> &batch) {
496 return batch->HasWakeups();
497 });
498 return (it != alarmBatches_.end()) ? *it : nullptr;
499 }
500
SetLocked(int type,std::chrono::nanoseconds when)501 void TimerManager::SetLocked(int type, std::chrono::nanoseconds when)
502 {
503 handler_->Set(static_cast<uint32_t>(type), when);
504 }
505
InsertAndBatchTimerLocked(std::shared_ptr<TimerInfo> alarm)506 void TimerManager::InsertAndBatchTimerLocked(std::shared_ptr<TimerInfo> alarm)
507 {
508 TIME_HILOGI(TIME_MODULE_SERVICE, "start");
509 int64_t whichBatch = (alarm->flags & static_cast<uint32_t>(STANDALONE)) ? -1
510 : AttemptCoalesceLocked(alarm->whenElapsed, alarm->maxWhenElapsed);
511 TIME_HILOGI(TIME_MODULE_SERVICE, "whichBatch= %{public}" PRId64 "", whichBatch);
512 if (whichBatch < 0) {
513 AddBatchLocked(alarmBatches_, std::make_shared<Batch>(*alarm));
514 } else {
515 auto batch = alarmBatches_.at(whichBatch);
516 if (batch->Add(alarm)) {
517 alarmBatches_.erase(alarmBatches_.begin() + whichBatch);
518 AddBatchLocked(alarmBatches_, batch);
519 }
520 }
521 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
522 }
523
AttemptCoalesceLocked(std::chrono::steady_clock::time_point whenElapsed,std::chrono::steady_clock::time_point maxWhen)524 int64_t TimerManager::AttemptCoalesceLocked(std::chrono::steady_clock::time_point whenElapsed,
525 std::chrono::steady_clock::time_point maxWhen)
526 {
527 TIME_HILOGI(TIME_MODULE_SERVICE, "start");
528 int64_t i = 0;
529 for (const auto &item : alarmBatches_) {
530 if ((item->GetFlags() & static_cast<uint32_t>(STANDALONE)) == 0 && item->CanHold(whenElapsed, maxWhen)) {
531 return i;
532 }
533 }
534 return -1;
535 }
536
DeliverTimersLocked(const std::vector<std::shared_ptr<TimerInfo>> & triggerList,std::chrono::steady_clock::time_point nowElapsed)537 void TimerManager::DeliverTimersLocked(const std::vector<std::shared_ptr<TimerInfo>> &triggerList,
538 std::chrono::steady_clock::time_point nowElapsed)
539 {
540 for (const auto &alarm : triggerList) {
541 if (alarm->callback) {
542 CallbackAlarmIfNeed(alarm);
543 }
544 if (alarm->wantAgent) {
545 NotifyWantAgent(alarm->wantAgent);
546 }
547 }
548 }
549
NotifyWantAgent(std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent)550 void TimerManager::NotifyWantAgent(std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent)
551 {
552 TIME_HILOGD(TIME_MODULE_SERVICE, "trigger wantagent.");
553 std::shared_ptr<AAFwk::Want> want =
554 OHOS::AbilityRuntime::WantAgent::WantAgentHelper::GetWant(wantAgent);
555 OHOS::AbilityRuntime::WantAgent::TriggerInfo paramsInfo("", nullptr, want, WANTAGENT_CODE_ELEVEN);
556 OHOS::AbilityRuntime::WantAgent::WantAgentHelper::TriggerWantAgent(
557 wantAgent, nullptr, paramsInfo);
558 }
559
CallbackAlarmIfNeed(std::shared_ptr<TimerInfo> alarm)560 void TimerManager::CallbackAlarmIfNeed(std::shared_ptr<TimerInfo> alarm)
561 {
562 int uid = alarm->uid;
563 std::lock_guard<std::mutex> lock(proxyMutex_);
564 auto it = proxyUids_.find(uid);
565 if (it == proxyUids_.end()) {
566 alarm->callback(alarm->id);
567 TIME_HILOGI(TIME_MODULE_SERVICE, "Trigger id: %{public}" PRId64 "", alarm->id);
568 return;
569 }
570 TIME_HILOGI(TIME_MODULE_SERVICE, "Alarm is proxy!");
571 auto itMap = proxyMap_.find(uid);
572 if (itMap == proxyMap_.end()) {
573 std::vector<std::shared_ptr<TimerInfo>> timeInfoVec;
574 timeInfoVec.push_back(alarm);
575 proxyMap_[uid] = timeInfoVec;
576 } else {
577 std::vector<std::shared_ptr<TimerInfo>> timeInfoVec = itMap->second;
578 timeInfoVec.push_back(alarm);
579 proxyMap_[uid] = timeInfoVec;
580 }
581 }
582
ProxyTimer(int32_t uid,bool isProxy,bool needRetrigger)583 bool TimerManager::ProxyTimer(int32_t uid, bool isProxy, bool needRetrigger)
584 {
585 std::lock_guard<std::mutex> lock(proxyMutex_);
586 TIME_HILOGD(TIME_MODULE_SERVICE, "start");
587 if (isProxy) {
588 proxyUids_.insert(uid);
589 return true;
590 }
591 auto it = proxyUids_.find(uid);
592 if (it != proxyUids_.end()) {
593 proxyUids_.erase(uid);
594 } else {
595 TIME_HILOGE(TIME_MODULE_SERVICE, "Uid: %{public}d doesn't exist in the proxy list." PRId64 "", uid);
596 return false;
597 }
598 if (!needRetrigger) {
599 TIME_HILOGI(TIME_MODULE_SERVICE, "ProxyTimer doesn't need retrigger, clear all callbacks!");
600 proxyMap_.erase(uid);
601 return true;
602 }
603 auto itMap = proxyMap_.find(uid);
604 if (itMap != proxyMap_.end()) {
605 auto timeInfoVec = itMap->second;
606 for (const auto& alarm : timeInfoVec) {
607 if (!alarm->callback) {
608 TIME_HILOGE(TIME_MODULE_SERVICE, "ProxyTimer Callback is nullptr!");
609 continue;
610 }
611 alarm->callback(alarm->id);
612 TIME_HILOGD(TIME_MODULE_SERVICE, "Shut down proxy, proxyUid: %{public}d, alarmId: %{public}" PRId64 "",
613 uid, alarm->id);
614 }
615 timeInfoVec.clear();
616 proxyMap_.erase(uid);
617 }
618 return true;
619 }
620
ResetAllProxy()621 bool TimerManager::ResetAllProxy()
622 {
623 std::lock_guard<std::mutex> lock(proxyMutex_);
624 TIME_HILOGD(TIME_MODULE_SERVICE, "start");
625 for (auto it = proxyMap_.begin(); it != proxyMap_.end(); it++) {
626 auto timeInfoVec = it->second;
627 for (const auto& alarm : timeInfoVec) {
628 if (!alarm->callback) {
629 TIME_HILOGE(TIME_MODULE_SERVICE, "Callback is nullptr!");
630 continue;
631 }
632 alarm->callback(alarm->id);
633 TIME_HILOGD(TIME_MODULE_SERVICE, "Reset all proxy, proxyUid: %{public}d, alarmId: %{public}" PRId64 "",
634 it->first, alarm->id);
635 }
636 timeInfoVec.clear();
637 }
638 proxyMap_.clear();
639 proxyUids_.clear();
640 return true;
641 }
642
AddBatchLocked(std::vector<std::shared_ptr<Batch>> & list,const std::shared_ptr<Batch> & newBatch)643 bool AddBatchLocked(std::vector<std::shared_ptr<Batch>> &list, const std::shared_ptr<Batch> &newBatch)
644 {
645 TIME_HILOGI(TIME_MODULE_SERVICE, "start");
646 auto it = std::upper_bound(list.begin(),
647 list.end(),
648 newBatch,
649 [](const std::shared_ptr<Batch> &first, const std::shared_ptr<Batch> &second) {
650 return first->GetStart() < second->GetStart();
651 });
652 list.insert(it, newBatch);
653 TIME_HILOGI(TIME_MODULE_SERVICE, "end");
654 return it == list.begin();
655 }
656
MaxTriggerTime(steady_clock::time_point now,steady_clock::time_point triggerAtTime,milliseconds interval)657 steady_clock::time_point MaxTriggerTime(steady_clock::time_point now,
658 steady_clock::time_point triggerAtTime,
659 milliseconds interval)
660 {
661 milliseconds futurity = (interval == milliseconds::zero()) ?
662 (duration_cast<milliseconds>(triggerAtTime - now)) : interval;
663 if (futurity < MIN_FUZZABLE_INTERVAL) {
664 futurity = milliseconds::zero();
665 }
666 return triggerAtTime + milliseconds(static_cast<long>(BATCH_WINDOW_COE * futurity.count()));
667 }
668
ShowtimerEntryMap(int fd)669 bool TimerManager::ShowtimerEntryMap(int fd)
670 {
671 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
672 std::lock_guard<std::mutex> lock(showTimerMutex_);
673 std::map<uint64_t, std::shared_ptr<TimerEntry>>::iterator iter = timerEntryMap_.begin();
674 for (; iter != timerEntryMap_.end(); iter++) {
675 dprintf(fd, " - dump timer number = %lu\n", iter->first);
676 dprintf(fd, " * timer id = %lu\n", iter->second->id);
677 dprintf(fd, " * timer type = %d\n", iter->second->type);
678 dprintf(fd, " * timer window Length = %lu\n", iter->second->windowLength);
679 dprintf(fd, " * timer interval = %lu\n", iter->second->interval);
680 dprintf(fd, " * timer uid = %d\n\n", iter->second->uid);
681 }
682 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
683 return true;
684 }
685
ShowTimerEntryById(int fd,uint64_t timerId)686 bool TimerManager::ShowTimerEntryById(int fd, uint64_t timerId)
687 {
688 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
689 std::lock_guard<std::mutex> lock(showTimerMutex_);
690 std::map<uint64_t, std::shared_ptr<TimerEntry>>::iterator iter = timerEntryMap_.find(timerId);
691 if (iter == timerEntryMap_.end()) {
692 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
693 return false;
694 } else {
695 dprintf(fd, " - dump timer number = %lu\n", iter->first);
696 dprintf(fd, " * timer id = %lu\n", iter->second->id);
697 dprintf(fd, " * timer type = %d\n", iter->second->type);
698 dprintf(fd, " * timer window Length = %lu\n", iter->second->windowLength);
699 dprintf(fd, " * timer interval = %lu\n", iter->second->interval);
700 dprintf(fd, " * timer uid = %d\n\n", iter->second->uid);
701 }
702 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
703 return true;
704 }
705
ShowTimerTriggerById(int fd,uint64_t timerId)706 bool TimerManager::ShowTimerTriggerById(int fd, uint64_t timerId)
707 {
708 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
709 std::lock_guard<std::mutex> lock(showTimerMutex_);
710 for (size_t i = 0; i < alarmBatches_.size(); i++) {
711 for (size_t j = 0; j < alarmBatches_[i]->Size(); j++) {
712 if (alarmBatches_[i]->Get(j)->id == timerId) {
713 dprintf(fd, " - dump timer id = %lu\n", alarmBatches_[i]->Get(j)->id);
714 dprintf(fd, " * timer trigger = %lld\n", alarmBatches_[i]->Get(j)->origWhen);
715 }
716 }
717 }
718 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
719 return true;
720 }
721 } // MiscServices
722 } // OHOS