• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &paras,
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